summaryrefslogtreecommitdiff
path: root/frontends/riscos
diff options
context:
space:
mode:
authorVincent Sanders <vince@kyllikki.org>2016-05-05 22:28:51 +0100
committerVincent Sanders <vince@kyllikki.org>2016-05-15 13:44:34 +0100
commitd21447d096a320a08b3efb2b8768fad0dcdcfd64 (patch)
tree1a83814b7c9e94b2f13c473261f23dd3a17dee64 /frontends/riscos
parent2cbb337756d9af5bda4d594964d446439f602551 (diff)
downloadnetsurf-d21447d096a320a08b3efb2b8768fad0dcdcfd64.tar.gz
netsurf-d21447d096a320a08b3efb2b8768fad0dcdcfd64.tar.bz2
move frontends into sub directory
Diffstat (limited to 'frontends/riscos')
-rw-r--r--frontends/riscos/401login.c236
-rw-r--r--frontends/riscos/Makefile153
-rw-r--r--frontends/riscos/Makefile.defaults37
-rw-r--r--frontends/riscos/assert.c44
-rw-r--r--frontends/riscos/bitmap.c876
-rw-r--r--frontends/riscos/bitmap.h116
-rw-r--r--frontends/riscos/buffer.c396
-rw-r--r--frontends/riscos/buffer.h31
-rw-r--r--frontends/riscos/configure.c410
-rw-r--r--frontends/riscos/configure.h34
-rw-r--r--frontends/riscos/configure/con_cache.c107
-rw-r--r--frontends/riscos/configure/con_connect.c220
-rw-r--r--frontends/riscos/configure/con_content.c107
-rw-r--r--frontends/riscos/configure/con_fonts.c209
-rw-r--r--frontends/riscos/configure/con_home.c118
-rw-r--r--frontends/riscos/configure/con_image.c269
-rw-r--r--frontends/riscos/configure/con_inter.c145
-rw-r--r--frontends/riscos/configure/con_language.c139
-rw-r--r--frontends/riscos/configure/con_secure.c83
-rw-r--r--frontends/riscos/configure/con_theme.c420
-rw-r--r--frontends/riscos/configure/configure.h43
-rw-r--r--frontends/riscos/content-handlers/artworks.c435
-rw-r--r--frontends/riscos/content-handlers/artworks.h42
-rw-r--r--frontends/riscos/content-handlers/awrender.s390
-rw-r--r--frontends/riscos/content-handlers/draw.c254
-rw-r--r--frontends/riscos/content-handlers/draw.h42
-rw-r--r--frontends/riscos/content-handlers/sprite.c266
-rw-r--r--frontends/riscos/content-handlers/sprite.h44
-rw-r--r--frontends/riscos/cookies.c385
-rw-r--r--frontends/riscos/cookies.h38
-rw-r--r--frontends/riscos/dialog.c816
-rw-r--r--frontends/riscos/dialog.h55
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Cache/!Boot,feb17
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Cache/!Help,feb2
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Cache/!Run,feb9
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Cache/!RunImage,ffbbin0 -> 2985 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Cache/!Sprites,ff9bin0 -> 864 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Cache/!Sprites22,ff9bin0 -> 2504 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Cache/Caches/Blank1
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/MultiError,ffbbin0 -> 24031 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/ResFind,ffbbin0 -> 1930 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/UK/!Meta9
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/UK/Help60
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/UK/Messages8
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/UK/Templates,fecbin0 -> 541 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/!Boot,feb5
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/!Help1
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/!Run,feb5
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/!Sprites,ff9bin0 -> 5780 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/!Sprites11,ff9bin0 -> 11132 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/!Sprites22,ff9bin0 -> 7324 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Acorn/Latin1bin0 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/CentEurobin0 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Cyrillicbin0 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Romanbin0 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Ukrainianbin0 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/BigFivebin0 -> 29516 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/C0/40[ISO646]bin0 -> 64 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/C1/43[IS6429]bin0 -> 64 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/40[646old]bin0 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/41[646-GB]bin0 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/42[646IRV]bin0 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/43[FinSwe]bin0 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/47[646-SE]bin0 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/48[646-SE]bin0 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/49[JS201K]1
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4A[JS201R]bin0 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4B[646-DE]bin0 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4C[646-PT]bin0 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/54[GB1988]bin0 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/56[Teltxt]bin0 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/59[646-IT]bin0 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/5A[646-ES]bin0 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/60[646-NO]bin0 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/66[646-FR]bin0 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/69[646-HU]bin0 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/6B[Arabic]bin0 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/6C[IS6937]bin0 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/7A[SerbCr]bin0 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/40[JS6226]bin0 -> 17672 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/41[GB2312]bin0 -> 17672 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/42[JIS208]bin0 -> 17672 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/43[KS1001]bin0 -> 17672 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/44[JIS212]bin0 -> 17672 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/47[CNS1]bin0 -> 17672 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/48[CNS2]bin0 -> 17672 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/49[CNS3]bin0 -> 17672 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4A[CNS4]bin0 -> 17672 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4B[CNS5]bin0 -> 17672 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4C[CNS6]bin0 -> 17672 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4D[CNS7]2
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/41[Lat1]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/42[Lat2]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/43[Lat3]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/44[Lat4]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/46[Greek]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/47[Arabic]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/48[Hebrew]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/4C[Cyrill]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/4D[Lat5]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/50[LatSup]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/52[IS6937]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/54[Thai]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/56[Lat6]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/58[L6Sami]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/59[Lat7]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5C[Welsh]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5D[Sami]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5E[Hebrew]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5F[Lat8]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/62[Lat9]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/66[Lat10]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/KOI8-Rbin0 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1250bin0 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1251bin0 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1252bin0 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1253bin0 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1254bin0 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1256bin0 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP866bin0 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP874bin0 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP932bin0 -> 996 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Files/Aliases303
-rw-r--r--frontends/riscos/distribution/!System/310/Modules/CryptRand,ffabin0 -> 15584 bytes
-rw-r--r--frontends/riscos/distribution/!System/310/Modules/Iconv,ffabin0 -> 66240 bytes
-rw-r--r--frontends/riscos/distribution/!System/310/Modules/Network/URI,ffabin0 -> 9188 bytes
-rwxr-xr-xfrontends/riscos/distribution/!System/310/Modules/SharedULib,ffabin0 -> 3116 bytes
-rw-r--r--frontends/riscos/distribution/!System/310/Modules/Tinct,ffabin0 -> 25680 bytes
-rw-r--r--frontends/riscos/distribution/3rdParty/AcornURI/!ReadMe34
-rw-r--r--frontends/riscos/distribution/3rdParty/AcornURI/Copying504
-rw-r--r--frontends/riscos/distribution/3rdParty/CryptRand/Copyright46
-rw-r--r--frontends/riscos/distribution/3rdParty/Iconv/ReadMe45
-rw-r--r--frontends/riscos/distribution/3rdParty/Iconv/doc/API132
-rw-r--r--frontends/riscos/distribution/3rdParty/Iconv/doc/ChangeLog114
-rw-r--r--frontends/riscos/distribution/3rdParty/Iconv/doc/Uni-iconv204
-rw-r--r--frontends/riscos/distribution/3rdParty/SharedULib/Copyright761
-rw-r--r--frontends/riscos/distribution/3rdParty/Tinct/!Help304
-rw-r--r--frontends/riscos/distribution/LeesMij73
-rw-r--r--frontends/riscos/distribution/ReadMe61
-rw-r--r--frontends/riscos/download.c1629
-rw-r--r--frontends/riscos/filetype.c352
-rw-r--r--frontends/riscos/filetype.h128
-rw-r--r--frontends/riscos/font.c598
-rw-r--r--frontends/riscos/font.h45
-rw-r--r--frontends/riscos/global_history.c413
-rw-r--r--frontends/riscos/global_history.h38
-rw-r--r--frontends/riscos/gui.c2522
-rw-r--r--frontends/riscos/gui.h271
-rw-r--r--frontends/riscos/gui/button_bar.c1229
-rw-r--r--frontends/riscos/gui/button_bar.h309
-rw-r--r--frontends/riscos/gui/progress_bar.c535
-rw-r--r--frontends/riscos/gui/progress_bar.h44
-rw-r--r--frontends/riscos/gui/status_bar.c625
-rw-r--r--frontends/riscos/gui/status_bar.h45
-rw-r--r--frontends/riscos/gui/throbber.c418
-rw-r--r--frontends/riscos/gui/throbber.h147
-rw-r--r--frontends/riscos/gui/url_bar.c1344
-rw-r--r--frontends/riscos/gui/url_bar.h329
-rw-r--r--frontends/riscos/help.c361
-rw-r--r--frontends/riscos/help.h33
-rw-r--r--frontends/riscos/history.c336
-rw-r--r--frontends/riscos/hotlist.c737
-rw-r--r--frontends/riscos/hotlist.h53
-rw-r--r--frontends/riscos/iconbar.c261
-rw-r--r--frontends/riscos/iconbar.h32
-rw-r--r--frontends/riscos/image.c219
-rw-r--r--frontends/riscos/image.h39
-rw-r--r--frontends/riscos/menus.c958
-rw-r--r--frontends/riscos/menus.h183
-rw-r--r--frontends/riscos/message.c247
-rw-r--r--frontends/riscos/message.h42
-rw-r--r--frontends/riscos/mouse.c282
-rw-r--r--frontends/riscos/mouse.h110
-rw-r--r--frontends/riscos/options.h68
-rw-r--r--frontends/riscos/oslib_pre7.h42
-rw-r--r--frontends/riscos/palettes.c321
-rw-r--r--frontends/riscos/palettes.h33
-rw-r--r--frontends/riscos/plotters.c525
-rw-r--r--frontends/riscos/print.c976
-rw-r--r--frontends/riscos/print.h33
-rw-r--r--frontends/riscos/query.c381
-rw-r--r--frontends/riscos/query.h53
-rw-r--r--frontends/riscos/save.c1401
-rw-r--r--frontends/riscos/save.h50
-rw-r--r--frontends/riscos/save_draw.c474
-rw-r--r--frontends/riscos/save_draw.h31
-rw-r--r--frontends/riscos/save_pdf.c60
-rw-r--r--frontends/riscos/save_pdf.h31
-rw-r--r--frontends/riscos/schedule.c163
-rw-r--r--frontends/riscos/scripts/Help12
-rw-r--r--frontends/riscos/scripts/Run109
-rw-r--r--frontends/riscos/search.c475
-rw-r--r--frontends/riscos/searchweb.c18
-rw-r--r--frontends/riscos/sslcert.c348
-rw-r--r--frontends/riscos/sslcert.h34
-rw-r--r--frontends/riscos/templates/de3845
-rw-r--r--frontends/riscos/templates/en3837
-rw-r--r--frontends/riscos/templates/fr3862
-rw-r--r--frontends/riscos/templates/nl3887
-rw-r--r--frontends/riscos/textarea.c1160
-rw-r--r--frontends/riscos/textarea.h50
-rw-r--r--frontends/riscos/textselection.c657
-rw-r--r--frontends/riscos/textselection.h53
-rw-r--r--frontends/riscos/theme.c741
-rw-r--r--frontends/riscos/theme.h109
-rw-r--r--frontends/riscos/theme_install.c237
-rw-r--r--frontends/riscos/tinct.h154
-rw-r--r--frontends/riscos/toolbar.c1788
-rw-r--r--frontends/riscos/toolbar.h542
-rw-r--r--frontends/riscos/treeview.c1279
-rw-r--r--frontends/riscos/treeview.h55
-rw-r--r--frontends/riscos/ucstables.c697
-rw-r--r--frontends/riscos/ucstables.h29
-rw-r--r--frontends/riscos/uri.c139
-rw-r--r--frontends/riscos/uri.h30
-rw-r--r--frontends/riscos/url_complete.c740
-rw-r--r--frontends/riscos/url_complete.h100
-rw-r--r--frontends/riscos/url_protocol.c226
-rw-r--r--frontends/riscos/url_protocol.h35
-rw-r--r--frontends/riscos/url_suggest.c239
-rw-r--r--frontends/riscos/url_suggest.h38
-rw-r--r--frontends/riscos/wimp.c1134
-rw-r--r--frontends/riscos/wimp.h83
-rw-r--r--frontends/riscos/wimp_event.c1814
-rw-r--r--frontends/riscos/wimp_event.h116
-rw-r--r--frontends/riscos/wimputils.h65
-rw-r--r--frontends/riscos/window.c5025
-rw-r--r--frontends/riscos/window.h46
228 files changed, 63025 insertions, 0 deletions
diff --git a/frontends/riscos/401login.c b/frontends/riscos/401login.c
new file mode 100644
index 000000000..e95a74809
--- /dev/null
+++ b/frontends/riscos/401login.c
@@ -0,0 +1,236 @@
+/*
+ * Copyright 2003 John M Bell <jmb202@ecs.soton.ac.uk>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "utils/config.h"
+
+#include <assert.h>
+#include <stdbool.h>
+#include <string.h>
+#include <oslib/wimp.h>
+
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "content/content.h"
+#include "content/hlcache.h"
+#include "content/urldb.h"
+#include "desktop/browser.h"
+
+#include "riscos/gui.h"
+#include "riscos/dialog.h"
+#include "riscos/wimp_event.h"
+
+#define ICON_401LOGIN_LOGIN 0
+#define ICON_401LOGIN_CANCEL 1
+#define ICON_401LOGIN_HOST 2
+#define ICON_401LOGIN_REALM 3
+#define ICON_401LOGIN_USERNAME 4
+#define ICON_401LOGIN_PASSWORD 5
+
+static void ro_gui_401login_close(wimp_w w);
+static bool ro_gui_401login_apply(wimp_w w);
+static void ro_gui_401login_open(nsurl *url, lwc_string *host,
+ const char *realm,
+ nserror (*cb)(bool proceed, void *pw), void *cbpw);
+
+static wimp_window *dialog_401_template;
+
+struct session_401 {
+ lwc_string *host; /**< Host for user display */
+ char *realm; /**< Authentication realm */
+ char uname[256]; /**< Buffer for username */
+ nsurl *url; /**< URL being fetched */
+ char pwd[256]; /**< Buffer for password */
+ nserror (*cb)(bool proceed, void *pw); /**< Continuation callback */
+ void *cbpw; /**< Continuation callback data */
+};
+
+
+/**
+ * Load the 401 login window template.
+ */
+
+void ro_gui_401login_init(void)
+{
+ dialog_401_template = ro_gui_dialog_load_template("login");
+}
+
+
+/**
+ * Open the login dialog
+ */
+void gui_401login_open(nsurl *url, const char *realm,
+ nserror (*cb)(bool proceed, void *pw), void *cbpw)
+{
+ lwc_string *host = nsurl_get_component(url, NSURL_HOST);
+ assert(host != NULL);
+
+ ro_gui_401login_open(url, host, realm, cb, cbpw);
+
+ lwc_string_unref(host);
+}
+
+
+/**
+ * Open a 401 login window.
+ */
+
+void ro_gui_401login_open(nsurl *url, lwc_string *host, const char *realm,
+ nserror (*cb)(bool proceed, void *pw), void *cbpw)
+{
+ struct session_401 *session;
+ wimp_w w;
+ const char *auth;
+
+ session = calloc(1, sizeof(struct session_401));
+ if (!session) {
+ ro_warn_user("NoMemory", 0);
+ return;
+ }
+
+ session->url = nsurl_ref(url);
+ if (realm == NULL)
+ realm = "Secure Area";
+ auth = urldb_get_auth_details(session->url, realm);
+ if (auth == NULL) {
+ session->uname[0] = '\0';
+ session->pwd[0] = '\0';
+ } else {
+ const char *pwd;
+ size_t pwd_len;
+
+ pwd = strchr(auth, ':');
+ assert(pwd && pwd < auth + sizeof(session->uname));
+ memcpy(session->uname, auth, pwd - auth);
+ session->uname[pwd - auth] = '\0';
+ ++pwd;
+ pwd_len = strlen(pwd);
+ assert(pwd_len < sizeof(session->pwd));
+ memcpy(session->pwd, pwd, pwd_len);
+ session->pwd[pwd_len] = '\0';
+ }
+ session->host = lwc_string_ref(host);
+ session->realm = strdup(realm);
+ session->cb = cb;
+ session->cbpw = cbpw;
+
+ if (!session->realm) {
+ nsurl_unref(session->url);
+ lwc_string_unref(session->host);
+ free(session);
+ ro_warn_user("NoMemory", 0);
+ return;
+ }
+
+ /* fill in download window icons */
+ dialog_401_template->icons[ICON_401LOGIN_HOST].data.
+ indirected_text.text =
+ (char *)lwc_string_data(session->host);
+ dialog_401_template->icons[ICON_401LOGIN_HOST].data.
+ indirected_text.size =
+ lwc_string_length(session->host) + 1;
+ dialog_401_template->icons[ICON_401LOGIN_REALM].data.
+ indirected_text.text = session->realm;
+ dialog_401_template->icons[ICON_401LOGIN_REALM].data.
+ indirected_text.size = strlen(session->realm) + 1;
+ dialog_401_template->icons[ICON_401LOGIN_USERNAME].data.
+ indirected_text.text = session->uname;
+ dialog_401_template->icons[ICON_401LOGIN_USERNAME].data.
+ indirected_text.size = sizeof(session->uname);
+ dialog_401_template->icons[ICON_401LOGIN_PASSWORD].data.
+ indirected_text.text = session->pwd;
+ dialog_401_template->icons[ICON_401LOGIN_PASSWORD].data.
+ indirected_text.size = sizeof(session->pwd);
+
+ /* create and open the window */
+ w = wimp_create_window(dialog_401_template);
+
+ ro_gui_wimp_event_register_text_field(w, ICON_401LOGIN_USERNAME);
+ ro_gui_wimp_event_register_text_field(w, ICON_401LOGIN_PASSWORD);
+ ro_gui_wimp_event_register_cancel(w, ICON_401LOGIN_CANCEL);
+ ro_gui_wimp_event_register_ok(w, ICON_401LOGIN_LOGIN,
+ ro_gui_401login_apply);
+ ro_gui_wimp_event_register_close_window(w, ro_gui_401login_close);
+ ro_gui_wimp_event_set_user_data(w, session);
+
+ ro_gui_dialog_open_persistent(NULL, w, false);
+}
+
+/**
+ * Handle closing of login dialog
+ */
+void ro_gui_401login_close(wimp_w w)
+{
+ os_error *error;
+ struct session_401 *session;
+
+ session = (struct session_401 *)ro_gui_wimp_event_get_user_data(w);
+
+ assert(session);
+
+ /* If ok didn't happen, send failure response */
+ if (session->cb != NULL)
+ session->cb(false, session->cbpw);
+
+ nsurl_unref(session->url);
+ lwc_string_unref(session->host);
+ free(session->realm);
+ free(session);
+
+ error = xwimp_delete_window(w);
+ if (error) {
+ LOG("xwimp_delete_window: 0x%x:%s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+ ro_gui_wimp_event_finalise(w);
+}
+
+
+/* Login Clicked -> create a new fetch request, specifying uname & pwd
+ * CURLOPT_USERPWD takes a string "username:password"
+ */
+bool ro_gui_401login_apply(wimp_w w)
+{
+ struct session_401 *session;
+ char *auth;
+
+ session = (struct session_401 *)ro_gui_wimp_event_get_user_data(w);
+
+ assert(session);
+
+ auth = malloc(strlen(session->uname) + strlen(session->pwd) + 2);
+ if (!auth) {
+ LOG("calloc failed");
+ ro_warn_user("NoMemory", 0);
+ return false;
+ }
+
+ sprintf(auth, "%s:%s", session->uname, session->pwd);
+
+ urldb_set_auth_details(session->url, session->realm, auth);
+
+ free(auth);
+
+ session->cb(true, session->cbpw);
+
+ /* Flag that we sent response by invalidating callback details */
+ session->cb = NULL;
+ session->cbpw = NULL;
+
+ return true;
+}
+
diff --git a/frontends/riscos/Makefile b/frontends/riscos/Makefile
new file mode 100644
index 000000000..6ed076800
--- /dev/null
+++ b/frontends/riscos/Makefile
@@ -0,0 +1,153 @@
+#
+# Makefile for NetSurf RISC OS target
+#
+# This file is part of NetSurf
+
+# ----------------------------------------------------------------------------
+# RISC OS target setup
+# ----------------------------------------------------------------------------
+
+$(eval $(call pkg_config_find_and_add,libcares,Cares))
+
+$(eval $(call feature_enabled,DRAW,-DWITH_DRAW,,Drawfile rendering))
+$(eval $(call feature_enabled,SPRITE,-DWITH_SPRITE,,Sprite rendering))
+$(eval $(call feature_enabled,ARTWORKS,-DWITH_ARTWORKS,,ArtWorks rendering))
+$(eval $(call feature_enabled,DRAW_EXPORT,-DWITH_DRAW_EXPORT,-lpencil,Drawfile export))
+
+
+TPD_RISCOS = $(foreach TPL,$(notdir $(TPL_RISCOS)), \
+ !NetSurf/Resources/$(TPL)/Templates$(TPLEXT))
+
+RESOURCES = $(TPD_RISCOS)
+
+CFLAGS += -Driscos -std=c99 -D_BSD_SOURCE -D_POSIX_C_SOURCE \
+ -mpoke-function-name -fno-strict-aliasing
+
+CFLAGS += -I$(GCCSDK_INSTALL_ENV)/include
+ifeq ($(HOST),riscos)
+ CFLAGS += -I<OSLib$$Dir> -mthrowback
+endif
+ASFLAGS += -xassembler-with-cpp -I. -I$(GCCSDK_INSTALL_ENV)/include
+LDFLAGS += -L$(GCCSDK_INSTALL_ENV)/lib -lrufl
+ifeq ($(HOST),riscos)
+ LDFLAGS += -LOSLib: -lOSLib32
+else
+ LDFLAGS += -lOSLib32
+ ifeq ($(SUBTARGET),-elf)
+ # Go for static builds & AIF binary at the moment:
+ CFLAGS += -static
+ LDFLAGS += -static
+ EXEEXT := ,ff8
+ endif
+endif
+
+# ----------------------------------------------------------------------------
+# Source file setup
+# ----------------------------------------------------------------------------
+
+# S_RISCOS are sources purely for the RISC OS build
+S_FRONTEND := 401login.c assert.c bitmap.c buffer.c cookies.c configure.c \
+ dialog.c download.c filetype.c font.c \
+ global_history.c gui.c help.c history.c hotlist.c iconbar.c \
+ image.c menus.c message.c mouse.c palettes.c plotters.c \
+ print.c query.c save.c save_draw.c save_pdf.c schedule.c \
+ search.c searchweb.c sslcert.c textarea.c \
+ textselection.c theme.c theme_install.c toolbar.c \
+ treeview.c ucstables.c uri.c url_complete.c url_protocol.c \
+ url_suggest.c wimp.c wimp_event.c window.c \
+ $(addprefix content-handlers/,artworks.c awrender.s draw.c \
+ sprite.c) \
+ $(addprefix gui/,button_bar.c progress_bar.c status_bar.c \
+ throbber.c url_bar.c) \
+ $(addprefix configure/,con_cache.c con_connect.c con_content.c \
+ con_fonts.c con_home.c con_image.c con_inter.c con_language.c \
+ con_secure.c con_theme.c)
+
+# This is the final source build list
+# Note this is deliberately *not* expanded here as common and image
+# are not yet available
+SOURCES = $(S_COMMON) $(S_IMAGE) $(S_BROWSER) $(S_FRONTEND)
+
+EXETARGET := !NetSurf/!RunImage$(EXEEXT)
+
+# The filter and target for split messages
+MESSAGES_FILTER=ro
+
+!NetSurf/!Run$(RUNEXT): $(FRONTEND_SOURCE_DIR)/scripts/Run $(EXETARGET)
+ $(VQ)echo " MAKERUN: $@"
+ $(Q)$(MAKERUN) $(EXETARGET) $< $@
+
+!NetSurf/!Help$(RUNEXT): $(FRONTEND_SOURCE_DIR)/scripts/Help
+ $(VQ)echo " CP: $@"
+ $(Q)cp $< $@
+
+$(DEPROOT)/squeeze.d: $(EXETARGET)
+ $(VQ)echo " SQUEEZE: $<"
+ $(Q)$(SQUEEZE) -f -v $(EXETARGET)
+ $(Q)$(TOUCH) $@
+
+POSTEXES += !NetSurf/!Run$(RUNEXT) !NetSurf/!Help$(RUNEXT) $(DEPROOT)/squeeze.d
+
+
+clean-run:
+ $(VQ)echo " CLEAN: !NetSurf/!Run$(RUNEXT)"
+ $(Q) $(RM) !NetSurf/!Run$(RUNEXT)
+
+clean-help:
+ $(VQ)echo " CLEAN: !NetSurf/!Help$(RUNEXT)"
+ $(Q) $(RM) !NetSurf/!Help$(RUNEXT)
+
+CLEANS += clean-run clean-help
+
+# ----------------------------------------------------------------------------
+# Template targets
+# ----------------------------------------------------------------------------
+
+# Template objects
+TPL_RISCOS := de en fr nl # TODO: It'd be nice to auto-detect these
+TPL_RISCOS := $(addprefix $(FRONTEND_SOURCE_DIR)/templates/,$(TPL_RISCOS))
+
+# Template target creation macro
+define compile_template
+!NetSurf/Resources/$(1)/Templates$$(TPLEXT): $(2)
+ $$(VQ)echo "TEMPLATE: $(2)"
+ $$(Q)mkdir -p !NetSurf/Resources/$(1)
+ $$(Q)$$(CC) -x c -E -P $$(CFLAGS) $(2) | $$(CCRES) - $$@
+
+CLEAN_TEMPLATES += !NetSurf/Resources/$(1)/Templates$$(TPLEXT)
+
+endef
+
+$(eval $(foreach TPL,$(TPL_RISCOS), \
+ $(call compile_template,$(notdir $(TPL)),$(TPL))))
+
+clean-templates:
+ $(VQ)echo " CLEAN: $(CLEAN_TEMPLATES)"
+ $(Q)$(RM) $(CLEAN_TEMPLATES)
+CLEANS += clean-templates
+
+
+# ----------------------------------------------------------------------------
+# Install target
+# ----------------------------------------------------------------------------
+
+install-riscos:
+
+# ----------------------------------------------------------------------------
+# Package target
+# ----------------------------------------------------------------------------
+
+package-riscos: netsurf.zip
+
+netsurf.zip: $(EXETARGET)
+ $(eval $@_TMPDIR := $(shell mktemp -d))
+ $(Q) $(RM) $@
+ $(Q) rsync --archive --verbose $(CURDIR)/!NetSurf $($@_TMPDIR)
+ $(Q) $(CURDIR)/utils/git-date.sh $(FRONTEND_SOURCE_DIR)/distribution
+ $(Q) rsync --archive --verbose $(FRONTEND_SOURCE_DIR)/distribution/!Boot $($@_TMPDIR)
+ $(Q) rsync --archive --verbose $(FRONTEND_SOURCE_DIR)/distribution/!System $($@_TMPDIR)
+ $(Q) rsync --archive --verbose $(FRONTEND_SOURCE_DIR)/distribution/3rdParty $($@_TMPDIR)
+ $(Q) cp $(FRONTEND_SOURCE_DIR)/distribution/ReadMe $($@_TMPDIR)
+ $(Q) cp $(FRONTEND_SOURCE_DIR)/distribution/LeesMij $($@_TMPDIR)
+ $(Q) cd $($@_TMPDIR) && /opt/netsurf/arm-unknown-riscos/env/bin/zip -9vr\, $(CURDIR)/$@ *
+ $(Q) $(RM) -rf $($@_TMPDIR)
diff --git a/frontends/riscos/Makefile.defaults b/frontends/riscos/Makefile.defaults
new file mode 100644
index 000000000..aed361631
--- /dev/null
+++ b/frontends/riscos/Makefile.defaults
@@ -0,0 +1,37 @@
+# ----------------------------------------------------------------------------
+# RISC OS-specific options
+# ----------------------------------------------------------------------------
+
+# Enable NetSurf's use of libsvgtiny for displaying SVGs
+# Valid options: YES, NO
+NETSURF_USE_NSSVG := YES
+
+# Enable NetSurf's support for displaying RISC OS Draw files
+# Valid options: YES, NO
+NETSURF_USE_DRAW := YES
+
+# Enable NetSurf's support for displaying RISC OS Sprites
+# Valid options: YES, NO
+NETSURF_USE_SPRITE := YES
+
+# Enable NetSurf's use of librosprite for displaying RISC OS Sprites
+# Valid options: YES, NO, AUTO
+NETSURF_USE_ROSPRITE := NO
+
+# Enable NetSurf's use of AWRender for displaying ArtWorks files
+# Valid options: YES, NO
+NETSURF_USE_ARTWORKS := YES
+
+# Enable NetSurf's support for the Acorn plugin protocol
+# Valid options: YES, NO
+NETSURF_USE_PLUGINS := NO
+
+# Enable NetSurf's use of pencil for Drawfile export
+# Valid options: YES, NO
+NETSURF_USE_DRAW_EXPORT := YES
+
+# Enable building the source object cache filesystem based backing store.
+NETSURF_FS_BACKING_STORE := YES
+
+# Optimisation levels
+CFLAGS += -O2
diff --git a/frontends/riscos/assert.c b/frontends/riscos/assert.c
new file mode 100644
index 000000000..50b8f5d54
--- /dev/null
+++ b/frontends/riscos/assert.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2005 James Bursa <bursa@users.sourceforge.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Assert reporting (RISC OS implementation).
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "oslib/wimp.h"
+
+
+/**
+ * Report an assert() failure and exit.
+ */
+
+void __assert2(const char *expr, const char *function, const char *file,
+ int line)
+{
+ fprintf(stderr, "\n\"%s\", line %d: %s%sAssertion failed: %s\n",
+ file, line,
+ function ? function : "",
+ function ? ": " : "",
+ expr);
+ fflush(stderr);
+
+ abort();
+}
diff --git a/frontends/riscos/bitmap.c b/frontends/riscos/bitmap.c
new file mode 100644
index 000000000..cc4be590c
--- /dev/null
+++ b/frontends/riscos/bitmap.c
@@ -0,0 +1,876 @@
+/*
+ * Copyright 2004 James Bursa <bursa@users.sourceforge.net>
+ * Copyright 2005 Richard Wilson <info@tinct.net>
+ * Copyright 2008 Adrian Lees <adrianl@users.sourceforge.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * RISC OS implementation of bitmap operations.
+ *
+ * This implements the interface given by image/bitmap.h using RISC OS
+ * sprites.
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <string.h>
+#include <swis.h>
+#include <rufl.h>
+#include <unixlib/local.h>
+#include <oslib/colourtrans.h>
+#include <oslib/osfile.h>
+#include <oslib/osfind.h>
+#include <oslib/osgbpb.h>
+#include <oslib/osspriteop.h>
+#include <oslib/wimp.h>
+
+#include "utils/nsoption.h"
+#include "utils/filename.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "desktop/plotters.h"
+#include "content/content.h"
+#include "image/bitmap.h"
+
+#include "riscos/gui.h"
+#include "riscos/image.h"
+#include "riscos/palettes.h"
+#include "riscos/content-handlers/sprite.h"
+#include "riscos/tinct.h"
+#include "riscos/bitmap.h"
+
+/** Colour in the overlay sprite that allows the bitmap to show through */
+#define OVERLAY_INDEX 0xfe
+
+/** Size of buffer used when constructing mask data to be saved */
+#define SAVE_CHUNK_SIZE 4096
+
+/**
+ * Whether we can use 32bpp sprites
+ */
+static int thumbnail_32bpp_available = -1;
+
+/**
+ * Sprite output context saving
+ */
+struct thumbnail_save_area {
+ osspriteop_save_area *save_area;
+ int context1;
+ int context2;
+ int context3;
+};
+
+/**
+ * Initialise a bitmaps sprite area.
+ *
+ * \param bitmap the bitmap to initialise
+ * \return true if bitmap initialised else false.
+ */
+
+static bool bitmap_initialise(struct bitmap *bitmap)
+{
+ unsigned int area_size;
+ osspriteop_area *sprite_area;
+ osspriteop_header *sprite;
+
+ assert(!bitmap->sprite_area);
+
+ area_size = 16 + 44 + bitmap->width * bitmap->height * 4;
+ if (bitmap->state & BITMAP_CLEAR_MEMORY)
+ bitmap->sprite_area = calloc(1, area_size);
+ else
+ bitmap->sprite_area = malloc(area_size);
+
+ if (!bitmap->sprite_area)
+ return false;
+
+ /* area control block */
+ sprite_area = bitmap->sprite_area;
+ sprite_area->size = area_size;
+ sprite_area->sprite_count = 1;
+ sprite_area->first = 16;
+ sprite_area->used = area_size;
+
+ /* sprite control block */
+ sprite = (osspriteop_header *) (sprite_area + 1);
+ sprite->size = area_size - 16;
+ memset(sprite->name, 0x00, 12);
+ strncpy(sprite->name, "bitmap", 12);
+ sprite->width = bitmap->width - 1;
+ sprite->height = bitmap->height - 1;
+ sprite->left_bit = 0;
+ sprite->right_bit = 31;
+ sprite->image = sprite->mask = 44;
+ sprite->mode = tinct_SPRITE_MODE;
+
+ return true;
+}
+
+
+/* exported interface documented in riscos/bitmap.h */
+void *riscos_bitmap_create(int width, int height, unsigned int state)
+{
+ struct bitmap *bitmap;
+
+ if (width == 0 || height == 0)
+ return NULL;
+
+ bitmap = calloc(1, sizeof(struct bitmap));
+ if (!bitmap)
+ return NULL;
+ bitmap->width = width;
+ bitmap->height = height;
+ bitmap->state = state;
+
+ return bitmap;
+}
+
+
+/* exported interface documented in riscos/bitmap.h */
+unsigned char *riscos_bitmap_get_buffer(void *vbitmap)
+{
+ struct bitmap *bitmap = (struct bitmap *) vbitmap;
+ assert(bitmap);
+
+ /* dynamically create the buffer */
+ if (bitmap->sprite_area == NULL) {
+ if (!bitmap_initialise(bitmap))
+ return NULL;
+ }
+
+ /* image data area should exist */
+ if (bitmap->sprite_area)
+ return ((unsigned char *) (bitmap->sprite_area)) + 16 + 44;
+
+ return NULL;
+}
+
+
+/**
+ * Sets whether a bitmap should be plotted opaque
+ *
+ * \param vbitmap a bitmap, as returned by bitmap_create()
+ * \param opaque whether the bitmap should be plotted opaque
+ */
+static void bitmap_set_opaque(void *vbitmap, bool opaque)
+{
+ struct bitmap *bitmap = (struct bitmap *) vbitmap;
+ assert(bitmap);
+
+ if (opaque)
+ bitmap->state |= BITMAP_OPAQUE;
+ else
+ bitmap->state &= ~BITMAP_OPAQUE;
+}
+
+
+/**
+ * Find the width of a pixel row in bytes.
+ *
+ * \param vbitmap A bitmap, as returned by riscos_bitmap_create()
+ * \return width of a pixel row in the bitmap
+ */
+static size_t bitmap_get_rowstride(void *vbitmap)
+{
+ struct bitmap *bitmap = (struct bitmap *) vbitmap;
+ return bitmap->width * 4;
+}
+
+
+/**
+ * Tests whether a bitmap has an opaque alpha channel
+ *
+ * \param vbitmap a bitmap, as returned by bitmap_create()
+ * \return whether the bitmap is opaque
+ */
+static bool bitmap_test_opaque(void *vbitmap)
+{
+ struct bitmap *bitmap = (struct bitmap *) vbitmap;
+ unsigned char *sprite;
+ unsigned int width, height, size;
+ osspriteop_header *sprite_header;
+ unsigned *p, *ep;
+
+ assert(bitmap);
+
+ sprite = riscos_bitmap_get_buffer(bitmap);
+ if (!sprite)
+ return false;
+
+ width = bitmap_get_rowstride(bitmap);
+
+ sprite_header = (osspriteop_header *) (bitmap->sprite_area + 1);
+
+ height = (sprite_header->height + 1);
+
+ size = width * height;
+
+ p = (void *) sprite;
+
+ ep = (void *) (sprite + (size & ~31));
+ while (p < ep) {
+ /* \todo prefetch(p, 128)? */
+ if (((p[0] & p[1] & p[2] & p[3] & p[4] & p[5] & p[6] & p[7])
+ & 0xff000000U) != 0xff000000U)
+ return false;
+ p += 8;
+ }
+
+ ep = (void *) (sprite + size);
+ while (p < ep) {
+ if ((*p & 0xff000000U) != 0xff000000U) return false;
+ p++;
+ }
+
+ return true;
+}
+
+
+/* exported interface documented in riscos/bitmap.h */
+bool riscos_bitmap_get_opaque(void *vbitmap)
+{
+ struct bitmap *bitmap = (struct bitmap *) vbitmap;
+ assert(bitmap);
+ return (bitmap->state & BITMAP_OPAQUE);
+}
+
+
+/* exported interface documented in riscos/bitmap.h */
+void riscos_bitmap_destroy(void *vbitmap)
+{
+ struct bitmap *bitmap = (struct bitmap *) vbitmap;
+
+ assert(bitmap);
+
+ /* destroy bitmap */
+ if (bitmap->sprite_area) {
+ free(bitmap->sprite_area);
+ }
+
+ free(bitmap);
+}
+
+
+/* exported interface documented in riscos/bitmap.h */
+bool riscos_bitmap_save(void *vbitmap, const char *path, unsigned flags)
+{
+ struct bitmap *bitmap = (struct bitmap *) vbitmap;
+ os_error *error;
+
+ if (bitmap == NULL) {
+ ro_warn_user("SaveError", messages_get("SprIsNull"));
+ return false;
+ }
+
+ if (!bitmap->sprite_area) {
+ riscos_bitmap_get_buffer(bitmap);
+ }
+ if (!bitmap->sprite_area)
+ return false;
+
+ if (riscos_bitmap_get_opaque(bitmap)) {
+ error = xosspriteop_save_sprite_file(osspriteop_USER_AREA,
+ (bitmap->sprite_area), path);
+ if (error) {
+ LOG("xosspriteop_save_sprite_file: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("SaveError", error->errmess);
+ return false;
+ }
+ return true;
+ } else {
+ /* to make the saved sprite useful we must convert from 'Tinct'
+ * format to either a bi-level mask or a Select-style full
+ * alpha channel */
+ osspriteop_area *area = bitmap->sprite_area;
+ osspriteop_header *hdr = (void *) ((char *) area + area->first);
+ unsigned width = hdr->width + 1, height = hdr->height + 1;
+ unsigned image_size = height * width * 4;
+ unsigned char *chunk_buf;
+ unsigned *p, *elp, *eip;
+ unsigned mask_size;
+ size_t chunk_pix;
+ struct {
+ osspriteop_area area;
+ osspriteop_header hdr;
+ } file_hdr;
+ os_fw fw;
+
+ /* we only support 32bpp sprites */
+ if ((((unsigned)hdr->mode >> 27)&15) != 6) {
+ assert(!"Unsupported sprite format in bitmap_save");
+ return false;
+ }
+
+ chunk_buf = malloc(SAVE_CHUNK_SIZE);
+ if (!chunk_buf) {
+ ro_warn_user("NoMemory", NULL);
+ return false;
+ }
+
+ file_hdr.area = *area;
+ file_hdr.hdr = *hdr;
+
+ if (flags & BITMAP_SAVE_FULL_ALPHA) {
+ mask_size = ((width + 3) & ~3) * height;
+ chunk_pix = SAVE_CHUNK_SIZE;
+ file_hdr.hdr.mode = (os_mode)((unsigned)file_hdr.hdr.mode
+ | (1U<<31));
+ } else {
+ mask_size = (((width + 31) & ~31)/8) * height;
+ chunk_pix = SAVE_CHUNK_SIZE<<3;
+ file_hdr.hdr.mode = (os_mode)((unsigned)file_hdr.hdr.mode
+ & ~(1U<<31));
+ }
+
+ file_hdr.area.sprite_count = 1;
+ file_hdr.area.first = sizeof(file_hdr.area);
+ file_hdr.area.used = sizeof(file_hdr) + image_size + mask_size;
+
+ file_hdr.hdr.image = sizeof(file_hdr.hdr);
+ file_hdr.hdr.mask = file_hdr.hdr.image + image_size;
+ file_hdr.hdr.size = file_hdr.hdr.mask + mask_size;
+
+ error = xosfind_openoutw(0, path, NULL, &fw);
+ if (error) {
+ LOG("xosfind_openoutw: 0x%x: %s", error->errnum, error->errmess);
+ free(chunk_buf);
+ ro_warn_user("SaveError", error->errmess);
+ return false;
+ }
+
+ p = (void *) ((char *) hdr + hdr->image);
+
+ /* write out the area header, sprite header and image data */
+ error = xosgbpb_writew(fw, (byte*)&file_hdr + 4,
+ sizeof(file_hdr)-4, NULL);
+ if (!error)
+ error = xosgbpb_writew(fw, (byte*)p, image_size, NULL);
+ if (error) {
+ LOG("xosgbpb_writew: 0x%x: %s", error->errnum, error->errmess);
+ free(chunk_buf);
+ xosfind_closew(fw);
+ ro_warn_user("SaveError", error->errmess);
+ return false;
+ }
+
+ /* then write out the mask data in chunks */
+ eip = p + (width * height); /* end of image */
+ elp = p + width; /* end of line */
+
+ while (p < eip) {
+ unsigned char *dp = chunk_buf;
+ unsigned *ep = p + chunk_pix;
+ if (ep > elp) ep = elp;
+
+ if (flags & BITMAP_SAVE_FULL_ALPHA) {
+ while (p < ep) {
+ *dp++ = ((unsigned char*)p)[3];
+ p++;
+ }
+ }
+ else {
+ unsigned char mb = 0;
+ int msh = 0;
+ while (p < ep) {
+ if (((unsigned char*)p)[3]) mb |= (1 << msh);
+ if (++msh >= 8) {
+ *dp++ = mb;
+ msh = 0;
+ mb = 0;
+ }
+ p++;
+ }
+ if (msh > 0) *dp++ = mb;
+ }
+
+ if (p >= elp) { /* end of line yet? */
+ /* align to word boundary */
+ while ((int)dp & 3) *dp++ = 0;
+ /* advance end of line pointer */
+ elp += width;
+ }
+ error = xosgbpb_writew(fw, (byte*)chunk_buf, dp-chunk_buf, NULL);
+ if (error) {
+ LOG("xosgbpb_writew: 0x%x: %s", error->errnum, error->errmess);
+ free(chunk_buf);
+ xosfind_closew(fw);
+ ro_warn_user("SaveError", error->errmess);
+ return false;
+ }
+ }
+
+ error = xosfind_closew(fw);
+ if (error) {
+ LOG("xosfind_closew: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("SaveError", error->errmess);
+ }
+
+ error = xosfile_set_type(path, osfile_TYPE_SPRITE);
+ if (error) {
+ LOG("xosfile_set_type: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("SaveError", error->errmess);
+ }
+
+ free(chunk_buf);
+ return true;
+ }
+}
+
+
+/**
+ * The bitmap image has changed, so flush any persistent cache.
+ *
+ * \param vbitmap a bitmap, as returned by bitmap_create()
+ */
+static void bitmap_modified(void *vbitmap)
+{
+ struct bitmap *bitmap = (struct bitmap *) vbitmap;
+ bitmap->state |= BITMAP_MODIFIED;
+}
+
+
+/**
+ * Get the width of a bitmap.
+ *
+ * \param vbitmap A bitmap, as returned by bitmap_create()
+ * \return The bitmaps width in pixels.
+ */
+static int bitmap_get_width(void *vbitmap)
+{
+ struct bitmap *bitmap = (struct bitmap *) vbitmap;
+ return bitmap->width;
+}
+
+
+/**
+ * Get the height of a bitmap.
+ *
+ * \param vbitmap A bitmap, as returned by bitmap_create()
+ * \return The bitmaps height in pixels.
+ */
+static int bitmap_get_height(void *vbitmap)
+{
+ struct bitmap *bitmap = (struct bitmap *) vbitmap;
+ return bitmap->height;
+}
+
+
+/**
+ * Find the bytes per pixel of a bitmap
+ *
+ * \param vbitmap a bitmap, as returned by bitmap_create()
+ * \return bytes per pixel
+ */
+static size_t bitmap_get_bpp(void *vbitmap)
+{
+ struct bitmap *bitmap = (struct bitmap *)vbitmap;
+ assert(bitmap);
+ return 4;
+}
+
+
+/* exported interface documented in riscos/bitmap.h */
+void riscos_bitmap_overlay_sprite(struct bitmap *bitmap,
+ const osspriteop_header *s)
+{
+ const os_colour *palette;
+ const byte *sp, *mp;
+ bool masked = false;
+ bool alpha = false;
+ os_error *error;
+ int dp_offset;
+ int sp_offset;
+ unsigned *dp;
+ int x, y;
+ int w, h;
+
+ assert(sprite_bpp(s) == 8);
+
+ if ((unsigned)s->mode & 0x80000000U)
+ alpha = true;
+
+ error = xosspriteop_read_sprite_info(osspriteop_PTR,
+ (osspriteop_area *)0x100,
+ (osspriteop_id)s,
+ &w, &h, NULL, NULL);
+ if (error) {
+ LOG("xosspriteop_read_sprite_info: 0x%x:%s", error->errnum, error->errmess);
+ return;
+ }
+ sp_offset = ((s->width + 1) * 4) - w;
+
+ if (w > bitmap->width)
+ w = bitmap->width;
+ if (h > bitmap->height)
+ h = bitmap->height;
+
+ dp_offset = bitmap_get_rowstride(bitmap) / 4;
+
+ dp = (void*)riscos_bitmap_get_buffer(bitmap);
+ if (!dp)
+ return;
+ sp = (byte*)s + s->image;
+ mp = (byte*)s + s->mask;
+
+ sp += s->left_bit / 8;
+ mp += s->left_bit / 8;
+
+ if (s->image > (int)sizeof(*s))
+ palette = (os_colour*)(s + 1);
+ else
+ palette = default_palette8;
+
+ if (s->mask != s->image) {
+ masked = true;
+ bitmap_set_opaque(bitmap, false);
+ }
+
+ /* (partially-)transparent pixels in the overlayed sprite retain
+ * their transparency in the output bitmap; opaque sprite pixels
+ * are also propagated to the bitmap, except those which are the
+ * OVERLAY_INDEX colour which allow the original bitmap contents to
+ * show through */
+ for (y = 0; y < h; y++) {
+ unsigned *sdp = dp;
+ for(x = 0; x < w; x++) {
+ os_colour d = ((unsigned)palette[(*sp) << 1]) >> 8;
+ if (*sp++ == OVERLAY_INDEX)
+ d = *dp;
+ if (masked) {
+ if (alpha)
+ d |= ((*mp << 24) ^ 0xff000000U);
+ else if (*mp)
+ d |= 0xff000000U;
+ }
+ *dp++ = d;
+ mp++;
+ }
+ dp = sdp + dp_offset;
+ sp += sp_offset;
+ mp += sp_offset;
+ }
+}
+
+
+/**
+ * Creates an 8bpp canvas.
+ *
+ * \param bitmap the bitmap to clone the size of
+ * \return a sprite area containing an 8bpp sprite
+ */
+static osspriteop_area *thumbnail_create_8bpp(struct bitmap *bitmap)
+{
+ unsigned image_size = ((bitmap->width + 3) & ~3) * bitmap->height;
+ bool opaque = riscos_bitmap_get_opaque(bitmap);
+ osspriteop_header *sprite_header = NULL;
+ osspriteop_area *sprite_area = NULL;
+ unsigned area_size;
+
+ /* clone the sprite */
+ area_size = sizeof(osspriteop_area) +
+ sizeof(osspriteop_header) +
+ image_size +
+ 2048;
+
+ if (!opaque) area_size += image_size;
+
+ sprite_area = (osspriteop_area *)malloc(area_size);
+ if (!sprite_area) {
+ LOG("no memory for malloc()");
+ return NULL;
+ }
+ sprite_area->size = area_size;
+ sprite_area->sprite_count = 1;
+ sprite_area->first = 16;
+ sprite_area->used = area_size;
+ sprite_header = (osspriteop_header *)(sprite_area + 1);
+ sprite_header->size = area_size - sizeof(osspriteop_area);
+ memset(sprite_header->name, 0x00, 12);
+ strcpy(sprite_header->name, "bitmap");
+ sprite_header->left_bit = 0;
+ sprite_header->height = bitmap->height - 1;
+ sprite_header->mode = os_MODE8BPP90X90;
+ sprite_header->right_bit = ((bitmap->width << 3) - 1) & 31;
+ sprite_header->width = ((bitmap->width + 3) >> 2) - 1;
+ sprite_header->image = sizeof(osspriteop_header) + 2048;
+ sprite_header->mask = sizeof(osspriteop_header) + 2048;
+ if (!opaque) sprite_header->mask += image_size;
+
+ /* create the palette. we don't read the necessary size like
+ * we really should as we know it's going to have 256 entries
+ * of 8 bytes = 2048. */
+ xcolourtrans_read_palette((osspriteop_area *)os_MODE8BPP90X90,
+ (osspriteop_id)0,
+ (os_palette *)(sprite_header + 1), 2048,
+ (colourtrans_palette_flags)(1 << 1), 0);
+ return sprite_area;
+}
+
+
+/**
+ * Switches output to the specified sprite and returns the previous context.
+ */
+static struct thumbnail_save_area*
+thumbnail_switch_output(osspriteop_area *sprite_area,
+ osspriteop_header *sprite_header)
+{
+ struct thumbnail_save_area *save_area;
+ int size;
+
+ /* create a save area */
+ save_area = calloc(sizeof(struct thumbnail_save_area), 1);
+ if (save_area == NULL) return NULL;
+
+ /* allocate OS_SpriteOp save area */
+ if (xosspriteop_read_save_area_size(osspriteop_PTR, sprite_area,
+ (osspriteop_id)sprite_header, &size)) {
+ free(save_area);
+ return NULL;
+ }
+
+ /* create the save area */
+ save_area->save_area = malloc((unsigned)size);
+ if (save_area->save_area == NULL) {
+ free(save_area);
+ return NULL;
+ }
+ save_area->save_area->a[0] = 0;
+
+ /* switch output to sprite */
+ if (xosspriteop_switch_output_to_sprite(osspriteop_PTR, sprite_area,
+ (osspriteop_id)sprite_header, save_area->save_area,
+ 0, &save_area->context1, &save_area->context2,
+ &save_area->context3)) {
+ free(save_area->save_area);
+ free(save_area);
+ return NULL;
+ }
+ return save_area;
+}
+
+
+/**
+ * Restores output to the specified context, and destroys it.
+ */
+static void thumbnail_restore_output(struct thumbnail_save_area *save_area)
+{
+ /* we don't care if we err, as there's nothing we can do about it */
+ xosspriteop_switch_output_to_sprite(osspriteop_PTR,
+ (osspriteop_area *)save_area->context1,
+ (osspriteop_id)save_area->context2,
+ (osspriteop_save_area *)save_area->context3,
+ 0, 0, 0, 0);
+ free(save_area->save_area);
+ free(save_area);
+}
+
+
+/**
+ * Convert a bitmap to 8bpp.
+ *
+ * \param bitmap the bitmap to convert
+ * \return a sprite area containing an 8bpp sprite
+ */
+osspriteop_area *riscos_bitmap_convert_8bpp(struct bitmap *bitmap)
+{
+ struct thumbnail_save_area *save_area;
+ osspriteop_area *sprite_area = NULL;
+ osspriteop_header *sprite_header = NULL;
+
+ sprite_area = thumbnail_create_8bpp(bitmap);
+ if (!sprite_area)
+ return NULL;
+ sprite_header = (osspriteop_header *)(sprite_area + 1);
+
+
+ /* switch output and redraw */
+ save_area = thumbnail_switch_output(sprite_area, sprite_header);
+ if (save_area == NULL) {
+ if (thumbnail_32bpp_available != 1)
+ free(sprite_area);
+ return false;
+ }
+ _swix(Tinct_Plot, _IN(2) | _IN(3) | _IN(4) | _IN(7),
+ (osspriteop_header *)(bitmap->sprite_area + 1),
+ 0, 0,
+ tinct_ERROR_DIFFUSE);
+ thumbnail_restore_output(save_area);
+
+ if (sprite_header->image != sprite_header->mask) {
+ /* build the sprite mask from the alpha channel */
+ void *buf = riscos_bitmap_get_buffer(bitmap);
+ unsigned *dp = (unsigned *) buf;
+ if (!dp)
+ return sprite_area;
+ int w = bitmap_get_width(bitmap);
+ int h = bitmap_get_height(bitmap);
+ int dp_offset = bitmap_get_rowstride(bitmap) / 4 - w;
+ int mp_offset = ((sprite_header->width + 1) * 4) - w;
+ byte *mp = (byte*)sprite_header + sprite_header->mask;
+ bool alpha = ((unsigned)sprite_header->mode & 0x80000000U) != 0;
+
+ while (h-- > 0) {
+ int x = 0;
+ for(x = 0; x < w; x++) {
+ unsigned d = *dp++;
+ if (alpha)
+ *mp++ = (d >> 24) ^ 0xff;
+ else
+ *mp++ = (d < 0xff000000U) ? 0 : 0xff;
+ }
+ dp += dp_offset;
+ mp += mp_offset;
+ }
+ }
+
+ return sprite_area;
+}
+
+
+
+
+/**
+ * Check to see whether 32bpp sprites are available.
+ *
+ * Rather than using Wimp_ReadSysInfo we test if 32bpp sprites are available
+ * in case the user has a 3rd party patch to enable them.
+ */
+static void thumbnail_test(void)
+{
+ unsigned int area_size;
+ osspriteop_area *sprite_area;
+
+ /* try to create a 1x1 32bpp sprite */
+ area_size = sizeof(osspriteop_area) +
+ sizeof(osspriteop_header) + sizeof(int);
+ if ((sprite_area = (osspriteop_area *)malloc(area_size)) == NULL) {
+ LOG("Insufficient memory to perform sprite test.");
+ return;
+ }
+ sprite_area->size = area_size + 1;
+ sprite_area->sprite_count = 0;
+ sprite_area->first = 16;
+ sprite_area->used = 16;
+ if (xosspriteop_create_sprite(osspriteop_NAME, sprite_area,
+ "test", false, 1, 1, (os_mode)tinct_SPRITE_MODE))
+ thumbnail_32bpp_available = 0;
+ else
+ thumbnail_32bpp_available = 1;
+ free(sprite_area);
+}
+
+
+/* exported interface documented in riscos/bitmap.h */
+nserror riscos_bitmap_render(struct bitmap *bitmap,
+ struct hlcache_handle *content)
+{
+ struct thumbnail_save_area *save_area;
+ osspriteop_area *sprite_area = NULL;
+ osspriteop_header *sprite_header = NULL;
+ struct redraw_context ctx = {
+ .interactive = false,
+ .background_images = true,
+ .plot = &ro_plotters
+ };
+
+ assert(content);
+ assert(bitmap);
+
+ LOG("content %p in bitmap %p", content, bitmap);
+
+ /* check if we have access to 32bpp sprites natively */
+ if (thumbnail_32bpp_available == -1) {
+ thumbnail_test();
+ }
+
+ /* if we don't support 32bpp sprites then we redirect to an 8bpp
+ * image and then convert back.
+ */
+ if (thumbnail_32bpp_available != 1) {
+ sprite_area = thumbnail_create_8bpp(bitmap);
+ if (!sprite_area)
+ return false;
+ sprite_header = (osspriteop_header *)(sprite_area + 1);
+ } else {
+ const uint8_t *pixbufp = riscos_bitmap_get_buffer(bitmap);
+ if (!pixbufp || !bitmap->sprite_area)
+ return false;
+ sprite_area = bitmap->sprite_area;
+ sprite_header = (osspriteop_header *)(sprite_area + 1);
+ }
+
+ /* set up the plotters */
+ ro_plot_origin_x = 0;
+ ro_plot_origin_y = bitmap->height * 2;
+
+ /* switch output and redraw */
+ save_area = thumbnail_switch_output(sprite_area, sprite_header);
+ if (!save_area) {
+ if (thumbnail_32bpp_available != 1)
+ free(sprite_area);
+ return false;
+ }
+ rufl_invalidate_cache();
+ colourtrans_set_gcol(os_COLOUR_WHITE, colourtrans_SET_BG_GCOL,
+ os_ACTION_OVERWRITE, 0);
+
+ /* render the content */
+ content_scaled_redraw(content, bitmap->width, bitmap->height, &ctx);
+
+ thumbnail_restore_output(save_area);
+ rufl_invalidate_cache();
+
+ /* if we changed to 8bpp then go back to 32bpp */
+ if (thumbnail_32bpp_available != 1) {
+ const uint8_t *pixbufp = riscos_bitmap_get_buffer(bitmap);
+ _kernel_oserror *error;
+
+ if (!pixbufp || !bitmap->sprite_area) {
+ free(sprite_area);
+ return false;
+ }
+ error = _swix(Tinct_ConvertSprite, _INR(2,3),
+ sprite_header,
+ (osspriteop_header *)(bitmap->sprite_area + 1));
+ free(sprite_area);
+ if (error)
+ return false;
+ }
+
+ bitmap_modified(bitmap);
+
+ return NSERROR_OK;
+}
+
+static struct gui_bitmap_table bitmap_table = {
+ .create = riscos_bitmap_create,
+ .destroy = riscos_bitmap_destroy,
+ .set_opaque = bitmap_set_opaque,
+ .get_opaque = riscos_bitmap_get_opaque,
+ .test_opaque = bitmap_test_opaque,
+ .get_buffer = riscos_bitmap_get_buffer,
+ .get_rowstride = bitmap_get_rowstride,
+ .get_width = bitmap_get_width,
+ .get_height = bitmap_get_height,
+ .get_bpp = bitmap_get_bpp,
+ .save = riscos_bitmap_save,
+ .modified = bitmap_modified,
+ .render = riscos_bitmap_render,
+};
+
+struct gui_bitmap_table *riscos_bitmap_table = &bitmap_table;
diff --git a/frontends/riscos/bitmap.h b/frontends/riscos/bitmap.h
new file mode 100644
index 000000000..3aca30de6
--- /dev/null
+++ b/frontends/riscos/bitmap.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2004 James Bursa <bursa@users.sourceforge.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _NETSURF_RISCOS_BITMAP_H_
+#define _NETSURF_RISCOS_BITMAP_H_
+
+struct osspriteop_area;
+struct osspriteop_header;
+struct hlcache_handle;
+struct bitmap;
+
+/** bitmap operations table */
+struct gui_bitmap_table *riscos_bitmap_table;
+
+/** save with full alpha channel (if not opaque) */
+#define BITMAP_SAVE_FULL_ALPHA (1 << 0)
+
+/**
+ * RISC OS wimp toolkit bitmap.
+ */
+struct bitmap {
+ int width; /**< width of bitmap */
+ int height; /**< height of bitmap */
+
+ unsigned int state; /**< The bitmap attributes (opaque/dirty etc.) */
+
+ struct osspriteop_area *sprite_area; /**< Uncompressed data, or NULL */
+};
+
+/**
+ * Convert bitmap to 8bpp sprite.
+ *
+ * \param bitmap the bitmap to convert.
+ * \return The converted sprite.
+ */
+struct osspriteop_area *riscos_bitmap_convert_8bpp(struct bitmap *bitmap);
+
+/**
+ * Render content into bitmap.
+ *
+ * \param bitmap the bitmap to draw to
+ * \param content content structure to render
+ * \return true on success and bitmap updated else false
+ */
+nserror riscos_bitmap_render(struct bitmap *bitmap, struct hlcache_handle *content);
+
+/**
+ * Overlay a sprite onto the given bitmap
+ *
+ * \param bitmap bitmap object
+ * \param s 8bpp sprite to be overlayed onto bitmap
+ */
+void riscos_bitmap_overlay_sprite(struct bitmap *bitmap, const struct osspriteop_header *s);
+
+/**
+ * Create a bitmap.
+ *
+ * \param width width of image in pixels
+ * \param height width of image in pixels
+ * \param state the state to create the bitmap in.
+ * \return an opaque struct bitmap, or NULL on memory exhaustion
+ */
+void *riscos_bitmap_create(int width, int height, unsigned int state);
+
+/**
+ * Free a bitmap.
+ *
+ * \param vbitmap a bitmap, as returned by bitmap_create()
+ */
+void riscos_bitmap_destroy(void *vbitmap);
+
+/**
+ * Return a pointer to the pixel data in a bitmap.
+ *
+ * The pixel data is packed as BITMAP_FORMAT, possibly with padding at
+ * the end of rows. The width of a row in bytes is given by
+ * riscos_bitmap_get_rowstride().
+ *
+ * \param vbitmap A bitmap as returned by riscos_bitmap_create()
+ * \return pointer to the pixel buffer
+ */
+unsigned char *riscos_bitmap_get_buffer(void *vbitmap);
+
+/**
+ * Gets whether a bitmap should be plotted opaque
+ *
+ * \param vbitmap A bitmap, as returned by riscos_bitmap_create()
+ */
+bool riscos_bitmap_get_opaque(void *vbitmap);
+
+/**
+ * Save a bitmap in the platform's native format.
+ *
+ * \param vbitmap a bitmap, as returned by bitmap_create()
+ * \param path pathname for file
+ * \param flags modify the behaviour of the save
+ * \return true on success, false on error and error reported
+ */
+bool riscos_bitmap_save(void *vbitmap, const char *path, unsigned flags);
+
+#endif
diff --git a/frontends/riscos/buffer.c b/frontends/riscos/buffer.c
new file mode 100644
index 000000000..7176c1c1c
--- /dev/null
+++ b/frontends/riscos/buffer.c
@@ -0,0 +1,396 @@
+/*
+ * Copyright 2004, 2005 Richard Wilson <info@tinct.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <swis.h>
+#include <oslib/colourtrans.h>
+#include <oslib/os.h>
+#include <oslib/osspriteop.h>
+#include <oslib/wimp.h>
+#include <oslib/wimpreadsysinfo.h>
+
+#include "utils/nsoption.h"
+#include "utils/log.h"
+
+#include "riscos/buffer.h"
+#include "riscos/gui.h"
+#include "riscos/tinct.h"
+#include "riscos/wimp.h"
+#include "riscos/wimputils.h"
+
+#define BUFFER_EXCLUSIVE_USER_REDRAW "Only support pure user redraw (faster)"
+//#define BUFFER_EMULATE_32BPP "Redirect to a 32bpp sprite and plot with Tinct"
+
+/** Absent from OSLib
+*/
+#ifndef osspriteop_TYPEEXPANSION
+#define osspriteop_TYPEEXPANSION ((osspriteop_mode_word) 0xFu)
+#endif
+#ifndef osspriteop_TYPE16BPP4K
+#define osspriteop_TYPE16BPP4K ((osspriteop_mode_word) 0x10u)
+#endif
+
+static void ro_gui_buffer_free(void);
+
+
+/** The buffer characteristics
+*/
+static osspriteop_area *buffer = NULL;
+static char buffer_name[12] = "scr_buffer";
+
+/** The current clip area
+*/
+static os_box clipping;
+
+/** The current save area
+*/
+static osspriteop_save_area *save_area;
+static int context0;
+static int context1;
+static int context2;
+static int context3;
+
+/** The current sprite mode
+*/
+static os_mode mode;
+
+
+/**
+ * Opens a buffer for writing to.
+ *
+ * The ro_plot_origin_ variables are updated to reflect the new screen origin,
+ * so the variables should be set before calling this function, and not
+ * changed until after ro_gui_buffer_close() has been called.
+ *
+ * \param redraw the current WIMP redraw area to buffer
+ */
+void ro_gui_buffer_open(wimp_draw *redraw)
+{
+ int size;
+ int total_size;
+ os_coord sprite_size;
+ int bpp, word_width;
+ bool palette;
+ os_error *error;
+ int palette_size = 0;
+#ifdef BUFFER_EXCLUSIVE_USER_REDRAW
+ osspriteop_header *header;
+#endif
+
+ /* Close any open buffer
+ */
+ if (buffer)
+ ro_gui_buffer_close();
+
+ /* Store our clipping region
+ */
+ clipping = redraw->clip;
+
+ /* Stop bad rectangles
+ */
+ if ((clipping.x1 < clipping.x0) ||
+ (clipping.y1 < clipping.y0)) {
+ LOG("Invalid clipping rectangle (%i, %i) to (%i,%i)", clipping.x0, clipping.y0, clipping.x1, clipping.y1);
+ return;
+ }
+
+ /* Work out how much buffer we need
+ */
+ sprite_size.x = clipping.x1 - clipping.x0 + 1;
+ sprite_size.y = clipping.y1 - clipping.y0 + 1;
+ ro_convert_os_units_to_pixels(&sprite_size, (os_mode)-1);
+ if (sprite_size.y == 1) /* work around SpriteExtend bug */
+ sprite_size.y = 2;
+
+#ifdef BUFFER_EMULATE_32BPP
+ bpp = 5;
+ palette = false;
+#else
+ /* Get the screen depth as we can't use palettes for >8bpp
+ */
+ xos_read_mode_variable((os_mode)-1, os_MODEVAR_LOG2_BPP, &bpp, 0);
+ palette = (bpp < 4);
+#endif
+
+ /* Get our required buffer size
+ */
+ word_width = ((sprite_size.x << bpp) + 31) >> 5;
+ if (palette)
+ palette_size = ((1 << (1 << bpp)) << 3);
+ total_size = sizeof(osspriteop_area) + sizeof(osspriteop_header) +
+ (word_width * sprite_size.y * 4) + palette_size;
+ buffer = (osspriteop_area *)malloc(total_size);
+ if (!buffer) {
+ LOG("Failed to allocate memory");
+ ro_gui_buffer_free();
+ return;
+ }
+ buffer->size = total_size;
+ buffer->first = 16;
+
+#ifdef BUFFER_EMULATE_32BPP
+ mode = tinct_SPRITE_MODE;
+#else
+ if ((error = xwimpreadsysinfo_wimp_mode(&mode)) != NULL) {
+ LOG("Error reading mode '%s'", error->errmess);
+ ro_gui_buffer_free();
+ return;
+ }
+
+ /* if we're not in a numbered screen mode then we need
+ to build a suitable sprite mode word */
+ if (mode >= (os_mode)0x100) {
+ static const ns_os_vdu_var_list vars = {
+ os_MODEVAR_LOG2_BPP,
+ {
+ os_MODEVAR_MODE_FLAGS,
+ os_MODEVAR_NCOLOUR,
+ os_MODEVAR_XEIG_FACTOR,
+ os_MODEVAR_YEIG_FACTOR,
+ os_VDUVAR_END_LIST
+ }
+ };
+ struct {
+ int log2bpp;
+ int flags;
+ int ncolour;
+ int xeig, yeig;
+ } vals;
+ int type;
+
+ error = xos_read_vdu_variables(PTR_OS_VDU_VAR_LIST(&vars), (int *)&vals);
+ if (error) {
+ LOG("Error reading mode properties '%s'", error->errmess);
+ ro_gui_buffer_free();
+ return;
+ }
+
+ switch (vals.ncolour) {
+ case 1:
+ case 3:
+ case 15:
+ case 63:
+ case 255:
+ /* Paletted modes are pixel packing order agnostic */
+ type = 1 + vals.log2bpp;
+ mode = (os_mode)((type << osspriteop_TYPE_SHIFT) |
+ osspriteop_NEW_STYLE |
+ ((180 >> vals.yeig) << osspriteop_YRES_SHIFT) |
+ ((180 >> vals.xeig) << osspriteop_XRES_SHIFT));
+ break;
+ case 4095:
+ /* 16bpp 4k colours */
+ type = osspriteop_TYPE16BPP4K;
+ mode = (os_mode)((osspriteop_TYPEEXPANSION << osspriteop_TYPE_SHIFT) |
+ osspriteop_NEW_STYLE |
+ (vals.yeig << 6) |
+ (vals.xeig << 4) |
+ (type << 20) |
+ (vals.flags & 0xFF00));
+ break;
+ case 65535:
+ switch ((vals.flags & 0x3000) >> os_MODE_FLAG_DATA_FORMAT_SHIFT) {
+ case os_MODE_FLAG_DATA_FORMAT_RGB:
+ if (vals.flags & 0xC000) {
+ /* Non VIDC packing order */
+ if (vals.flags & os_MODE_FLAG_FULL_PALETTE)
+ type = osspriteop_TYPE16BPP64K;
+ else
+ type = osspriteop_TYPE16BPP;
+ mode = (os_mode)((osspriteop_TYPEEXPANSION << osspriteop_TYPE_SHIFT) |
+ osspriteop_NEW_STYLE |
+ (vals.yeig << 6) |
+ (vals.xeig << 4) |
+ (type << 20) |
+ (vals.flags & 0xFF00));
+ } else {
+ /* VIDC packing order */
+ if (vals.flags & os_MODE_FLAG_FULL_PALETTE)
+ type = osspriteop_TYPE16BPP64K;
+ else
+ type = osspriteop_TYPE16BPP;
+ mode = (os_mode)((type << osspriteop_TYPE_SHIFT) |
+ osspriteop_NEW_STYLE |
+ ((180 >> vals.yeig) << osspriteop_YRES_SHIFT) |
+ ((180 >> vals.xeig) << osspriteop_XRES_SHIFT));
+ }
+ break;
+ default:
+ LOG("Unhandled 16bpp format from flags %d", vals.flags);
+ ro_gui_buffer_free();
+ return;
+ }
+ break;
+ case -1:
+ /* 16M colours */
+ switch ((vals.flags & 0x3000) >> os_MODE_FLAG_DATA_FORMAT_SHIFT) {
+ case os_MODE_FLAG_DATA_FORMAT_RGB:
+ if (vals.flags & 0xC000) {
+ /* Non VIDC packing order */
+ type = osspriteop_TYPE32BPP;
+ mode = (os_mode)((osspriteop_TYPEEXPANSION << osspriteop_TYPE_SHIFT) |
+ osspriteop_NEW_STYLE |
+ (vals.yeig << 6) |
+ (vals.xeig << 4) |
+ (type << 20) |
+ (vals.flags & 0xFF00));
+ } else {
+ /* VIDC packing order */
+ type = osspriteop_TYPE32BPP;
+ mode = (os_mode)((type << osspriteop_TYPE_SHIFT) |
+ osspriteop_NEW_STYLE |
+ ((180 >> vals.yeig) << osspriteop_YRES_SHIFT) |
+ ((180 >> vals.xeig) << osspriteop_XRES_SHIFT));
+ }
+ break;
+ default:
+ LOG("Unhandled 32bpp data format from flags %d", vals.flags);
+ ro_gui_buffer_free();
+ return;
+ }
+ break;
+ default:
+ LOG("Unhandled NCOLOUR value %d", vals.ncolour);
+ ro_gui_buffer_free();
+ return;
+ }
+ }
+#endif
+
+#ifdef BUFFER_EXCLUSIVE_USER_REDRAW
+ /* Create the sprite manually so we don't waste time clearing the
+ background.
+ */
+ buffer->sprite_count = 1;
+ buffer->used = total_size;
+ header = (osspriteop_header *)(buffer + 1);
+ header->size = total_size - sizeof(osspriteop_area);
+ memcpy(header->name, buffer_name, 12);
+ header->width = word_width - 1;
+ header->height = sprite_size.y - 1;
+ header->left_bit = 0;
+ header->right_bit = ((sprite_size.x << bpp) - 1) & 31;
+ header->image = sizeof(osspriteop_header) + palette_size;
+ header->mask = header->image;
+ header->mode = mode;
+ if (palette)
+ xcolourtrans_read_palette((osspriteop_area *)mode,
+ (osspriteop_id)os_CURRENT_MODE,
+ (os_palette *)(header + 1), palette_size,
+ (colourtrans_palette_flags)
+ colourtrans_FLASHING_PALETTE, 0);
+#else
+ /* Read the current contents of the screen
+ */
+ buffer->sprite_count = 0;
+ buffer->used = 16;
+ if ((error = xosspriteop_get_sprite_user_coords(osspriteop_NAME,
+ buffer, buffer_name, palette,
+ clipping.x0, clipping.y0,
+ clipping.x1, clipping.y1)) != NULL) {
+ LOG("Grab error '%s'", error->errmess);
+ ro_gui_buffer_free();
+ return;
+ }
+#endif
+ /* Allocate OS_SpriteOp save area
+ */
+ if ((error = xosspriteop_read_save_area_size(osspriteop_PTR,
+ buffer, (osspriteop_id)(buffer + 1), &size)) != NULL) {
+ LOG("Save area error '%s'", error->errmess);
+ ro_gui_buffer_free();
+ return;
+ }
+ if ((save_area = malloc((size_t)size)) == NULL) {
+ ro_gui_buffer_free();
+ return;
+ }
+ save_area->a[0] = 0;
+
+ /* Switch output to sprite
+ */
+ if ((error = xosspriteop_switch_output_to_sprite(osspriteop_PTR,
+ buffer, (osspriteop_id)(buffer + 1), save_area,
+ &context0, &context1, &context2, &context3)) != NULL) {
+ LOG("Switching error '%s'", error->errmess);
+ free(save_area);
+ ro_gui_buffer_free();
+ return;
+ }
+
+ /* Emulate an origin as the FontManager doesn't respect it in
+ most cases.
+ */
+ ro_plot_origin_x -= clipping.x0;
+ ro_plot_origin_y -= clipping.y0;
+
+ /* Update the ECF origin
+ */
+ if ((error = xos_set_ecf_origin(-ro_plot_origin_x,
+ -ro_plot_origin_y)) != NULL) {
+ LOG("Invalid ECF origin: '%s'", error->errmess);
+ }
+}
+
+
+/**
+ * Closes any open buffer and flushes the contents to screen
+ */
+void ro_gui_buffer_close(void)
+{
+ /* Check we have an open buffer
+ */
+ if (!buffer)
+ return;
+
+ /* Remove any previous redirection
+ */
+ ro_plot_origin_x += clipping.x0;
+ ro_plot_origin_y += clipping.y0;
+ xosspriteop_unswitch_output(context0, context1, context2, context3);
+ free(save_area);
+
+ /* Plot the contents to screen
+ */
+ if (mode == tinct_SPRITE_MODE)
+ _swix(Tinct_Plot, _IN(2) | _IN(3) | _IN(4) | _IN(7),
+ (char *)(buffer + 1),
+ clipping.x0, clipping.y0,
+ nsoption_int(plot_fg_quality));
+ else
+ xosspriteop_put_sprite_user_coords(osspriteop_PTR,
+ buffer, (osspriteop_id)(buffer + 1),
+ clipping.x0, clipping.y0, (os_action)0);
+ ro_gui_buffer_free();
+
+ /* Update the ECF origin
+ */
+ os_set_ecf_origin(0, 0);
+}
+
+
+/**
+ * Releases any buffer memory depending on cache constraints.
+ */
+static void ro_gui_buffer_free(void)
+{
+ free(buffer);
+ buffer = NULL;
+}
diff --git a/frontends/riscos/buffer.h b/frontends/riscos/buffer.h
new file mode 100644
index 000000000..a683c324c
--- /dev/null
+++ b/frontends/riscos/buffer.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2004 Richard Wilson <not_ginger_matt@users.sourceforge.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Screen buffering (interface).
+ */
+
+#ifndef _NETSURF_RISCOS_BUFFER_H_
+#define _NETSURF_RISCOS_BUFFER_H_
+
+#include "oslib/wimp.h"
+
+void ro_gui_buffer_open(wimp_draw *redraw);
+void ro_gui_buffer_close(void);
+
+#endif
diff --git a/frontends/riscos/configure.c b/frontends/riscos/configure.c
new file mode 100644
index 000000000..9d28616ec
--- /dev/null
+++ b/frontends/riscos/configure.c
@@ -0,0 +1,410 @@
+/*
+ * Copyright 2005 Richard Wilson <info@tinct.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * RISC OS option setting (implementation).
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <oslib/os.h>
+#include <oslib/osbyte.h>
+#include <oslib/territory.h>
+#include <oslib/wimp.h>
+
+#include "utils/log.h"
+#include "utils/messages.h"
+
+#include "riscos/gui.h"
+#include "riscos/dialog.h"
+#include "riscos/configure.h"
+#include "riscos/wimp.h"
+#include "riscos/wimp_event.h"
+#include "riscos/configure/configure.h"
+
+#define CONFIGURE_ICON_PADDING_H 32
+#define CONFIGURE_ICON_PADDING_V 32
+#define CONFIGURE_DEFAULT_ICON_WIDTH (68 + CONFIGURE_ICON_PADDING_H)
+#define CONFIGURE_DEFAULT_ICON_HEIGHT (128 + CONFIGURE_ICON_PADDING_V)
+
+struct configure_tool {
+ const char *name;
+#define CONFIGURE_TOOL_TRANSLATED_SIZE 64
+ char translated[CONFIGURE_TOOL_TRANSLATED_SIZE];
+ char *validation;
+ bool (*initialise)(wimp_w w);
+ void (*finalise)(wimp_w w);
+ wimp_w w;
+ wimp_i i;
+ bool open;
+ struct configure_tool *next;
+};
+
+static wimp_w configure_window;
+static int configure_current_encoding;
+static int configure_icons = 0;
+static struct configure_tool *configure_tools = NULL;
+static int configure_icon_width = CONFIGURE_DEFAULT_ICON_WIDTH;
+static int configure_icon_height = CONFIGURE_DEFAULT_ICON_HEIGHT;
+static int configure_icons_per_line = 0;
+static int configure_width;
+static int configure_height;
+
+static bool ro_gui_configure_click(wimp_pointer *pointer);
+static void ro_gui_configure_open_window(wimp_open *open);
+static void ro_gui_configure_close(wimp_w w);
+static bool ro_gui_configure_translate(void);
+static void ro_gui_configure_register(const char *window,
+ bool (*initialise)(wimp_w w), void (*finalise)(wimp_w w));
+
+void ro_gui_configure_initialise(void)
+{
+ /* create our window */
+ configure_window = ro_gui_dialog_create("configure");
+ ro_gui_wimp_event_register_open_window(configure_window,
+ ro_gui_configure_open_window);
+ ro_gui_wimp_event_register_mouse_click(configure_window,
+ ro_gui_configure_click);
+ ro_gui_wimp_event_set_help_prefix(configure_window, "HelpConfigure");
+
+ /* add in our option windows */
+ ro_gui_configure_register("con_cache",
+ ro_gui_options_cache_initialise,
+ ro_gui_wimp_event_finalise);
+ ro_gui_configure_register("con_connect",
+ ro_gui_options_connection_initialise,
+ ro_gui_wimp_event_finalise);
+ ro_gui_configure_register("con_content",
+ ro_gui_options_content_initialise,
+ ro_gui_wimp_event_finalise);
+ ro_gui_configure_register("con_fonts",
+ ro_gui_options_fonts_initialise,
+ ro_gui_wimp_event_finalise);
+ ro_gui_configure_register("con_home",
+ ro_gui_options_home_initialise,
+ ro_gui_wimp_event_finalise);
+ ro_gui_configure_register("con_image",
+ ro_gui_options_image_initialise,
+ ro_gui_options_image_finalise);
+ ro_gui_configure_register("con_inter",
+ ro_gui_options_interface_initialise,
+ ro_gui_wimp_event_finalise);
+ ro_gui_configure_register("con_lang",
+ ro_gui_options_language_initialise,
+ ro_gui_wimp_event_finalise);
+ ro_gui_configure_register("con_theme",
+ ro_gui_options_theme_initialise,
+ ro_gui_options_theme_finalise);
+ ro_gui_configure_register("con_secure",
+ ro_gui_options_security_initialise,
+ ro_gui_wimp_event_finalise);
+
+ /* translate the icons */
+ if (!ro_gui_configure_translate())
+ die("ro_gui_configure_translate failed");
+}
+
+void ro_gui_configure_show(void)
+{
+ int width, height;
+
+ width = configure_icon_width << 2;
+ height = ((configure_icons + 3) >> 2) * configure_icon_height;
+ ro_gui_dialog_open_top(configure_window, NULL, width, height);
+}
+
+bool ro_gui_configure_click(wimp_pointer *pointer)
+{
+ struct configure_tool *tool;
+
+ if (pointer->buttons == wimp_CLICK_MENU)
+ return true;
+
+ for (tool = configure_tools; tool; tool = tool->next) {
+ if (tool->i == pointer->i) {
+ if (!tool->open) {
+ tool->open = true;
+ if (!tool->initialise(tool->w))
+ return false;
+ ro_gui_dialog_open_persistent(
+ configure_window,
+ tool->w, true);
+ ro_gui_wimp_event_register_close_window(
+ tool->w,
+ ro_gui_configure_close);
+ } else {
+ ro_gui_dialog_open_top(tool->w, NULL, 0, 0);
+ }
+ break;
+ }
+ }
+ return true;
+}
+
+void ro_gui_configure_close(wimp_w w)
+{
+ struct configure_tool *tool;
+
+ for (tool = configure_tools; tool; tool = tool->next) {
+ if (tool->w == w) {
+ tool->open = false;
+ if (tool->finalise)
+ tool->finalise(w);
+ break;
+ }
+ }
+}
+
+void ro_gui_configure_open_window(wimp_open *open)
+{
+ os_error *error;
+ int screen_width, screen_height;
+ int height, width;
+ int icons_per_line, icon_lines;
+ int max_height;
+ os_box extent = { 0, 0, 0, 0 };
+ struct configure_tool *tool;
+
+ if (!ro_gui_configure_translate()) {
+ ro_warn_user("ro_gui_configure_translate failed", 0);
+ return;
+ }
+
+ width = open->visible.x1 - open->visible.x0;
+ height = open->visible.y1 - open->visible.y0;
+ icons_per_line = width / configure_icon_width;
+ if (icons_per_line < 1)
+ icons_per_line = 1;
+
+ /* move our icons */
+ if (icons_per_line != configure_icons_per_line) {
+ int x, y, l;
+ configure_icons_per_line = icons_per_line;
+ x = CONFIGURE_ICON_PADDING_H / 2;
+ y = -configure_icon_height + (CONFIGURE_ICON_PADDING_V / 2);
+ l = 0;
+ for (tool = configure_tools; tool; tool = tool->next) {
+ error = xwimp_resize_icon(configure_window,
+ tool->i,
+ x,
+ y,
+ x + configure_icon_width -
+ CONFIGURE_ICON_PADDING_H,
+ y + configure_icon_height -
+ CONFIGURE_ICON_PADDING_V);
+ if (error) {
+ LOG("xwimp_resize_icon: 0x%x: %s", error->errnum, error->errmess);
+ }
+ x += configure_icon_width;
+ l++;
+ if (l >= icons_per_line) {
+ x = CONFIGURE_ICON_PADDING_H / 2;
+ l = 0;
+ y -= configure_icon_height;
+ }
+ }
+ error = xwimp_force_redraw(configure_window,
+ 0, -16384, 16384, 0);
+ if (error) {
+ LOG("xwimp_force_redraw: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+ }
+
+ /* restrict our height */
+ icon_lines = (configure_icons + icons_per_line - 1) /
+ icons_per_line;
+ max_height = (icon_lines * configure_icon_height);
+ if (height > max_height)
+ open->visible.y0 = open->visible.y1 - max_height;
+
+ /* set the extent */
+ if ((configure_height != height) || (configure_width != width)) {
+ int max_icons_per_line;
+ ro_gui_screen_size(&screen_width, &screen_height);
+ max_icons_per_line = screen_width / configure_icon_width;
+ if (max_icons_per_line > configure_icons)
+ max_icons_per_line = configure_icons;
+ extent.x1 = configure_icon_width * max_icons_per_line;
+ extent.y0 = -max_height;
+ error = xwimp_set_extent(open->w, &extent);
+ if (error) {
+ LOG("xwimp_set_extent: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+ configure_height = height;
+ configure_width = width;
+ }
+
+ /* open the window */
+ error = xwimp_open_window(open);
+ if (error) {
+ LOG("xwimp_open_window: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+}
+
+void ro_gui_configure_register(const char *window,
+ bool (*initialise)(wimp_w w), void (*finalise)(wimp_w w))
+{
+ wimp_icon_create new_icon;
+ struct configure_tool *tool;
+ struct configure_tool *link;
+ os_error *error;
+
+ /* create our tool */
+ tool = calloc(sizeof(struct configure_tool), 1);
+ if (!tool) {
+ LOG("Insufficient memory for calloc()");
+ die("Insufficient memory");
+ return; /* For the benefit of scan-build */
+ }
+ tool->name = window;
+ tool->translated[0] = '\0';
+ tool->validation = malloc(strlen(window) + 2);
+ if (!tool->validation) {
+ LOG("Insufficient memory for malloc()");
+ die("Insufficient memory");
+ }
+ sprintf(tool->validation, "S%s", window);
+ tool->initialise = initialise;
+ tool->finalise = finalise;
+ tool->w = ro_gui_dialog_create(tool->name);
+
+ /* create the icon */
+ new_icon.w = configure_window;
+ new_icon.icon.extent.x0 = 0;
+ new_icon.icon.extent.x1 = configure_icon_width;
+ new_icon.icon.extent.y1 = 0;
+ new_icon.icon.extent.y0 = -configure_icon_height;
+ new_icon.icon.flags = wimp_ICON_TEXT | wimp_ICON_SPRITE |
+ wimp_ICON_INDIRECTED | wimp_ICON_HCENTRED |
+ (wimp_COLOUR_VERY_LIGHT_GREY << wimp_ICON_BG_COLOUR_SHIFT) |
+ (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) |
+ (wimp_BUTTON_CLICK << wimp_ICON_BUTTON_TYPE_SHIFT);
+ new_icon.icon.data.indirected_text_and_sprite.text =
+ tool->translated;
+ new_icon.icon.data.indirected_text_and_sprite.validation =
+ tool->validation;
+ new_icon.icon.data.indirected_text_and_sprite.size =
+ CONFIGURE_TOOL_TRANSLATED_SIZE;
+ error = xwimp_create_icon(&new_icon, &tool->i);
+ if (error) {
+ LOG("xwimp_create_icon: 0x%x: %s", error->errnum, error->errmess);
+ die(error->errmess);
+ }
+
+ /* Set the icon's text in current local encoding */
+ ro_gui_set_icon_string(configure_window, tool->i,
+ messages_get(tool->name), true);
+
+ /* link into our list alphabetically */
+ if ((!configure_tools) ||
+ (strcmp(configure_tools->translated,
+ tool->translated) > 0)) {
+ tool->next = configure_tools;
+ configure_tools = tool;
+ } else {
+ for (link = configure_tools; link; link = link->next) {
+ if (link->next) {
+ if (strcmp(link->next->translated,
+ tool->translated) > 0) {
+ tool->next = link->next;
+ link->next = tool;
+ break;
+ }
+ } else {
+ link->next = tool;
+ break;
+ }
+ }
+ }
+ configure_icons++;
+}
+
+/**
+ * Translate tool icons into the system local encoding.
+ * This will also recalculate the minimum required icon width.
+ *
+ * \return true on success, false on memory exhaustion
+ */
+bool ro_gui_configure_translate(void)
+{
+ int alphabet;
+ struct configure_tool *tool;
+ int icon_width;
+ os_error *error;
+
+ /* read current alphabet */
+ error = xosbyte1(osbyte_ALPHABET_NUMBER, 127, 0,
+ &alphabet);
+ if (error) {
+ LOG("failed reading alphabet: 0x%x: %s", error->errnum, error->errmess);
+ /* assume Latin1 */
+ alphabet = territory_ALPHABET_LATIN1;
+ }
+
+ if (alphabet == configure_current_encoding)
+ /* text is already in the correct encoding */
+ return true;
+
+ /* reset icon width */
+ configure_icon_width = CONFIGURE_DEFAULT_ICON_WIDTH;
+
+ for (tool = configure_tools; tool; tool = tool->next) {
+ /* re-translate the text */
+ ro_gui_set_icon_string(configure_window, tool->i,
+ messages_get(tool->name), true);
+
+ /* update the width */
+ error = xwimptextop_string_width(tool->translated,
+ strlen(tool->translated), &icon_width);
+ if (error) {
+ LOG("xwimptextop_string_width: 0x%x: %s", error->errnum, error->errmess);
+ return false;
+ }
+ icon_width += CONFIGURE_ICON_PADDING_H;
+ if (icon_width > configure_icon_width)
+ configure_icon_width = icon_width;
+
+ error = xwimp_resize_icon(configure_window,
+ tool->i,
+ 0,
+ -configure_icon_height,
+ configure_icon_width,
+ 0);
+ if (error) {
+ LOG("xwimp_resize_icon: 0x%x: %s", error->errnum, error->errmess);
+ }
+ }
+
+ /* invalidate our global icons_per_line setting
+ * so the icons get reflowed */
+ configure_icons_per_line = 0;
+
+ /* finally, set the current encoding */
+ configure_current_encoding = alphabet;
+
+ return true;
+}
diff --git a/frontends/riscos/configure.h b/frontends/riscos/configure.h
new file mode 100644
index 000000000..c190a6d0c
--- /dev/null
+++ b/frontends/riscos/configure.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2005 Richard Wilson <info@tinct.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * RISC OS option setting (interface).
+ */
+
+
+#ifndef _NETSURF_RISCOS_CONFIGURE_H_
+#define _NETSURF_RISCOS_CONFIGURE_H_
+
+#include <stdbool.h>
+#include "oslib/os.h"
+#include "oslib/wimp.h"
+
+void ro_gui_configure_initialise(void);
+void ro_gui_configure_show(void);
+
+#endif
diff --git a/frontends/riscos/configure/con_cache.c b/frontends/riscos/configure/con_cache.c
new file mode 100644
index 000000000..730d6f82f
--- /dev/null
+++ b/frontends/riscos/configure/con_cache.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2005 Richard Wilson <info@tinct.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdbool.h>
+#include <oslib/hourglass.h>
+
+#include "utils/nsoption.h"
+#include "utils/filename.h"
+#include "utils/messages.h"
+
+#include "riscos/gui.h"
+#include "riscos/wimp.h"
+#include "riscos/wimp_event.h"
+#include "riscos/configure.h"
+#include "riscos/configure/configure.h"
+#include "riscos/dialog.h"
+
+
+#define CACHE_MEMORY_SIZE 3
+#define CACHE_MEMORY_DEC 4
+#define CACHE_MEMORY_INC 5
+#define CACHE_DISC_SIZE 10
+#define CACHE_DISC_DEC 11
+#define CACHE_DISC_INC 12
+#define CACHE_DISC_EXPIRE 15
+#define CACHE_DISC_EXPIRE_DEC 16
+#define CACHE_DISC_EXPIRE_INC 17
+#define CACHE_DEFAULT_BUTTON 19
+#define CACHE_CANCEL_BUTTON 20
+#define CACHE_OK_BUTTON 21
+
+static bool ro_gui_options_cache_click(wimp_pointer *pointer);
+static bool ro_gui_options_cache_ok(wimp_w w);
+
+bool ro_gui_options_cache_initialise(wimp_w w)
+{
+ /* set the current values */
+ ro_gui_set_icon_decimal(w, CACHE_MEMORY_SIZE,
+ (nsoption_int(memory_cache_size) * 10) >> 20, 1);
+ ro_gui_set_icon_decimal(w, CACHE_DISC_SIZE,
+ (int) ((nsoption_uint(disc_cache_size)) >> 20), 0);
+ ro_gui_set_icon_decimal(w, CACHE_DISC_EXPIRE,
+ (nsoption_int(disc_cache_age)), 0);
+
+ /* initialise all functions for a newly created window */
+ ro_gui_wimp_event_register_numeric_field(w, CACHE_MEMORY_SIZE,
+ CACHE_MEMORY_INC, CACHE_MEMORY_DEC, 0, 640, 1, 1);
+ ro_gui_wimp_event_register_numeric_field(w, CACHE_DISC_SIZE,
+ CACHE_DISC_INC, CACHE_DISC_DEC, 0, 4095, 1, 0);
+ ro_gui_wimp_event_register_numeric_field(w, CACHE_DISC_EXPIRE,
+ CACHE_DISC_EXPIRE_INC, CACHE_DISC_EXPIRE_DEC, 1, 3650,
+ 1, 0);
+ ro_gui_wimp_event_register_mouse_click(w, ro_gui_options_cache_click);
+ ro_gui_wimp_event_register_cancel(w, CACHE_CANCEL_BUTTON);
+ ro_gui_wimp_event_register_ok(w, CACHE_OK_BUTTON,
+ ro_gui_options_cache_ok);
+ ro_gui_wimp_event_set_help_prefix(w, "HelpCacheConfig");
+ ro_gui_wimp_event_memorise(w);
+ return true;
+
+}
+
+bool ro_gui_options_cache_click(wimp_pointer *pointer)
+{
+ switch (pointer->i) {
+ case CACHE_DEFAULT_BUTTON:
+ /* set the default values */
+ ro_gui_set_icon_decimal(pointer->w, CACHE_MEMORY_SIZE,
+ 120, 1);
+ ro_gui_set_icon_decimal(pointer->w, CACHE_DISC_SIZE,
+ 1024, 0);
+ ro_gui_set_icon_decimal(pointer->w, CACHE_DISC_EXPIRE,
+ 28, 0);
+ return true;
+ }
+ return false;
+}
+
+bool ro_gui_options_cache_ok(wimp_w w)
+{
+ nsoption_set_int(memory_cache_size,
+ (((ro_gui_get_icon_decimal(w,
+ CACHE_MEMORY_SIZE, 1) + 1) << 20) - 1) / 10);
+ nsoption_set_uint(disc_cache_size,
+ (uint) (ro_gui_get_icon_decimal(w,
+ CACHE_DISC_SIZE, 0) << 20));
+ nsoption_set_int(disc_cache_age,
+ ro_gui_get_icon_decimal(w, CACHE_DISC_EXPIRE, 0));
+
+ ro_gui_save_options();
+ return true;
+}
diff --git a/frontends/riscos/configure/con_connect.c b/frontends/riscos/configure/con_connect.c
new file mode 100644
index 000000000..9515c5d6f
--- /dev/null
+++ b/frontends/riscos/configure/con_connect.c
@@ -0,0 +1,220 @@
+/*
+ * Copyright 2006 Richard Wilson <info@tinct.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdbool.h>
+#include "swis.h"
+#include "oslib/osspriteop.h"
+#include "oslib/wimp.h"
+
+#include "utils/nsoption.h"
+#include "utils/log.h"
+
+#include "riscos/configure/configure.h"
+#include "riscos/dialog.h"
+#include "riscos/menus.h"
+#include "riscos/tinct.h"
+#include "riscos/wimp.h"
+#include "riscos/wimp_event.h"
+
+
+#define CONNECTION_PROXY_FIELD 3
+#define CONNECTION_PROXY_MENU 4
+#define CONNECTION_PROXY_HOST_LABEL 5
+#define CONNECTION_PROXY_HOST 6
+#define CONNECTION_PROXY_PORT_LABEL 7
+#define CONNECTION_PROXY_PORT 8
+#define CONNECTION_PROXY_USERNAME_LABEL 9
+#define CONNECTION_PROXY_USERNAME 10
+#define CONNECTION_PROXY_PASSWORD_LABEL 11
+#define CONNECTION_PROXY_PASSWORD 12
+#define CONNECTION_MAX_FETCH_FIELD 16
+#define CONNECTION_MAX_FETCH_DEC 17
+#define CONNECTION_MAX_FETCH_INC 18
+#define CONNECTION_HOST_FETCH_FIELD 20
+#define CONNECTION_HOST_FETCH_DEC 21
+#define CONNECTION_HOST_FETCH_INC 22
+#define CONNECTION_CACHE_FETCH_FIELD 24
+#define CONNECTION_CACHE_FETCH_DEC 25
+#define CONNECTION_CACHE_FETCH_INC 26
+#define CONNECTION_DEFAULT_BUTTON 27
+#define CONNECTION_CANCEL_BUTTON 28
+#define CONNECTION_OK_BUTTON 29
+
+#define http_proxy_type (nsoption_bool(http_proxy) ? (nsoption_int(http_proxy_auth) + 1) : 0)
+
+static int ro_gui_options_connection_proxy_type(wimp_w w);
+static void ro_gui_options_connection_default(wimp_pointer *pointer);
+static bool ro_gui_options_connection_ok(wimp_w w);
+static bool ro_gui_options_connection_update(wimp_w w, wimp_i i, wimp_menu *m,
+ wimp_selection *s, menu_action a);
+
+bool ro_gui_options_connection_initialise(wimp_w w)
+{
+ int proxy_type;
+
+ /* set the current values */
+ proxy_type = (nsoption_bool(http_proxy) ? (nsoption_int(http_proxy_auth) + 1) : 0);
+ ro_gui_set_icon_string(w, CONNECTION_PROXY_FIELD,
+ proxy_type_menu->entries[proxy_type].
+ data.indirected_text.text, true);
+ ro_gui_set_icon_string(w, CONNECTION_PROXY_HOST,
+ nsoption_charp(http_proxy_host) ?
+ nsoption_charp(http_proxy_host) : "", true);
+ ro_gui_set_icon_integer(w, CONNECTION_PROXY_PORT,
+ nsoption_int(http_proxy_port));
+ ro_gui_set_icon_string(w, CONNECTION_PROXY_USERNAME,
+ nsoption_charp(http_proxy_auth_user) ?
+ nsoption_charp(http_proxy_auth_user) : "", true);
+ ro_gui_set_icon_string(w, CONNECTION_PROXY_PASSWORD,
+ nsoption_charp(http_proxy_auth_pass) ?
+ nsoption_charp(http_proxy_auth_pass) : "", true);
+ ro_gui_set_icon_integer(w, CONNECTION_MAX_FETCH_FIELD,
+ nsoption_int(max_fetchers));
+ ro_gui_set_icon_integer(w, CONNECTION_HOST_FETCH_FIELD,
+ nsoption_int(max_fetchers_per_host));
+ ro_gui_set_icon_integer(w, CONNECTION_CACHE_FETCH_FIELD,
+ nsoption_int(max_cached_fetch_handles));
+ ro_gui_options_connection_update(w, -1, NULL, NULL, NO_ACTION);
+
+ /* register icons */
+ ro_gui_wimp_event_register_menu_gright(w, CONNECTION_PROXY_FIELD,
+ CONNECTION_PROXY_MENU, proxy_type_menu);
+ ro_gui_wimp_event_register_text_field(w, CONNECTION_PROXY_HOST_LABEL);
+ ro_gui_wimp_event_register_text_field(w, CONNECTION_PROXY_HOST);
+ ro_gui_wimp_event_register_text_field(w, CONNECTION_PROXY_PORT_LABEL);
+ ro_gui_wimp_event_register_text_field(w, CONNECTION_PROXY_PORT);
+ ro_gui_wimp_event_register_text_field(w, CONNECTION_PROXY_USERNAME_LABEL);
+ ro_gui_wimp_event_register_text_field(w, CONNECTION_PROXY_USERNAME);
+ ro_gui_wimp_event_register_text_field(w, CONNECTION_PROXY_PASSWORD_LABEL);
+ ro_gui_wimp_event_register_text_field(w, CONNECTION_PROXY_PASSWORD);
+ ro_gui_wimp_event_register_numeric_field(w, CONNECTION_MAX_FETCH_FIELD,
+ CONNECTION_MAX_FETCH_INC, CONNECTION_MAX_FETCH_DEC,
+ 1, 99, 1, 0);
+ ro_gui_wimp_event_register_numeric_field(w, CONNECTION_HOST_FETCH_FIELD,
+ CONNECTION_HOST_FETCH_INC, CONNECTION_HOST_FETCH_DEC,
+ 1, 99, 1, 0);
+ ro_gui_wimp_event_register_numeric_field(w, CONNECTION_CACHE_FETCH_FIELD,
+ CONNECTION_CACHE_FETCH_INC, CONNECTION_CACHE_FETCH_DEC,
+ 1, 99, 1, 0);
+ ro_gui_wimp_event_register_menu_selection(w,
+ ro_gui_options_connection_update);
+ ro_gui_wimp_event_register_button(w, CONNECTION_DEFAULT_BUTTON,
+ ro_gui_options_connection_default);
+ ro_gui_wimp_event_register_cancel(w, CONNECTION_CANCEL_BUTTON);
+ ro_gui_wimp_event_register_ok(w, CONNECTION_OK_BUTTON,
+ ro_gui_options_connection_ok);
+
+ ro_gui_wimp_event_set_help_prefix(w, "HelpConnectConfig");
+ ro_gui_wimp_event_memorise(w);
+ return true;
+
+}
+
+bool ro_gui_options_connection_update(wimp_w w, wimp_i i, wimp_menu *m,
+ wimp_selection *s, menu_action a)
+{
+ int proxy_type;
+ bool host, user;
+
+ /* update the shaded state */
+ proxy_type = ro_gui_options_connection_proxy_type(w);
+ host = (proxy_type > 0);
+ user = (proxy_type > 1);
+
+ ro_gui_set_icon_shaded_state(w, CONNECTION_PROXY_HOST_LABEL, !host);
+ ro_gui_set_icon_shaded_state(w, CONNECTION_PROXY_HOST, !host);
+ ro_gui_set_icon_shaded_state(w, CONNECTION_PROXY_PORT_LABEL, !host);
+ ro_gui_set_icon_shaded_state(w, CONNECTION_PROXY_PORT, !host);
+ ro_gui_set_icon_shaded_state(w, CONNECTION_PROXY_USERNAME_LABEL, !user);
+ ro_gui_set_icon_shaded_state(w, CONNECTION_PROXY_USERNAME, !user);
+ ro_gui_set_icon_shaded_state(w, CONNECTION_PROXY_PASSWORD_LABEL, !user);
+ ro_gui_set_icon_shaded_state(w, CONNECTION_PROXY_PASSWORD, !user);
+
+ return true;
+}
+
+int ro_gui_options_connection_proxy_type(wimp_w w)
+{
+ const char *text;
+ int i;
+
+ text = ro_gui_get_icon_string(w, CONNECTION_PROXY_FIELD);
+ for (i = 0; (i < 4); i++)
+ if (!strcmp(text, proxy_type_menu->entries[i].
+ data.indirected_text.text))
+ return i;
+ assert(false);
+}
+
+void ro_gui_options_connection_default(wimp_pointer *pointer)
+{
+ ro_gui_set_icon_string(pointer->w, CONNECTION_PROXY_FIELD,
+ proxy_type_menu->entries[0].
+ data.indirected_text.text, true);
+ ro_gui_set_icon_string(pointer->w, CONNECTION_PROXY_HOST, "", true);
+ ro_gui_set_icon_integer(pointer->w, CONNECTION_PROXY_PORT, 8080);
+ ro_gui_set_icon_string(pointer->w, CONNECTION_PROXY_USERNAME, "", true);
+ ro_gui_set_icon_string(pointer->w, CONNECTION_PROXY_PASSWORD, "", true);
+ ro_gui_set_icon_integer(pointer->w, CONNECTION_MAX_FETCH_FIELD, 24);
+ ro_gui_set_icon_integer(pointer->w, CONNECTION_HOST_FETCH_FIELD, 5);
+ ro_gui_set_icon_integer(pointer->w, CONNECTION_CACHE_FETCH_FIELD, 6);
+ ro_gui_options_connection_update(pointer->w, -1, NULL, NULL, NO_ACTION);
+}
+
+bool ro_gui_options_connection_ok(wimp_w w)
+{
+ int proxy_type;
+
+ proxy_type = ro_gui_options_connection_proxy_type(w);
+ if (proxy_type == 0) {
+ nsoption_set_bool(http_proxy, false);
+ } else {
+ nsoption_set_bool(http_proxy, true);
+ nsoption_set_int(http_proxy_auth, proxy_type - 1);
+ }
+
+ nsoption_set_charp(http_proxy_host,
+ strdup(ro_gui_get_icon_string(w,
+ CONNECTION_PROXY_HOST)));
+
+ nsoption_set_int(http_proxy_port,
+ ro_gui_get_icon_decimal(w, CONNECTION_PROXY_PORT, 0));
+
+ nsoption_set_charp(http_proxy_auth_user,
+ strdup(ro_gui_get_icon_string(w,
+ CONNECTION_PROXY_USERNAME)));
+
+ nsoption_set_charp(http_proxy_auth_pass,
+ strdup(ro_gui_get_icon_string(w,
+ CONNECTION_PROXY_PASSWORD)));
+
+ nsoption_set_int(max_fetchers,
+ ro_gui_get_icon_decimal(w,
+ CONNECTION_MAX_FETCH_FIELD, 0));
+
+ nsoption_set_int(max_fetchers_per_host,
+ ro_gui_get_icon_decimal(w,
+ CONNECTION_HOST_FETCH_FIELD, 0));
+
+ nsoption_set_int(max_cached_fetch_handles,
+ ro_gui_get_icon_decimal(w,
+ CONNECTION_CACHE_FETCH_FIELD, 0));
+
+ ro_gui_save_options();
+ return true;
+}
diff --git a/frontends/riscos/configure/con_content.c b/frontends/riscos/configure/con_content.c
new file mode 100644
index 000000000..50bbd15ef
--- /dev/null
+++ b/frontends/riscos/configure/con_content.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2006 Richard Wilson <info@tinct.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdbool.h>
+
+#include "utils/nsoption.h"
+#include "utils/messages.h"
+
+#include "riscos/gui.h"
+#include "riscos/wimp.h"
+#include "riscos/wimp_event.h"
+#include "riscos/configure.h"
+#include "riscos/configure/configure.h"
+#include "riscos/dialog.h"
+
+#define CONTENT_BLOCK_ADVERTISEMENTS 2
+#define CONTENT_BLOCK_POPUPS 3
+#define CONTENT_NO_PLUGINS 4
+#define CONTENT_TARGET_BLANK 7
+#define CONTENT_DEFAULT_BUTTON 8
+#define CONTENT_CANCEL_BUTTON 9
+#define CONTENT_OK_BUTTON 10
+#define CONTENT_NO_JAVASCRIPT 11
+
+static void ro_gui_options_content_default(wimp_pointer *pointer);
+static bool ro_gui_options_content_ok(wimp_w w);
+
+bool ro_gui_options_content_initialise(wimp_w w)
+{
+ /* set the current values */
+ ro_gui_set_icon_selected_state(w, CONTENT_BLOCK_ADVERTISEMENTS,
+ nsoption_bool(block_advertisements));
+ ro_gui_set_icon_selected_state(w, CONTENT_BLOCK_POPUPS,
+ nsoption_bool(block_popups));
+ ro_gui_set_icon_selected_state(w, CONTENT_NO_PLUGINS,
+ nsoption_bool(no_plugins));
+ ro_gui_set_icon_selected_state(w, CONTENT_TARGET_BLANK,
+ nsoption_bool(target_blank));
+ ro_gui_set_icon_selected_state(w, CONTENT_NO_JAVASCRIPT,
+ !nsoption_bool(enable_javascript));
+
+ /* initialise all functions for a newly created window */
+ ro_gui_wimp_event_register_checkbox(w, CONTENT_BLOCK_ADVERTISEMENTS);
+ ro_gui_wimp_event_register_checkbox(w, CONTENT_BLOCK_POPUPS);
+ ro_gui_wimp_event_register_checkbox(w, CONTENT_NO_PLUGINS);
+ ro_gui_wimp_event_register_checkbox(w, CONTENT_TARGET_BLANK);
+ ro_gui_wimp_event_register_checkbox(w, CONTENT_NO_JAVASCRIPT);
+ ro_gui_wimp_event_register_button(w, CONTENT_DEFAULT_BUTTON,
+ ro_gui_options_content_default);
+ ro_gui_wimp_event_register_cancel(w, CONTENT_CANCEL_BUTTON);
+ ro_gui_wimp_event_register_ok(w, CONTENT_OK_BUTTON,
+ ro_gui_options_content_ok);
+ ro_gui_wimp_event_set_help_prefix(w, "HelpContentConfig");
+ ro_gui_wimp_event_memorise(w);
+ return true;
+
+}
+
+void ro_gui_options_content_default(wimp_pointer *pointer)
+{
+ /* set the default values */
+ ro_gui_set_icon_selected_state(pointer->w, CONTENT_BLOCK_ADVERTISEMENTS,
+ false);
+ ro_gui_set_icon_selected_state(pointer->w, CONTENT_BLOCK_POPUPS,
+ false);
+ ro_gui_set_icon_selected_state(pointer->w, CONTENT_NO_PLUGINS,
+ false);
+ ro_gui_set_icon_selected_state(pointer->w, CONTENT_TARGET_BLANK,
+ true);
+ ro_gui_set_icon_selected_state(pointer->w, CONTENT_NO_JAVASCRIPT,
+ false);
+}
+
+bool ro_gui_options_content_ok(wimp_w w)
+{
+ nsoption_set_bool(block_advertisements,
+ ro_gui_get_icon_selected_state(w, CONTENT_BLOCK_ADVERTISEMENTS));
+
+ nsoption_set_bool(block_popups,
+ ro_gui_get_icon_selected_state(w, CONTENT_BLOCK_POPUPS));
+ nsoption_set_bool(no_plugins,
+ ro_gui_get_icon_selected_state(w, CONTENT_NO_PLUGINS));
+
+ nsoption_set_bool(target_blank,
+ ro_gui_get_icon_selected_state(w, CONTENT_TARGET_BLANK));
+
+ nsoption_set_bool(enable_javascript,
+ !ro_gui_get_icon_selected_state(w, CONTENT_NO_JAVASCRIPT));
+
+ ro_gui_save_options();
+ return true;
+}
diff --git a/frontends/riscos/configure/con_fonts.c b/frontends/riscos/configure/con_fonts.c
new file mode 100644
index 000000000..280312843
--- /dev/null
+++ b/frontends/riscos/configure/con_fonts.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2005 Richard Wilson <info@tinct.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdbool.h>
+#include <stddef.h>
+
+#include "utils/nsoption.h"
+#include "utils/messages.h"
+#include "desktop/plot_style.h"
+
+#include "riscos/gui.h"
+#include "riscos/font.h"
+#include "riscos/menus.h"
+#include "riscos/wimp.h"
+#include "riscos/wimp_event.h"
+#include "riscos/configure.h"
+#include "riscos/configure/configure.h"
+#include "riscos/dialog.h"
+
+
+#define FONT_SANS_FIELD 3
+#define FONT_SANS_MENU 4
+#define FONT_SERIF_FIELD 6
+#define FONT_SERIF_MENU 7
+#define FONT_MONOSPACE_FIELD 9
+#define FONT_MONOSPACE_MENU 10
+#define FONT_CURSIVE_FIELD 12
+#define FONT_CURSIVE_MENU 13
+#define FONT_FANTASY_FIELD 15
+#define FONT_FANTASY_MENU 16
+#define FONT_DEFAULT_FIELD 18
+#define FONT_DEFAULT_MENU 19
+#define FONT_DEFAULT_SIZE 23
+#define FONT_DEFAULT_DEC 24
+#define FONT_DEFAULT_INC 25
+#define FONT_MINIMUM_SIZE 28
+#define FONT_MINIMUM_DEC 29
+#define FONT_MINIMUM_INC 30
+#define FONT_DEFAULT_BUTTON 32
+#define FONT_CANCEL_BUTTON 33
+#define FONT_OK_BUTTON 34
+
+/* This menu only ever gets created once */
+/** \todo The memory claimed for this menu should
+ * probably be released at some point */
+static wimp_menu *default_menu;
+
+static const char *font_names[PLOT_FONT_FAMILY_COUNT] = {
+ "Sans-serif",
+ "Serif",
+ "Monospace",
+ "Cursive",
+ "Fantasy"
+};
+
+static void ro_gui_options_fonts_default(wimp_pointer *pointer);
+static bool ro_gui_options_fonts_ok(wimp_w w);
+static bool ro_gui_options_fonts_init_menu(void);
+
+bool ro_gui_options_fonts_initialise(wimp_w w)
+{
+ /* set the current values */
+ ro_gui_set_icon_decimal(w, FONT_DEFAULT_SIZE, nsoption_int(font_size), 1);
+ ro_gui_set_icon_decimal(w, FONT_MINIMUM_SIZE, nsoption_int(font_min_size), 1);
+ ro_gui_set_icon_string(w, FONT_SANS_FIELD, nsoption_charp(font_sans), true);
+ ro_gui_set_icon_string(w, FONT_SERIF_FIELD, nsoption_charp(font_serif), true);
+ ro_gui_set_icon_string(w, FONT_MONOSPACE_FIELD, nsoption_charp(font_mono), true);
+ ro_gui_set_icon_string(w, FONT_CURSIVE_FIELD, nsoption_charp(font_cursive), true);
+ ro_gui_set_icon_string(w, FONT_FANTASY_FIELD, nsoption_charp(font_fantasy), true);
+ ro_gui_set_icon_string(w, FONT_DEFAULT_FIELD,
+ font_names[nsoption_int(font_default)], true);
+
+ if (!ro_gui_options_fonts_init_menu())
+ return false;
+
+ /* initialise all functions for a newly created window */
+ ro_gui_wimp_event_register_menu_gright(w, FONT_SANS_FIELD,
+ FONT_SANS_MENU, rufl_family_menu);
+ ro_gui_wimp_event_register_menu_gright(w, FONT_SERIF_FIELD,
+ FONT_SERIF_MENU, rufl_family_menu);
+ ro_gui_wimp_event_register_menu_gright(w, FONT_MONOSPACE_FIELD,
+ FONT_MONOSPACE_MENU, rufl_family_menu);
+ ro_gui_wimp_event_register_menu_gright(w, FONT_CURSIVE_FIELD,
+ FONT_CURSIVE_MENU, rufl_family_menu);
+ ro_gui_wimp_event_register_menu_gright(w, FONT_FANTASY_FIELD,
+ FONT_FANTASY_MENU, rufl_family_menu);
+ ro_gui_wimp_event_register_menu_gright(w, FONT_DEFAULT_FIELD,
+ FONT_DEFAULT_MENU, default_menu);
+ ro_gui_wimp_event_register_numeric_field(w, FONT_DEFAULT_SIZE,
+ FONT_DEFAULT_INC, FONT_DEFAULT_DEC, 50, 1000, 1, 1);
+ ro_gui_wimp_event_register_numeric_field(w, FONT_MINIMUM_SIZE,
+ FONT_MINIMUM_INC, FONT_MINIMUM_DEC, 10, 500, 1, 1);
+ ro_gui_wimp_event_register_button(w, FONT_DEFAULT_BUTTON,
+ ro_gui_options_fonts_default);
+ ro_gui_wimp_event_register_cancel(w, FONT_CANCEL_BUTTON);
+ ro_gui_wimp_event_register_ok(w, FONT_OK_BUTTON,
+ ro_gui_options_fonts_ok);
+ ro_gui_wimp_event_set_help_prefix(w, "HelpFontConfig");
+ ro_gui_wimp_event_memorise(w);
+ return true;
+
+}
+
+void ro_gui_options_fonts_default(wimp_pointer *pointer)
+{
+ const char *fallback = nsfont_fallback_font();
+
+ /* set the default values */
+ ro_gui_set_icon_decimal(pointer->w, FONT_DEFAULT_SIZE, 128, 1);
+ ro_gui_set_icon_decimal(pointer->w, FONT_MINIMUM_SIZE, 85, 1);
+ ro_gui_set_icon_string(pointer->w, FONT_SANS_FIELD,
+ nsfont_exists("Homerton") ? "Homerton" : fallback, true);
+ ro_gui_set_icon_string(pointer->w, FONT_SERIF_FIELD,
+ nsfont_exists("Trinity") ? "Trinity" : fallback, true);
+ ro_gui_set_icon_string(pointer->w, FONT_MONOSPACE_FIELD,
+ nsfont_exists("Corpus") ? "Corpus" : fallback, true);
+ ro_gui_set_icon_string(pointer->w, FONT_CURSIVE_FIELD,
+ nsfont_exists("Churchill") ? "Churchill" : fallback, true);
+ ro_gui_set_icon_string(pointer->w, FONT_FANTASY_FIELD,
+ nsfont_exists("Sassoon") ? "Sassoon" : fallback, true);
+ ro_gui_set_icon_string(pointer->w, FONT_DEFAULT_FIELD,
+ font_names[0], true);
+}
+
+bool ro_gui_options_fonts_ok(wimp_w w)
+{
+ unsigned int i;
+
+ nsoption_set_int(font_size,
+ ro_gui_get_icon_decimal(w, FONT_DEFAULT_SIZE, 1));
+
+ nsoption_set_int(font_min_size,
+ ro_gui_get_icon_decimal(w, FONT_MINIMUM_SIZE, 1));
+
+ if (nsoption_int(font_size) < nsoption_int(font_min_size)) {
+ nsoption_set_int(font_size, nsoption_int(font_min_size));
+ ro_gui_set_icon_decimal(w, FONT_DEFAULT_SIZE, nsoption_int(font_size), 1);
+
+}
+
+ nsoption_set_charp(font_sans,
+ strdup(ro_gui_get_icon_string(w, FONT_SANS_FIELD)));
+
+ nsoption_set_charp(font_serif,
+ strdup(ro_gui_get_icon_string(w, FONT_SERIF_FIELD)));
+
+ nsoption_set_charp(font_mono,
+ strdup(ro_gui_get_icon_string(w, FONT_MONOSPACE_FIELD)));
+
+ nsoption_set_charp(font_cursive,
+ strdup(ro_gui_get_icon_string(w, FONT_CURSIVE_FIELD)));
+
+ nsoption_set_charp(font_fantasy,
+ strdup(ro_gui_get_icon_string(w, FONT_FANTASY_FIELD)));
+
+ for (i = 0; i != 5; i++) {
+ if (!strcmp(font_names[i], ro_gui_get_icon_string(w,
+ FONT_DEFAULT_FIELD)))
+ break;
+ }
+ if (i == 5)
+ /* this should never happen, but still */
+ i = 0;
+
+ nsoption_set_int(font_default, i);
+
+ ro_gui_save_options();
+ return true;
+}
+
+bool ro_gui_options_fonts_init_menu(void)
+{
+ unsigned int i;
+
+ if (default_menu)
+ /* Already exists */
+ return true;
+
+ default_menu = malloc(wimp_SIZEOF_MENU(5));
+ if (!default_menu) {
+ ro_warn_user("NoMemory", 0);
+ return false;
+ }
+ default_menu->title_data.indirected_text.text =
+ (char *) messages_get("DefaultFonts");
+ ro_gui_menu_init_structure(default_menu, 5);
+ for (i = 0; i < 5; i++) {
+ default_menu->entries[i].data.indirected_text.text =
+ (char *) font_names[i];
+ default_menu->entries[i].data.indirected_text.size =
+ strlen(font_names[i]);
+ }
+ return true;
+}
diff --git a/frontends/riscos/configure/con_home.c b/frontends/riscos/configure/con_home.c
new file mode 100644
index 000000000..ea8e243ed
--- /dev/null
+++ b/frontends/riscos/configure/con_home.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2005 Richard Wilson <info@tinct.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include "utils/messages.h"
+#include "utils/nsoption.h"
+
+#include "riscos/gui.h"
+#include "riscos/menus.h"
+#include "riscos/url_suggest.h"
+#include "riscos/wimp.h"
+#include "riscos/wimp_event.h"
+#include "riscos/configure.h"
+#include "riscos/configure/configure.h"
+#include "riscos/dialog.h"
+
+#define HOME_URL_FIELD 3
+#define HOME_URL_GRIGHT 4
+#define HOME_OPEN_STARTUP 5
+#define HOME_DEFAULT_BUTTON 6
+#define HOME_CANCEL_BUTTON 7
+#define HOME_OK_BUTTON 8
+
+static void ro_gui_options_home_default(wimp_pointer *pointer);
+static bool ro_gui_options_home_ok(wimp_w w);
+static bool ro_gui_options_home_menu_prepare(wimp_w w, wimp_i i,
+ wimp_menu *menu, wimp_pointer *pointer);
+
+bool ro_gui_options_home_initialise(wimp_w w)
+{
+ /* set the current values */
+ ro_gui_set_icon_string(w, HOME_URL_FIELD,
+ nsoption_charp(homepage_url) ?
+ nsoption_charp(homepage_url) : "", true);
+
+ ro_gui_set_icon_selected_state(w, HOME_OPEN_STARTUP,
+ nsoption_bool(open_browser_at_startup));
+
+ ro_gui_set_icon_shaded_state(w,
+ HOME_URL_GRIGHT, !ro_gui_url_suggest_prepare_menu());
+
+ /* initialise all functions for a newly created window */
+ ro_gui_wimp_event_register_menu_gright(w, HOME_URL_FIELD,
+ HOME_URL_GRIGHT, ro_gui_url_suggest_menu);
+ ro_gui_wimp_event_register_checkbox(w, HOME_OPEN_STARTUP);
+ ro_gui_wimp_event_register_button(w, HOME_DEFAULT_BUTTON,
+ ro_gui_options_home_default);
+ ro_gui_wimp_event_register_cancel(w, HOME_CANCEL_BUTTON);
+ ro_gui_wimp_event_register_ok(w, HOME_OK_BUTTON,
+ ro_gui_options_home_ok);
+ ro_gui_wimp_event_register_menu_prepare(w,
+ ro_gui_options_home_menu_prepare);
+ ro_gui_wimp_event_set_help_prefix(w, "HelpHomeConfig");
+ ro_gui_wimp_event_memorise(w);
+ return true;
+
+}
+
+void ro_gui_options_home_default(wimp_pointer *pointer)
+{
+ /* set the default values */
+ ro_gui_set_icon_string(pointer->w, HOME_URL_FIELD, "", true);
+ ro_gui_set_icon_selected_state(pointer->w, HOME_OPEN_STARTUP, false);
+}
+
+bool ro_gui_options_home_ok(wimp_w w)
+{
+ nsoption_set_charp(homepage_url,
+ strdup(ro_gui_get_icon_string(w, HOME_URL_FIELD)));
+
+ nsoption_set_bool(open_browser_at_startup,
+ ro_gui_get_icon_selected_state(w, HOME_OPEN_STARTUP));
+
+ ro_gui_save_options();
+ return true;
+}
+
+
+/**
+ * Callback to prepare menus in the Configure Home dialog. At present, this
+ * only has to handle the URL Suggestion pop-up.
+ *
+ * \param w The window handle owning the menu.
+ * \param i The icon handle owning the menu.
+ * \param *menu The menu to be prepared.
+ * \param *pointer The associated mouse click event block, or NULL
+ * on an Adjust-click re-opening.
+ * \return true if the event was handled; false if not.
+ */
+
+bool ro_gui_options_home_menu_prepare(wimp_w w, wimp_i i, wimp_menu *menu,
+ wimp_pointer *pointer)
+{
+ if (menu != ro_gui_url_suggest_menu || i != HOME_URL_GRIGHT)
+ return false;
+
+ if (pointer != NULL)
+ ro_gui_url_suggest_prepare_menu();
+
+ return true;
+}
diff --git a/frontends/riscos/configure/con_image.c b/frontends/riscos/configure/con_image.c
new file mode 100644
index 000000000..49dd4f76d
--- /dev/null
+++ b/frontends/riscos/configure/con_image.c
@@ -0,0 +1,269 @@
+/*
+ * Copyright 2006 Richard Wilson <info@tinct.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdbool.h>
+#include <swis.h>
+#include <oslib/osspriteop.h>
+#include <oslib/wimp.h>
+
+#include "utils/nsoption.h"
+#include "utils/log.h"
+
+#include "riscos/gui.h"
+#include "riscos/configure/configure.h"
+#include "riscos/dialog.h"
+#include "riscos/menus.h"
+#include "riscos/tinct.h"
+#include "riscos/wimp.h"
+#include "riscos/wimp_event.h"
+
+
+#define IMAGE_FOREGROUND_FIELD 3
+#define IMAGE_FOREGROUND_MENU 4
+#define IMAGE_BACKGROUND_FIELD 6
+#define IMAGE_BACKGROUND_MENU 7
+#define IMAGE_CURRENT_DISPLAY 8
+#define IMAGE_SPEED_TEXT 11
+#define IMAGE_SPEED_FIELD 12
+#define IMAGE_SPEED_DEC 13
+#define IMAGE_SPEED_INC 14
+#define IMAGE_SPEED_CS 15
+#define IMAGE_DISABLE_ANIMATION 16
+#define IMAGE_DEFAULT_BUTTON 17
+#define IMAGE_CANCEL_BUTTON 18
+#define IMAGE_OK_BUTTON 19
+
+static bool ro_gui_options_image_click(wimp_pointer *pointer);
+static bool ro_gui_options_image_ok(wimp_w w);
+static void ro_gui_options_image_redraw(wimp_draw *redraw);
+static bool ro_gui_options_image_update(wimp_w w, wimp_i i, wimp_menu *m,
+ wimp_selection *s, menu_action a);
+static void ro_gui_options_image_read(wimp_w w, unsigned int *bg,
+ unsigned int *fg);
+static void ro_gui_options_update_shading(wimp_w w);
+
+static osspriteop_area *example_images;
+int example_users = 0;
+unsigned int tinct_options[] = {tinct_USE_OS_SPRITE_OP, 0, tinct_DITHER,
+ tinct_ERROR_DIFFUSE};
+
+bool ro_gui_options_image_initialise(wimp_w w)
+{
+ int i;
+
+ /* load the sprite file */
+ if (example_users == 0) {
+ char pathname[256];
+ snprintf(pathname, 256, "%s.Resources.Image", NETSURF_DIR);
+ pathname[255] = '\0';
+ example_images = ro_gui_load_sprite_file(pathname);
+ if (!example_images)
+ return false;
+ }
+ example_users++;
+
+ /* set the current values */
+ for (i = 0; (i < 4); i++) {
+ if ((unsigned int)nsoption_int(plot_fg_quality) == tinct_options[i])
+ ro_gui_set_icon_string(w, IMAGE_FOREGROUND_FIELD,
+ image_quality_menu->entries[i].
+ data.indirected_text.text, true);
+ if ((unsigned int)nsoption_int(plot_bg_quality) == tinct_options[i])
+ ro_gui_set_icon_string(w, IMAGE_BACKGROUND_FIELD,
+ image_quality_menu->entries[i].
+ data.indirected_text.text, true);
+ }
+ ro_gui_set_icon_decimal(w, IMAGE_SPEED_FIELD,
+ nsoption_int(minimum_gif_delay), 2);
+ ro_gui_set_icon_selected_state(w, IMAGE_DISABLE_ANIMATION,
+ !nsoption_bool(animate_images));
+ ro_gui_options_update_shading(w);
+
+ /* register icons */
+ ro_gui_wimp_event_register_menu_gright(w, IMAGE_FOREGROUND_FIELD,
+ IMAGE_FOREGROUND_MENU, image_quality_menu);
+ ro_gui_wimp_event_register_menu_gright(w, IMAGE_BACKGROUND_FIELD,
+ IMAGE_BACKGROUND_MENU, image_quality_menu);
+ ro_gui_wimp_event_register_text_field(w, IMAGE_SPEED_TEXT);
+ ro_gui_wimp_event_register_numeric_field(w, IMAGE_SPEED_FIELD,
+ IMAGE_SPEED_INC, IMAGE_SPEED_DEC, 0, 6000, 10, 2);
+ ro_gui_wimp_event_register_checkbox(w, IMAGE_DISABLE_ANIMATION);
+ ro_gui_wimp_event_register_text_field(w, IMAGE_SPEED_CS);
+ ro_gui_wimp_event_register_redraw_window(w,
+ ro_gui_options_image_redraw);
+ ro_gui_wimp_event_register_mouse_click(w,
+ ro_gui_options_image_click);
+ ro_gui_wimp_event_register_menu_selection(w,
+ ro_gui_options_image_update);
+ ro_gui_wimp_event_register_cancel(w, IMAGE_CANCEL_BUTTON);
+ ro_gui_wimp_event_register_ok(w, IMAGE_OK_BUTTON,
+ ro_gui_options_image_ok);
+ ro_gui_wimp_event_set_help_prefix(w, "HelpImageConfig");
+ ro_gui_wimp_event_memorise(w);
+
+ return true;
+}
+
+void ro_gui_options_image_finalise(wimp_w w)
+{
+ example_users--;
+ if (example_users == 0) {
+ free(example_images);
+ example_images = NULL;
+ }
+ ro_gui_wimp_event_finalise(w);
+}
+
+bool ro_gui_options_image_update(wimp_w w, wimp_i i, wimp_menu *m,
+ wimp_selection *s, menu_action a)
+{
+ ro_gui_redraw_icon(w, IMAGE_CURRENT_DISPLAY);
+
+ return true;
+}
+
+void ro_gui_options_image_redraw(wimp_draw *redraw)
+{
+ osbool more;
+ os_error *error;
+ wimp_icon_state icon_state;
+ osspriteop_header *bg = NULL, *fg = NULL;
+ unsigned int bg_tinct = 0, fg_tinct = 0;
+
+ /* get the icon location */
+ icon_state.w = redraw->w;
+ icon_state.i = IMAGE_CURRENT_DISPLAY;
+ error = xwimp_get_icon_state(&icon_state);
+ if (error) {
+ LOG("xwimp_get_icon_state: 0x%x: %s",
+ error->errnum, error->errmess);
+ ro_warn_user("MenuError", error->errmess);
+ return;
+ }
+
+ /* find the sprites */
+ if (example_images) {
+ ro_gui_options_image_read(redraw->w, &bg_tinct, &fg_tinct);
+ fg_tinct |= 0xeeeeee00;
+ xosspriteop_select_sprite(osspriteop_USER_AREA,
+ example_images, (osspriteop_id)"img_bg", &bg);
+ xosspriteop_select_sprite(osspriteop_USER_AREA,
+ example_images, (osspriteop_id)"img_fg", &fg);
+ }
+
+ /* perform the redraw */
+ more = wimp_redraw_window(redraw);
+ while (more) {
+ int origin_x, origin_y;
+ origin_x = redraw->box.x0 - redraw->xscroll +
+ icon_state.icon.extent.x0 + 2;
+ origin_y = redraw->box.y1 - redraw->yscroll +
+ icon_state.icon.extent.y0 + 2;
+ if (bg)
+ _swix(Tinct_Plot, _INR(2,4) | _IN(7),
+ bg, origin_x, origin_y, bg_tinct);
+ if (fg)
+ _swix(Tinct_PlotAlpha, _INR(2,4) | _IN(7),
+ fg, origin_x, origin_y, fg_tinct);
+ more = wimp_get_rectangle(redraw);
+ }
+}
+
+void ro_gui_options_image_read(wimp_w w, unsigned int *bg, unsigned int *fg)
+{
+ const char *text;
+ int i;
+
+ text = ro_gui_get_icon_string(w, IMAGE_FOREGROUND_FIELD);
+ for (i = 0; i < 4; i++)
+ if (!strcmp(text, image_quality_menu->entries[i].
+ data.indirected_text.text))
+ *fg = tinct_options[i];
+
+ text = ro_gui_get_icon_string(w, IMAGE_BACKGROUND_FIELD);
+ for (i = 0; i < 4; i++)
+ if (!strcmp(text, image_quality_menu->entries[i].
+ data.indirected_text.text))
+ *bg = tinct_options[i];
+}
+
+bool ro_gui_options_image_click(wimp_pointer *pointer)
+{
+ unsigned int old_fg, old_bg, bg, fg;
+
+ ro_gui_options_image_read(pointer->w, &old_bg, &old_fg);
+ switch (pointer->i) {
+ case IMAGE_DEFAULT_BUTTON:
+ ro_gui_set_icon_string(pointer->w,
+ IMAGE_FOREGROUND_FIELD,
+ image_quality_menu->entries[3].
+ data.indirected_text.text, true);
+ ro_gui_set_icon_string(pointer->w,
+ IMAGE_BACKGROUND_FIELD,
+ image_quality_menu->entries[2].
+ data.indirected_text.text, true);
+ ro_gui_set_icon_decimal(pointer->w, IMAGE_SPEED_FIELD,
+ 10, 2);
+ ro_gui_set_icon_selected_state(pointer->w,
+ IMAGE_DISABLE_ANIMATION, false);
+ case IMAGE_DISABLE_ANIMATION:
+ ro_gui_options_update_shading(pointer->w);
+ break;
+ case IMAGE_CANCEL_BUTTON:
+ ro_gui_wimp_event_restore(pointer->w);
+ break;
+ default:
+ return false;
+ }
+
+ ro_gui_options_image_read(pointer->w, &bg, &fg);
+ if ((bg != old_bg) || (fg != old_fg))
+ ro_gui_options_image_update(pointer->w, pointer->i,
+ NULL, NULL, NO_ACTION);
+
+ return false;
+}
+
+void ro_gui_options_update_shading(wimp_w w)
+{
+ bool shaded;
+
+ shaded = ro_gui_get_icon_selected_state(w, IMAGE_DISABLE_ANIMATION);
+ ro_gui_set_icon_shaded_state(w, IMAGE_SPEED_TEXT, shaded);
+ ro_gui_set_icon_shaded_state(w, IMAGE_SPEED_FIELD, shaded);
+ ro_gui_set_icon_shaded_state(w, IMAGE_SPEED_DEC, shaded);
+ ro_gui_set_icon_shaded_state(w, IMAGE_SPEED_INC, shaded);
+ ro_gui_set_icon_shaded_state(w, IMAGE_SPEED_CS, shaded);
+}
+
+bool ro_gui_options_image_ok(wimp_w w)
+{
+ ro_gui_options_image_read(w,
+ (unsigned int *)&nsoption_int(plot_bg_quality),
+ (unsigned int *)&nsoption_int(plot_fg_quality));
+
+ nsoption_set_int(minimum_gif_delay,
+ ro_gui_get_icon_decimal(w, IMAGE_SPEED_FIELD, 2));
+
+ nsoption_set_bool(animate_images,
+ !ro_gui_get_icon_selected_state(w,
+ IMAGE_DISABLE_ANIMATION));
+ ro_gui_save_options();
+
+ return true;
+}
diff --git a/frontends/riscos/configure/con_inter.c b/frontends/riscos/configure/con_inter.c
new file mode 100644
index 000000000..7ab912c54
--- /dev/null
+++ b/frontends/riscos/configure/con_inter.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2006 Adrian Lees <adrianl@users.sourceforge.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdbool.h>
+
+#include "utils/nsoption.h"
+
+#include "riscos/gui.h"
+#include "riscos/wimp.h"
+#include "riscos/wimp_event.h"
+#include "riscos/configure.h"
+#include "riscos/configure/configure.h"
+#include "riscos/dialog.h"
+
+#define INTERFACE_STRIP_EXTNS_OPTION 2
+#define INTERFACE_CONFIRM_OVWR_OPTION 3
+#define INTERFACE_URL_COMPLETE_OPTION 6
+#define INTERFACE_HISTORY_TOOLTIP_OPTION 7
+#define INTERFACE_THUMBNAIL_ICONISE_OPTION 10
+#define INTERFACE_DEFAULT_BUTTON 11
+#define INTERFACE_CANCEL_BUTTON 12
+#define INTERFACE_OK_BUTTON 13
+#define INTERFACE_USE_EXTERNAL_HOTLIST 16
+#define INTERFACE_EXTERNAL_HOTLIST_APP 18
+
+
+static bool ro_gui_options_interface_click(wimp_pointer *pointer);
+static void ro_gui_options_interface_default(wimp_pointer *pointer);
+static bool ro_gui_options_interface_ok(wimp_w w);
+
+bool ro_gui_options_interface_initialise(wimp_w w)
+{
+ /* set the current values */
+ ro_gui_set_icon_selected_state(w, INTERFACE_STRIP_EXTNS_OPTION,
+ nsoption_bool(strip_extensions));
+ ro_gui_set_icon_selected_state(w, INTERFACE_CONFIRM_OVWR_OPTION,
+ nsoption_bool(confirm_overwrite));
+ ro_gui_set_icon_selected_state(w, INTERFACE_URL_COMPLETE_OPTION,
+ nsoption_bool(url_suggestion));
+ ro_gui_set_icon_selected_state(w, INTERFACE_HISTORY_TOOLTIP_OPTION,
+ nsoption_bool(history_tooltip));
+ ro_gui_set_icon_selected_state(w, INTERFACE_THUMBNAIL_ICONISE_OPTION,
+ nsoption_bool(thumbnail_iconise));
+ ro_gui_set_icon_selected_state(w, INTERFACE_USE_EXTERNAL_HOTLIST,
+ nsoption_bool(external_hotlists));
+ ro_gui_set_icon_string(w, INTERFACE_EXTERNAL_HOTLIST_APP,
+ (nsoption_charp(external_hotlist_app)) ?
+ nsoption_charp(external_hotlist_app) : "", false);
+
+ ro_gui_set_icon_shaded_state(w, INTERFACE_EXTERNAL_HOTLIST_APP,
+ !nsoption_bool(external_hotlists));
+
+ /* initialise all functions for a newly created window */
+ ro_gui_wimp_event_register_mouse_click(w,
+ ro_gui_options_interface_click);
+ ro_gui_wimp_event_register_button(w, INTERFACE_DEFAULT_BUTTON,
+ ro_gui_options_interface_default);
+ ro_gui_wimp_event_register_cancel(w, INTERFACE_CANCEL_BUTTON);
+ ro_gui_wimp_event_register_ok(w, INTERFACE_OK_BUTTON,
+ ro_gui_options_interface_ok);
+ ro_gui_wimp_event_set_help_prefix(w, "HelpInterfaceConfig");
+ ro_gui_wimp_event_memorise(w);
+ return true;
+
+}
+
+
+bool ro_gui_options_interface_click(wimp_pointer *pointer)
+{
+ bool shaded;
+
+ switch (pointer->i) {
+ case INTERFACE_USE_EXTERNAL_HOTLIST:
+ shaded = !ro_gui_get_icon_selected_state(pointer->w,
+ INTERFACE_USE_EXTERNAL_HOTLIST);
+ ro_gui_set_icon_shaded_state(pointer->w,
+ INTERFACE_EXTERNAL_HOTLIST_APP, shaded);
+ return false;
+ break;
+ }
+ return false;
+}
+
+
+
+void ro_gui_options_interface_default(wimp_pointer *pointer)
+{
+ ro_gui_set_icon_selected_state(pointer->w,
+ INTERFACE_STRIP_EXTNS_OPTION, true);
+ ro_gui_set_icon_selected_state(pointer->w,
+ INTERFACE_CONFIRM_OVWR_OPTION, true);
+ ro_gui_set_icon_selected_state(pointer->w,
+ INTERFACE_URL_COMPLETE_OPTION, true);
+ ro_gui_set_icon_selected_state(pointer->w,
+ INTERFACE_HISTORY_TOOLTIP_OPTION, true);
+ ro_gui_set_icon_selected_state(pointer->w,
+ INTERFACE_THUMBNAIL_ICONISE_OPTION, true);
+ ro_gui_set_icon_selected_state(pointer->w,
+ INTERFACE_USE_EXTERNAL_HOTLIST, false);
+ ro_gui_set_icon_string(pointer->w, INTERFACE_EXTERNAL_HOTLIST_APP,
+ "", false);
+}
+
+bool ro_gui_options_interface_ok(wimp_w w)
+{
+ nsoption_set_bool(strip_extensions,
+ ro_gui_get_icon_selected_state(w,
+ INTERFACE_STRIP_EXTNS_OPTION));
+ nsoption_set_bool(confirm_overwrite,
+ ro_gui_get_icon_selected_state(w,
+ INTERFACE_CONFIRM_OVWR_OPTION));
+ nsoption_set_bool(url_suggestion,
+ ro_gui_get_icon_selected_state(w,
+ INTERFACE_URL_COMPLETE_OPTION));
+ nsoption_set_bool(history_tooltip,
+ ro_gui_get_icon_selected_state(w,
+ INTERFACE_HISTORY_TOOLTIP_OPTION));
+ nsoption_set_bool(thumbnail_iconise,
+ ro_gui_get_icon_selected_state(w,
+ INTERFACE_THUMBNAIL_ICONISE_OPTION));
+ nsoption_set_bool(external_hotlists,
+ ro_gui_get_icon_selected_state(w,
+ INTERFACE_USE_EXTERNAL_HOTLIST));
+ nsoption_set_charp(external_hotlist_app,
+ strdup(ro_gui_get_icon_string(w,
+ INTERFACE_EXTERNAL_HOTLIST_APP)));
+
+ ro_gui_save_options();
+ return true;
+}
diff --git a/frontends/riscos/configure/con_language.c b/frontends/riscos/configure/con_language.c
new file mode 100644
index 000000000..2030c65c0
--- /dev/null
+++ b/frontends/riscos/configure/con_language.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2004 John M Bell <jmb202@ecs.soton.ac.uk>
+ * Copyright 2006 Richard Wilson <info@tinct.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdbool.h>
+
+#include "utils/nsoption.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+
+#include "riscos/gui.h"
+#include "riscos/menus.h"
+#include "riscos/wimp.h"
+#include "riscos/wimp_event.h"
+#include "riscos/configure.h"
+#include "riscos/configure/configure.h"
+#include "riscos/dialog.h"
+
+
+#define LANGUAGE_INTERFACE_FIELD 3
+#define LANGUAGE_INTERFACE_GRIGHT 4
+#define LANGUAGE_WEB_PAGES_FIELD 6
+#define LANGUAGE_WEB_PAGES_GRIGHT 7
+#define LANGUAGE_DEFAULT_BUTTON 8
+#define LANGUAGE_CANCEL_BUTTON 9
+#define LANGUAGE_OK_BUTTON 10
+
+static void ro_gui_options_language_default(wimp_pointer *pointer);
+static bool ro_gui_options_language_ok(wimp_w w);
+static const char *ro_gui_options_language_name(const char *code);
+
+bool ro_gui_options_language_initialise(wimp_w w)
+{
+ /* set the current values */
+ ro_gui_set_icon_string(w, LANGUAGE_INTERFACE_FIELD,
+ ro_gui_options_language_name(nsoption_charp(language) ?
+ nsoption_charp(language) : "en"), true);
+ ro_gui_set_icon_string(w, LANGUAGE_WEB_PAGES_FIELD,
+ ro_gui_options_language_name(nsoption_charp(accept_language) ?
+ nsoption_charp(accept_language) : "en"), true);
+
+ /* initialise all functions for a newly created window */
+ ro_gui_wimp_event_register_menu_gright(w, LANGUAGE_INTERFACE_FIELD,
+ LANGUAGE_INTERFACE_GRIGHT, languages_menu);
+ ro_gui_wimp_event_register_menu_gright(w, LANGUAGE_WEB_PAGES_FIELD,
+ LANGUAGE_WEB_PAGES_GRIGHT, languages_menu);
+ ro_gui_wimp_event_register_button(w, LANGUAGE_DEFAULT_BUTTON,
+ ro_gui_options_language_default);
+ ro_gui_wimp_event_register_cancel(w, LANGUAGE_CANCEL_BUTTON);
+ ro_gui_wimp_event_register_ok(w, LANGUAGE_OK_BUTTON,
+ ro_gui_options_language_ok);
+ ro_gui_wimp_event_set_help_prefix(w, "HelpLanguageConfig");
+ ro_gui_wimp_event_memorise(w);
+ return true;
+
+}
+
+void ro_gui_options_language_default(wimp_pointer *pointer)
+{
+ const char *code;
+
+ code = ro_gui_default_language();
+ ro_gui_set_icon_string(pointer->w, LANGUAGE_INTERFACE_FIELD,
+ ro_gui_options_language_name(code ?
+ code : "en"), true);
+ ro_gui_set_icon_string(pointer->w, LANGUAGE_WEB_PAGES_FIELD,
+ ro_gui_options_language_name(code ?
+ code : "en"), true);
+}
+
+bool ro_gui_options_language_ok(wimp_w w)
+{
+ const char *code;
+ char *temp;
+
+ code = ro_gui_menu_find_menu_entry_key(languages_menu,
+ ro_gui_get_icon_string(w, LANGUAGE_INTERFACE_FIELD));
+ if (code) {
+ code += 5; /* skip 'lang_' */
+ if ((!nsoption_charp(language)) ||
+ (strcmp(nsoption_charp(language), code))) {
+ temp = strdup(code);
+ if (temp) {
+ nsoption_set_charp(language, temp);
+ } else {
+ LOG("No memory to duplicate language code");
+ ro_warn_user("NoMemory", 0);
+ }
+ }
+ }
+ code = ro_gui_menu_find_menu_entry_key(languages_menu,
+ ro_gui_get_icon_string(w, LANGUAGE_WEB_PAGES_FIELD));
+ if (code) {
+ code += 5; /* skip 'lang_' */
+ if ((!nsoption_charp(accept_language)) ||
+ (strcmp(nsoption_charp(accept_language), code))) {
+ temp = strdup(code);
+ if (temp) {
+ nsoption_set_charp(accept_language,temp);
+ } else {
+ LOG("No memory to duplicate language code");
+ ro_warn_user("NoMemory", 0);
+ }
+ }
+ }
+ ro_gui_save_options();
+ return true;
+}
+
+
+/**
+ * Convert a 2-letter ISO language code to the language name.
+ *
+ * \param code 2-letter ISO language code
+ * \return language name, or code if unknown
+ */
+const char *ro_gui_options_language_name(const char *code)
+{
+ char key[] = "lang_xx";
+ key[5] = code[0];
+ key[6] = code[1];
+
+ return messages_get(key);
+}
diff --git a/frontends/riscos/configure/con_secure.c b/frontends/riscos/configure/con_secure.c
new file mode 100644
index 000000000..9c8a846c3
--- /dev/null
+++ b/frontends/riscos/configure/con_secure.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2006 Richard Wilson <info@tinct.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdbool.h>
+
+#include "utils/nsoption.h"
+#include "utils/messages.h"
+
+#include "riscos/gui.h"
+#include "riscos/wimp.h"
+#include "riscos/wimp_event.h"
+#include "riscos/configure.h"
+#include "riscos/configure/configure.h"
+#include "riscos/dialog.h"
+
+#define SECURITY_REFERRER 2
+#define SECURITY_DURATION_FIELD 6
+#define SECURITY_DURATION_INC 7
+#define SECURITY_DURATION_DEC 8
+#define SECURITY_DEFAULT_BUTTON 10
+#define SECURITY_CANCEL_BUTTON 11
+#define SECURITY_OK_BUTTON 12
+
+static void ro_gui_options_security_default(wimp_pointer *pointer);
+static bool ro_gui_options_security_ok(wimp_w w);
+
+bool ro_gui_options_security_initialise(wimp_w w)
+{
+ /* set the current values */
+ ro_gui_set_icon_selected_state(w, SECURITY_REFERRER,
+ nsoption_bool(send_referer));
+ ro_gui_set_icon_integer(w, SECURITY_DURATION_FIELD,
+ nsoption_int(expire_url));
+
+ /* initialise all functions for a newly created window */
+ ro_gui_wimp_event_register_checkbox(w, SECURITY_REFERRER);
+ ro_gui_wimp_event_register_numeric_field(w, SECURITY_DURATION_FIELD,
+ SECURITY_DURATION_DEC, SECURITY_DURATION_INC,
+ 0, 365, 1, 0);
+ ro_gui_wimp_event_register_button(w, SECURITY_DEFAULT_BUTTON,
+ ro_gui_options_security_default);
+ ro_gui_wimp_event_register_cancel(w, SECURITY_CANCEL_BUTTON);
+ ro_gui_wimp_event_register_ok(w, SECURITY_OK_BUTTON,
+ ro_gui_options_security_ok);
+ ro_gui_wimp_event_set_help_prefix(w, "HelpSecurityConfig");
+ ro_gui_wimp_event_memorise(w);
+ return true;
+
+}
+
+void ro_gui_options_security_default(wimp_pointer *pointer)
+{
+ /* set the default values */
+ ro_gui_set_icon_integer(pointer->w, SECURITY_DURATION_FIELD, 28);
+ ro_gui_set_icon_selected_state(pointer->w, SECURITY_REFERRER, true);
+}
+
+bool ro_gui_options_security_ok(wimp_w w)
+{
+ nsoption_set_bool(send_referer,
+ ro_gui_get_icon_selected_state(w, SECURITY_REFERRER));
+
+ nsoption_set_int(expire_url,
+ ro_gui_get_icon_decimal(w,SECURITY_DURATION_FIELD, 0));
+
+ ro_gui_save_options();
+ return true;
+}
diff --git a/frontends/riscos/configure/con_theme.c b/frontends/riscos/configure/con_theme.c
new file mode 100644
index 000000000..fb0d3dfb0
--- /dev/null
+++ b/frontends/riscos/configure/con_theme.c
@@ -0,0 +1,420 @@
+/*
+ * Copyright 2006 Richard Wilson <info@tinct.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <oslib/osspriteop.h>
+#include <oslib/wimp.h>
+#include <oslib/wimpspriteop.h>
+
+#include "utils/config.h"
+#include "utils/nsoption.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+
+#include "riscos/gui.h"
+#include "riscos/configure/configure.h"
+#include "riscos/configure.h"
+#include "riscos/dialog.h"
+#include "riscos/menus.h"
+#include "riscos/theme.h"
+#include "riscos/toolbar.h"
+#include "riscos/url_complete.h"
+#include "riscos/wimp.h"
+#include "riscos/wimp_event.h"
+#include "riscos/wimputils.h"
+
+
+#define THEME_PANE_AREA 0
+#define THEME_DEFAULT_BUTTON 2
+#define THEME_CANCEL_BUTTON 3
+#define THEME_OK_BUTTON 4
+
+struct toolbar_display {
+ struct toolbar *toolbar;
+ struct theme_descriptor *descriptor;
+ int icon_number;
+ struct toolbar_display *next;
+};
+
+static wimp_window theme_pane_definition = {
+ {0, 0, 16, 16},
+ 0,
+ 0,
+ wimp_TOP,
+ wimp_WINDOW_NEW_FORMAT | wimp_WINDOW_VSCROLL | wimp_WINDOW_AUTO_REDRAW,
+ wimp_COLOUR_BLACK,
+ wimp_COLOUR_LIGHT_GREY,
+ wimp_COLOUR_LIGHT_GREY,
+ wimp_COLOUR_VERY_LIGHT_GREY,
+ wimp_COLOUR_DARK_GREY,
+ wimp_COLOUR_MID_LIGHT_GREY,
+ wimp_COLOUR_CREAM,
+ 0,
+ {0, -16384, 16384, 0},
+ wimp_ICON_TEXT | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED,
+ wimp_BUTTON_CLICK << wimp_ICON_BUTTON_TYPE_SHIFT,
+ wimpspriteop_AREA,
+ 1,
+ 1,
+ {""},
+ 0,
+ {}
+};
+
+
+static wimp_w theme_pane;
+static struct theme_descriptor *theme_list = NULL;
+static struct toolbar_display *toolbars = NULL;
+static char theme_radio_validation[] = "Sradiooff,radioon";
+static char theme_null_validation[] = "";
+static char theme_line_validation[] = "R2";
+
+static bool ro_gui_options_theme_ok(wimp_w w);
+static bool ro_gui_options_theme_click(wimp_pointer *pointer);
+static void ro_gui_options_theme_load(void);
+static void ro_gui_options_theme_free(void);
+
+bool ro_gui_options_theme_initialise(wimp_w w)
+{
+ wimp_window_state state;
+ wimp_icon_state icon_state;
+ os_error *error;
+ struct theme_descriptor *theme_choice;
+ struct toolbar_display *toolbar;
+
+ /* only allow one instance for now*/
+ if (theme_pane)
+ return false;
+ error = xwimp_create_window(&theme_pane_definition, &theme_pane);
+ if (error) {
+ LOG("xwimp_create_window: 0x%x: %s", error->errnum, error->errmess);
+ return false;
+ }
+ state.w = w;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ return false;
+ }
+ icon_state.w = w;
+ icon_state.i = THEME_PANE_AREA;
+ error = xwimp_get_icon_state(&icon_state);
+ if (error) {
+ LOG("xwimp_get_icon_state: 0x%x: %s", error->errnum, error->errmess);
+ return false;
+ }
+ state.w = theme_pane;
+ state.visible.x1 = state.visible.x0 + icon_state.icon.extent.x1 - 16 -
+ ro_get_vscroll_width(theme_pane);
+ state.visible.x0 += icon_state.icon.extent.x0 + 16;
+ state.visible.y0 = state.visible.y1 + icon_state.icon.extent.y0 + 16;
+ state.visible.y1 += icon_state.icon.extent.y1 - 28;
+ LOG("Y0 = %i, y1 = %i", icon_state.icon.extent.y0, icon_state.icon.extent.y1);
+ error = xwimp_open_window_nested(PTR_WIMP_OPEN(&state), w,
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_XORIGIN_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_TOP_OR_RIGHT
+ << wimp_CHILD_YORIGIN_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_LS_EDGE_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_TOP_OR_RIGHT
+ << wimp_CHILD_BS_EDGE_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_TOP_OR_RIGHT
+ << wimp_CHILD_RS_EDGE_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_TOP_OR_RIGHT
+ << wimp_CHILD_TS_EDGE_SHIFT);
+ if (error) {
+ LOG("xwimp_open_window_nested: 0x%x: %s", error->errnum, error->errmess);
+ return false;
+ }
+
+ /* load themes */
+ ro_gui_options_theme_load();
+
+ /* set the current selection */
+ theme_choice = ro_gui_theme_find(nsoption_charp(theme));
+ if (!theme_choice)
+ theme_choice = ro_gui_theme_find("Aletheia");
+ for (toolbar = toolbars; toolbar; toolbar = toolbar->next)
+ ro_gui_set_icon_selected_state(theme_pane, toolbar->icon_number,
+ (toolbar->descriptor == theme_choice));
+ ro_gui_wimp_event_memorise(theme_pane);
+ ro_gui_wimp_event_set_help_prefix(theme_pane, "HelpThemePConfig");
+
+ ro_gui_wimp_event_register_mouse_click(w, ro_gui_options_theme_click);
+ ro_gui_wimp_event_register_cancel(w, THEME_CANCEL_BUTTON);
+ ro_gui_wimp_event_register_ok(w, THEME_OK_BUTTON,
+ ro_gui_options_theme_ok);
+ ro_gui_wimp_event_set_help_prefix(w, "HelpThemeConfig");
+ ro_gui_wimp_event_memorise(w);
+
+ return true;
+}
+
+void ro_gui_options_theme_finalise(wimp_w w)
+{
+ ro_gui_options_theme_free();
+ if (theme_pane) {
+ os_error *error;
+ ro_gui_wimp_event_finalise(theme_pane);
+ error = xwimp_delete_window(theme_pane);
+ if (error) {
+ LOG("xwimp_delete_window: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+ theme_pane = 0;
+ }
+ ro_gui_wimp_event_finalise(w);
+}
+
+bool ro_gui_options_theme_ok(wimp_w w)
+{
+ struct toolbar_display *toolbar;
+ struct theme_descriptor *theme_new = NULL;
+
+ /* find the current selection */
+ for (toolbar = toolbars; toolbar; toolbar = toolbar->next) {
+ if (ro_gui_get_icon_selected_state(theme_pane, toolbar->icon_number)) {
+ theme_new = toolbar->descriptor;
+ break;
+ }
+ }
+
+ /* set the options */
+ if (theme_new) {
+ nsoption_set_charp(theme, strdup(theme_new->leafname));
+ ro_gui_theme_apply(theme_new);
+ } else {
+ nsoption_set_charp(theme, NULL);
+ }
+ ro_gui_save_options();
+
+ /* store the pane status */
+ ro_gui_wimp_event_memorise(theme_pane);
+ return true;
+}
+
+bool ro_gui_options_theme_click(wimp_pointer *pointer)
+{
+ struct theme_descriptor *theme_default;
+ struct toolbar_display *toolbar;
+
+ switch (pointer->i) {
+ case THEME_DEFAULT_BUTTON:
+ theme_default = ro_gui_theme_find("Aletheia");
+ for (toolbar = toolbars; toolbar; toolbar = toolbar->next)
+ ro_gui_set_icon_selected_state(theme_pane,
+ toolbar->icon_number,
+ (toolbar->descriptor == theme_default));
+ break;
+ case THEME_CANCEL_BUTTON:
+ ro_gui_wimp_event_restore(theme_pane);
+ break;
+ case THEME_OK_BUTTON:
+ ro_gui_wimp_event_memorise(theme_pane);
+ break;
+ }
+ return false;
+}
+
+void ro_gui_options_theme_load(void)
+{
+ os_error *error;
+ os_box extent = { 0, 0, 0, 0 };
+ struct theme_descriptor *descriptor;
+ struct toolbar_display *link;
+ struct toolbar_display *toolbar_display;
+ struct toolbar *toolbar;
+ wimp_icon_create new_icon;
+ wimp_window_state state;
+ int parent_width, nested_y, min_extent, base_extent;
+ int *radio_icons, *radio_set;
+ int theme_count;
+
+ /* delete our old list and get/open a new one */
+ ro_gui_options_theme_free();
+ theme_list = ro_gui_theme_get_available();
+ ro_gui_theme_open(theme_list, true);
+
+ /* create toolbars for each theme */
+ theme_count = 0;
+ descriptor = theme_list;
+ while (descriptor != NULL) {
+ /* try to create a toolbar */
+ toolbar = ro_toolbar_create(descriptor, NULL,
+ THEME_STYLE_BROWSER_TOOLBAR,
+ TOOLBAR_FLAGS_DISPLAY, NULL, NULL, NULL);
+ if (toolbar != NULL) {
+ ro_toolbar_add_buttons(toolbar, brower_toolbar_buttons,
+ nsoption_charp(toolbar_browser));
+ ro_toolbar_add_url(toolbar);
+ ro_toolbar_add_throbber(toolbar);
+ ro_toolbar_rebuild(toolbar);
+ toolbar_display = calloc(sizeof(struct toolbar_display), 1);
+ if (!toolbar_display) {
+ LOG("No memory for calloc()");
+ ro_warn_user("NoMemory", 0);
+ return;
+ }
+ toolbar_display->toolbar = toolbar;
+ toolbar_display->descriptor = descriptor;
+ if (!toolbars) {
+ toolbars = toolbar_display;
+ } else {
+ link = toolbars;
+ while (link->next) link = link->next;
+ link->next = toolbar_display;
+ }
+ theme_count++;
+ }
+ descriptor = descriptor->next;
+ }
+
+ /* nest the toolbars */
+ state.w = theme_pane;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ parent_width = state.visible.x1 - state.visible.x0;
+ min_extent = state.visible.y0 - state.visible.y1;
+ nested_y = 0;
+ base_extent = state.visible.y1 - state.yscroll;
+ extent.x1 = parent_width;
+ link = toolbars;
+ new_icon.w = theme_pane;
+ new_icon.icon.flags = wimp_ICON_TEXT | wimp_ICON_INDIRECTED |
+ wimp_ICON_VCENTRED |
+ (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) |
+ (wimp_COLOUR_VERY_LIGHT_GREY << wimp_ICON_BG_COLOUR_SHIFT);
+ while (link) {
+ /* update the toolbar */
+ int item_height = 44 + 44 + 16;
+ if (link->next) item_height += 16;
+ ro_toolbar_process(link->toolbar, parent_width, false);
+ extent.y0 = nested_y -
+ ro_toolbar_height(link->toolbar) -
+ item_height;
+ if (link->next) extent.y0 -= 16;
+ if (extent.y0 > min_extent) extent.y0 = min_extent;
+ xwimp_set_extent(theme_pane, &extent);
+
+ /* create the descriptor icons and separator line */
+ new_icon.icon.extent.x0 = 8;
+ new_icon.icon.extent.x1 = parent_width - 8;
+ new_icon.icon.flags &= ~wimp_ICON_BORDER;
+ new_icon.icon.flags |= wimp_ICON_SPRITE;
+ new_icon.icon.extent.y1 = nested_y -
+ ro_toolbar_height(link->toolbar) - 8;
+ new_icon.icon.extent.y0 = nested_y -
+ ro_toolbar_height(link->toolbar) - 52;
+ new_icon.icon.data.indirected_text_and_sprite.text =
+ (char *)&link->descriptor->name;
+ new_icon.icon.data.indirected_text_and_sprite.size =
+ strlen(link->descriptor->name) + 1;
+ new_icon.icon.data.indirected_text_and_sprite.validation =
+ theme_radio_validation;
+ new_icon.icon.flags |= (wimp_BUTTON_RADIO <<
+ wimp_ICON_BUTTON_TYPE_SHIFT);
+ xwimp_create_icon(&new_icon, &link->icon_number);
+ new_icon.icon.flags &= ~wimp_ICON_SPRITE;
+ new_icon.icon.extent.x0 = 52;
+ new_icon.icon.extent.y1 -= 44;
+ new_icon.icon.extent.y0 -= 44;
+ new_icon.icon.data.indirected_text.text =
+ (char *)&link->descriptor->author;
+ new_icon.icon.data.indirected_text.size =
+ strlen(link->descriptor->author) + 1;
+ new_icon.icon.data.indirected_text.validation =
+ theme_null_validation;
+ new_icon.icon.flags &= ~(wimp_BUTTON_RADIO <<
+ wimp_ICON_BUTTON_TYPE_SHIFT);
+ xwimp_create_icon(&new_icon, 0);
+ if (link->next) {
+ new_icon.icon.flags |= wimp_ICON_BORDER;
+ new_icon.icon.extent.x0 = -8;
+ new_icon.icon.extent.x1 = parent_width + 8;
+ new_icon.icon.extent.y1 -= 52;
+ new_icon.icon.extent.y0 = new_icon.icon.extent.y1 - 8;
+ new_icon.icon.data.indirected_text.text =
+ theme_null_validation;
+ new_icon.icon.data.indirected_text.validation =
+ theme_line_validation;
+ new_icon.icon.data.indirected_text.size = 1;
+ xwimp_create_icon(&new_icon, 0);
+ }
+
+ /* nest the toolbar window */
+ state.w = ro_toolbar_get_window(link->toolbar);
+ state.yscroll = 0;
+ state.visible.y1 = nested_y + base_extent;
+ state.visible.y0 = state.visible.y1 -
+ ro_toolbar_height(link->toolbar) + 2;
+ xwimp_open_window_nested(PTR_WIMP_OPEN(&state), theme_pane,
+ wimp_CHILD_LINKS_PARENT_WORK_AREA
+ << wimp_CHILD_BS_EDGE_SHIFT |
+ wimp_CHILD_LINKS_PARENT_WORK_AREA
+ << wimp_CHILD_TS_EDGE_SHIFT);
+
+ /* continue processing */
+ nested_y -= ro_toolbar_height(link->toolbar) +
+ item_height;
+ link = link->next;
+ }
+
+ /* set the icons as radios */
+ radio_icons = (int *)calloc(theme_count + 1, sizeof(int));
+ radio_set = radio_icons;
+ for (link = toolbars; link; link = link->next)
+ *radio_set++ = link->icon_number;
+ *radio_set = -1;
+ ro_gui_wimp_event_register_radio(theme_pane, radio_icons);
+
+ /* update our display */
+ xwimp_force_redraw(theme_pane, 0, -16384, 16384, 16384);
+}
+
+void ro_gui_options_theme_free(void)
+{
+ struct toolbar_display *toolbar;
+ struct toolbar_display *next_toolbar;
+
+ /* free all our toolbars */
+ next_toolbar = toolbars;
+ while ((toolbar = next_toolbar) != NULL) {
+ next_toolbar = toolbar->next;
+ xwimp_delete_icon(theme_pane, toolbar->icon_number);
+ xwimp_delete_icon(theme_pane, toolbar->icon_number + 1);
+ if (next_toolbar)
+ xwimp_delete_icon(theme_pane,
+ toolbar->icon_number + 2);
+ ro_toolbar_destroy(toolbar->toolbar);
+ free(toolbar);
+ }
+ toolbars = NULL;
+
+ /* close all our themes */
+ if (theme_list)
+ ro_gui_theme_close(theme_list, true);
+ theme_list = NULL;
+}
diff --git a/frontends/riscos/configure/configure.h b/frontends/riscos/configure/configure.h
new file mode 100644
index 000000000..e5cdb392e
--- /dev/null
+++ b/frontends/riscos/configure/configure.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2005 Richard Wilson <info@tinct.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Automated RISC OS WIMP event handling (interface).
+ */
+
+
+#ifndef _NETSURF_RISCOS_OPTIONS_CONFIGURE_H_
+#define _NETSURF_RISCOS_OPTIONS_CONFIGURE_H_
+
+#include <stdbool.h>
+#include "oslib/wimp.h"
+
+bool ro_gui_options_cache_initialise(wimp_w w);
+bool ro_gui_options_connection_initialise(wimp_w w);
+bool ro_gui_options_content_initialise(wimp_w w);
+bool ro_gui_options_fonts_initialise(wimp_w w);
+bool ro_gui_options_home_initialise(wimp_w w);
+bool ro_gui_options_image_initialise(wimp_w w);
+void ro_gui_options_image_finalise(wimp_w w);
+bool ro_gui_options_interface_initialise(wimp_w w);
+bool ro_gui_options_language_initialise(wimp_w w);
+bool ro_gui_options_security_initialise(wimp_w w);
+bool ro_gui_options_theme_initialise(wimp_w w);
+void ro_gui_options_theme_finalise(wimp_w w);
+
+#endif
diff --git a/frontends/riscos/content-handlers/artworks.c b/frontends/riscos/content-handlers/artworks.c
new file mode 100644
index 000000000..b6f7a0d08
--- /dev/null
+++ b/frontends/riscos/content-handlers/artworks.c
@@ -0,0 +1,435 @@
+/*
+ * Copyright 2005 Adrian Lees <adrianl@users.sourceforge.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Content for image/x-artworks (RISC OS implementation).
+ *
+ * Uses the ArtworksRenderer module
+ */
+
+#include "utils/config.h"
+#ifdef WITH_ARTWORKS
+
+#include <assert.h>
+#include <limits.h>
+#include <stdlib.h>
+#include "swis.h"
+#include "oslib/os.h"
+#include "oslib/wimp.h"
+
+#include "utils/config.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/utils.h"
+#include "content/content_protected.h"
+#include "desktop/plotters.h"
+
+#include "riscos/content-handlers/artworks.h"
+#include "riscos/gui.h"
+#include "riscos/wimputils.h"
+
+#define AWRender_FileInitAddress 0x46080
+#define AWRender_RenderAddress 0x46081
+#define AWRender_DocBounds 0x46082
+#define AWRender_SendDefs 0x46083
+#define AWRender_ClaimVectors 0x46084
+#define AWRender_ReleaseVectors 0x46085
+#define AWRender_FindFirstFont 0x46086
+#define AWRender_FindNextFont 0x46087
+
+
+#define INITIAL_BLOCK_SIZE 0x1000
+
+typedef struct artworks_content {
+ struct content base;
+
+ int x0, y0, x1, y1;
+
+ void *render_routine;
+ void *render_workspace;
+
+ /* dynamically-resizable block required by
+ ArtWorksRenderer rendering routine */
+
+ void *block;
+ size_t size;
+} artworks_content;
+
+struct awinfo_block {
+ int ditherx;
+ int dithery;
+ int clip_x0;
+ int clip_y0;
+ int clip_x1;
+ int clip_y1;
+ int print_lowx;
+ int print_lowy;
+ int print_handle;
+ int print_x1;
+ int print_y1;
+ int bgcolour;
+};
+
+
+/* Assembler routines for interfacing with the ArtworksRenderer module */
+
+extern os_error *awrender_init(const char **doc,
+ unsigned long *doc_size,
+ void *routine,
+ void *workspace);
+
+extern os_error *awrender_render(const char *doc,
+ const struct awinfo_block *info,
+ const os_trfm *trans,
+ const int *vdu_vars,
+ void **rsz_block,
+ size_t *rsz_size,
+ int wysiwyg_setting,
+ int output_dest,
+ size_t doc_size,
+ void *routine,
+ void *workspace);
+
+static nserror artworks_create(const content_handler *handler,
+ lwc_string *imime_type, const struct http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c);
+static bool artworks_convert(struct content *c);
+static void artworks_destroy(struct content *c);
+static bool artworks_redraw(struct content *c, struct content_redraw_data *data,
+ const struct rect *clip, const struct redraw_context *ctx);
+static nserror artworks_clone(const struct content *old, struct content **newc);
+static content_type artworks_content_type(void);
+
+static const content_handler artworks_content_handler = {
+ .create = artworks_create,
+ .data_complete = artworks_convert,
+ .destroy = artworks_destroy,
+ .redraw = artworks_redraw,
+ .clone = artworks_clone,
+ .type = artworks_content_type,
+ .no_share = false,
+};
+
+static const char *artworks_types[] = {
+ "image/x-artworks"
+};
+
+CONTENT_FACTORY_REGISTER_TYPES(artworks, artworks_types,
+ artworks_content_handler)
+
+nserror artworks_create(const content_handler *handler,
+ lwc_string *imime_type, const struct http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c)
+{
+ artworks_content *aw;
+ nserror error;
+
+ aw = calloc(1, sizeof(artworks_content));
+ if (aw == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init(&aw->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ free(aw);
+ return error;
+ }
+
+ *c = (struct content *) aw;
+
+ return NSERROR_OK;
+}
+
+/**
+ * Convert a CONTENT_ARTWORKS for display.
+ *
+ * No conversion is necessary. We merely read the ArtWorks
+ * bounding box bottom-left.
+ */
+
+bool artworks_convert(struct content *c)
+{
+ artworks_content *aw = (artworks_content *) c;
+ union content_msg_data msg_data;
+ const char *source_data;
+ unsigned long source_size;
+ void *init_workspace;
+ void *init_routine;
+ os_error *error;
+ int used = -1; /* slightly better with older OSLib versions */
+ char *title;
+
+ /* check whether AWViewer has been seen and we can therefore
+ locate the ArtWorks rendering modules */
+ xos_read_var_val_size("Alias$LoadArtWorksModules", 0, os_VARTYPE_STRING,
+ &used, NULL, NULL);
+ if (used >= 0) {
+ LOG("Alias$LoadArtWorksModules not defined");
+ msg_data.error = messages_get("AWNotSeen");
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ return false;
+ }
+
+ /* load the modules, or do nothing if they're already loaded */
+ error = xos_cli("LoadArtWorksModules");
+ if (error) {
+ LOG("xos_cli: 0x%x: %s", error->errnum, error->errmess);
+ msg_data.error = error->errmess;
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ return false;
+ }
+
+ /* lookup the addresses of the init and render routines */
+ error = (os_error*)_swix(AWRender_FileInitAddress, _OUT(0) | _OUT(1),
+ &init_routine, &init_workspace);
+ if (error) {
+ LOG("AWRender_FileInitAddress: 0x%x: %s", error->errnum, error->errmess);
+ msg_data.error = error->errmess;
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ return false;
+ }
+
+ error = (os_error*)_swix(AWRender_RenderAddress, _OUT(0) | _OUT(1),
+ &aw->render_routine,
+ &aw->render_workspace);
+ if (error) {
+ LOG("AWRender_RenderAddress: 0x%x: %s", error->errnum, error->errmess);
+ msg_data.error = error->errmess;
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ return false;
+ }
+
+ source_data = content__get_source_data(c, &source_size);
+
+ /* initialise (convert file to new format if required) */
+ error = awrender_init(&source_data, &source_size,
+ init_routine, init_workspace);
+ if (error) {
+ LOG("awrender_init: 0x%x : %s", error->errnum, error->errmess);
+ msg_data.error = error->errmess;
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ return false;
+ }
+
+ error = (os_error*)_swix(AWRender_DocBounds,
+ _IN(0) | _OUT(2) | _OUT(3) | _OUT(4) | _OUT(5),
+ source_data,
+ &aw->x0,
+ &aw->y0,
+ &aw->x1,
+ &aw->y1);
+
+ if (error) {
+ LOG("AWRender_DocBounds: 0x%x: %s", error->errnum, error->errmess);
+ msg_data.error = error->errmess;
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ return false;
+ }
+
+ LOG("bounding box: %d,%d,%d,%d", aw->x0, aw->y0, aw->x1, aw->y1);
+
+ /* create the resizable workspace required by the
+ ArtWorksRenderer rendering routine */
+
+ aw->size = INITIAL_BLOCK_SIZE;
+ aw->block = malloc(INITIAL_BLOCK_SIZE);
+ if (!aw->block) {
+ LOG("failed to create block for ArtworksRenderer");
+ msg_data.error = messages_get("NoMemory");
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ return false;
+ }
+
+ c->width = (aw->x1 - aw->x0) / 512;
+ c->height = (aw->y1 - aw->y0) / 512;
+
+ title = messages_get_buff("ArtWorksTitle",
+ nsurl_access_leaf(llcache_handle_get_url(c->llcache)),
+ c->width, c->height);
+ if (title != NULL) {
+ content__set_title(c, title);
+ free(title);
+ }
+ content_set_ready(c);
+ content_set_done(c);
+ /* Done: update status bar */
+ content_set_status(c, "");
+ return true;
+}
+
+
+/**
+ * Destroy a CONTENT_ARTWORKS and free all resources it owns.
+ */
+
+void artworks_destroy(struct content *c)
+{
+ artworks_content *aw = (artworks_content *) c;
+
+ free(aw->block);
+}
+
+
+/**
+ * Redraw a CONTENT_ARTWORKS.
+ */
+
+bool artworks_redraw(struct content *c, struct content_redraw_data *data,
+ const struct rect *clip, const struct redraw_context *ctx)
+{
+ static const ns_os_vdu_var_list vars = {
+ os_MODEVAR_XEIG_FACTOR,
+ {
+ os_MODEVAR_YEIG_FACTOR,
+ os_MODEVAR_LOG2_BPP,
+ os_VDUVAR_END_LIST
+ }
+ };
+ artworks_content *aw = (artworks_content *) c;
+ struct awinfo_block info;
+ const char *source_data;
+ unsigned long source_size;
+ os_error *error;
+ os_trfm matrix;
+ int vals[24];
+
+ int clip_x0 = clip->x0;
+ int clip_y0 = clip->y0;
+ int clip_x1 = clip->x1;
+ int clip_y1 = clip->y1;
+
+ if (ctx->plot->flush && !ctx->plot->flush())
+ return false;
+
+ /* pick up render addresses again in case they've changed
+ (eg. newer AWRender module loaded since we first loaded this file) */
+ (void)_swix(AWRender_RenderAddress, _OUT(0) | _OUT(1),
+ &aw->render_routine,
+ &aw->render_workspace);
+
+ /* Scaled image. Transform units (65536*OS units) */
+ matrix.entries[0][0] = data->width * 65536 / c->width;
+ matrix.entries[0][1] = 0;
+ matrix.entries[1][0] = 0;
+ matrix.entries[1][1] = data->height * 65536 / c->height;
+ /* Draw units. (x,y) = bottom left */
+ matrix.entries[2][0] = ro_plot_origin_x * 256 + data->x * 512 -
+ aw->x0 * data->width / c->width;
+ matrix.entries[2][1] = ro_plot_origin_y * 256 -
+ (data->y + data->height) * 512 -
+ aw->y0 * data->height / c->height;
+
+ info.ditherx = ro_plot_origin_x;
+ info.dithery = ro_plot_origin_y;
+
+ clip_x0 -= data->x;
+ clip_y0 -= data->y;
+ clip_x1 -= data->x;
+ clip_y1 -= data->y;
+
+ if (data->scale == 1.0) {
+ info.clip_x0 = (clip_x0 * 512) + aw->x0 - 511;
+ info.clip_y0 = ((c->height - clip_y1) * 512) + aw->y0 - 511;
+ info.clip_x1 = (clip_x1 * 512) + aw->x0 + 511;
+ info.clip_y1 = ((c->height - clip_y0) * 512) + aw->y0 + 511;
+ }
+ else {
+ info.clip_x0 = (clip_x0 * 512 / data->scale) + aw->x0 - 511;
+ info.clip_y0 = ((c->height - (clip_y1 / data->scale)) * 512) +
+ aw->y0 - 511;
+ info.clip_x1 = (clip_x1 * 512 / data->scale) + aw->x0 + 511;
+ info.clip_y1 = ((c->height - (clip_y0 / data->scale)) * 512) +
+ aw->y0 + 511;
+ }
+
+ info.print_lowx = 0;
+ info.print_lowy = 0;
+ info.print_handle = 0;
+ info.bgcolour = 0x20000000 | data->background_colour;
+
+ error = xos_read_vdu_variables(PTR_OS_VDU_VAR_LIST(&vars), vals);
+ if (error) {
+ LOG("xos_read_vdu_variables: 0x%x: %s", error->errnum, error->errmess);
+ return false;
+ }
+
+ error = xwimp_read_palette((os_palette*)&vals[3]);
+ if (error) {
+ LOG("xwimp_read_palette: 0x%x: %s", error->errnum, error->errmess);
+ return false;
+ }
+
+ source_data = content__get_source_data(c, &source_size);
+
+ error = awrender_render(source_data,
+ &info,
+ &matrix,
+ vals,
+ &aw->block,
+ &aw->size,
+ 110, /* fully anti-aliased */
+ 0,
+ source_size,
+ aw->render_routine,
+ aw->render_workspace);
+
+ if (error) {
+ LOG("awrender_render: 0x%x: %s", error->errnum, error->errmess);
+ return false;
+ }
+
+ return true;
+}
+
+nserror artworks_clone(const struct content *old, struct content **newc)
+{
+ artworks_content *aw;
+ nserror error;
+
+ aw = calloc(1, sizeof(artworks_content));
+ if (aw == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__clone(old, &aw->base);
+ if (error != NSERROR_OK) {
+ content_destroy(&aw->base);
+ return error;
+ }
+
+ /* Simply re-run convert */
+ if (old->status == CONTENT_STATUS_READY ||
+ old->status == CONTENT_STATUS_DONE) {
+ if (artworks_convert(&aw->base) == false) {
+ content_destroy(&aw->base);
+ return NSERROR_CLONE_FAILED;
+ }
+ }
+
+ *newc = (struct content *) aw;
+
+ return NSERROR_OK;
+}
+
+content_type artworks_content_type(void)
+{
+ return CONTENT_IMAGE;
+}
+
+#endif
diff --git a/frontends/riscos/content-handlers/artworks.h b/frontends/riscos/content-handlers/artworks.h
new file mode 100644
index 000000000..67832cc54
--- /dev/null
+++ b/frontends/riscos/content-handlers/artworks.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2005 Adrian Lees <adrianl@users.sourceforge.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Content for image/x-artworks (RISC OS interface).
+ */
+
+#ifndef _NETSURF_RISCOS_ARTWORKS_H_
+#define _NETSURF_RISCOS_ARTWORKS_H_
+
+#include "utils/config.h"
+#include "utils/errors.h"
+
+#ifdef WITH_ARTWORKS
+
+nserror artworks_init(void);
+
+#else
+
+static inline nserror artworks_init(void)
+{
+ return NSERROR_OK;
+}
+
+#endif
+
+#endif
diff --git a/frontends/riscos/content-handlers/awrender.s b/frontends/riscos/content-handlers/awrender.s
new file mode 100644
index 000000000..5bcafe520
--- /dev/null
+++ b/frontends/riscos/content-handlers/awrender.s
@@ -0,0 +1,390 @@
+#if defined(__aof__)
+ AREA |ARM$$code|,CODE,READONLY
+
+ IMPORT messages_get
+ IMPORT realloc
+ IMPORT strcpy
+ IMPORT |__rt_stkovf_split_big|
+
+ EXPORT awrender_init
+ EXPORT awrender_render
+
+
+aw_rsz_block * 0
+aw_rsz_size * 4
+aw_fixed_block * 8
+aw_fixed_size * 12
+aw_sl * 16
+aw_fp * 20
+sizeof_aw * 24
+
+
+; os_error *awrender_init(byte **doc, size_t *doc_size, void *init_routine, void *init_workspace);
+
+awrender_init MOV ip,sp
+ STMFD sp!,{a1,a2,v1,v2,fp,ip,lr,pc}
+ SUB fp,ip,#4
+ SUB ip,sp,#512
+ CMP ip,sl
+ BLMI |__rt_stkovf_split_big|
+
+ LDR v2,=aw_temp
+ LDR a1,[a1]
+ MOV v1,a3
+ LDR a3,[a2]
+ MOV ip,a4
+ STR a1,[v2,#aw_rsz_block]
+ STR a3,[v2,#aw_rsz_size]
+ MOV a2,#-1
+ STR a2,[v2,#aw_fixed_block]
+ STR a3,[v2,#aw_fixed_size]
+ STR sl,[v2,#aw_sl]
+ STR fp,[v2,#aw_fp]
+ ADR a2,aw_callback
+ MOV lr,pc
+ MOV pc,v1
+ MOVVC a1,#0
+
+ ;return updated block ptr & size to caller
+
+ LDR a2,[fp,#-28]
+ LDR a3,[fp,#-24]
+ LDR ip,[v2,#aw_rsz_block]
+ LDR lr,[v2,#aw_rsz_size]
+ STR ip,[a2]
+ STR lr,[a3]
+
+ LDMEA fp,{v1,v2,fp,sp,pc}
+
+
+; os_error *awrender_render(const char *doc,
+; const struct awinfo_block *info,
+; const os_trfm *trans,
+; const int *vdu_vars,
+; char **rsz_block,
+; size_t *rsz_size,
+; int wysiwyg_setting,
+; int output_dest,
+; size_t doc_size,
+; void *routine,
+; void *workspace);
+
+awrender_render MOV ip,sp
+ STMFD sp!,{v1-v4,fp,ip,lr,pc}
+ SUB fp,ip,#4
+ SUB ip,sp,#512
+ CMP ip,sl
+ BLMI |__rt_stkovf_split_big|
+
+ LDR R12,[fp,#20]
+ LDR R14,=aw_temp
+ LDR R5,[fp,#4]
+ LDR R6,[fp,#12]
+ LDR R4,[R5] ;resizable block
+ LDR R7,[fp,#16]
+ STR R4,[R14,#aw_rsz_block]
+ STR R0,[R14,#aw_fixed_block] ;document ptr
+ STR R12,[R14,#aw_fixed_size] ;document size
+ LDR R12,[fp,#8]
+
+ STR R5,[sp,#-4]! ;ptr to receive block
+ STR R12,[sp,#-4]! ;ptr to receive size
+
+ LDR R12,[R12]
+ ADR R5,aw_callback
+ STR R12,[R14,#aw_rsz_size]
+
+ STR sl,[R14,#aw_sl]
+ STR fp,[R14,#aw_fp]
+
+ LDR R12,[fp,#28]
+ MOV lr,pc
+ LDR pc,[fp,#24]
+ MOVVC a1,#0
+
+ ;return updated block ptr & size to caller
+
+ LDR R7,=aw_temp
+ LDR R12,[sp],#4
+ LDR R4,[sp],#4
+ LDR R5,[R7,#aw_rsz_size]
+ LDR R6,[R7,#aw_rsz_block]
+ STR R5,[R12]
+ STR R6,[R4]
+
+ LDMEA fp,{v1-v4,fp,sp,pc}
+
+
+; Callback routine for block resizing
+; (passed to AWRender init and render routines)
+;
+; entry R11 = reason code
+; 0 = CallBackReason_Memory
+; 3 = CallBackReason_Interface
+; (0 => return capabilities)
+; exit R0 => base of resizable block
+; R1 = size of resizable block
+; R2 => base of fixed block (or -1 if no fixed block)
+; R3 = size of fixed block (or document in resizable block)
+; VC if resize successful, VS and R0 => error otherwise
+
+aw_callback TEQ R11,#3
+ TEQEQ R0,#0
+ MOVEQ R0,#1<<10 ;background colour supplied
+ TEQ R11,#0
+ LDREQ R11,=aw_temp
+ MOVNE PC,R14
+
+ CMP R0,#-1 ;read block size?
+ LDRNE R2,[R11,#aw_rsz_size]
+ MOVNE R1,R0 ;new block size
+ LDR R0,[R11,#aw_rsz_block]
+ BEQ aw_read
+
+ ; Note: because ArtworksRenderer seems to call
+ ; this routine for every scanline rendered
+ ; we never call realloc unless we have to in
+ ; order to expand the block. Also it calls
+ ; us with a size request of 0 which we must
+ ; safely ignore otherwise rendering will stop.
+
+ CMP R1,R2
+ BLS aw_read
+
+ STMFD R13!,{R1,R10-R12,R14}
+ LDR sl,[R11,#aw_sl]
+ LDR fp,[R11,#aw_fp]
+ BL realloc
+ LDMFD R13!,{R1,R10-R12,R14}
+
+ CMP R0,#0 ;did it work?
+ BEQ aw_nomem
+
+ STR R0,[R11]
+ STR R1,[R11,#aw_rsz_size]
+
+aw_read ; return details of fixed block
+
+ LDR R2,[R11,#aw_fixed_block]
+ LDR R3,[R11,#aw_fixed_size]
+ SUBS R11,R11,R11 ;clear V
+ MOV PC,R14
+
+aw_nomem STMFD R13!,{R10,R12,R14}
+ LDR sl,[R11,#aw_sl]
+ LDR fp,[R11,#aw_fp]
+ ADR R0,tok_nomem
+ BL messages_get
+ MOV a2,a1
+ LDR a1,=errblk + 4
+ BL strcpy
+ SUB R0,R0,#4 ;error number already 0
+ MOV R11,#0 ;restore reason code
+ CMP PC,#1<<31 ;set V
+ LDMFD R13!,{R10,R12,PC}
+
+tok_nomem = "NoMemory",0
+ ALIGN
+
+
+ AREA |ARM$$zidata|,DATA,NOINIT
+
+aw_temp % sizeof_aw
+errblk % 256
+
+ END
+
+#elif defined(__ELF__)
+
+ .text
+
+.set aw_rsz_block, 0
+.set aw_rsz_size, 4
+.set aw_fixed_block, 8
+.set aw_fixed_size, 12
+.set aw_sl, 16
+.set aw_fp, 20
+.set sizeof_aw, 24
+
+@ os_error *awrender_init(byte **doc, size_t *doc_size, void *init_routine, void *init_workspace);
+
+ .global awrender_init
+awrender_init: MOV ip,sp
+ STMFD sp!,{a1,a2,v1,v2,fp,ip,lr,pc}
+ SUB fp,ip,#4
+ SUB ip,sp,#512
+ CMP ip,sl
+ BLMI __rt_stkovf_split_big
+
+ LDR v2,=aw_temp
+ LDR a1,[a1]
+ MOV v1,a3
+ LDR a3,[a2]
+ MOV ip,a4
+ STR a1,[v2,#aw_rsz_block]
+ STR a3,[v2,#aw_rsz_size]
+ MOV a2,#-1
+ STR a2,[v2,#aw_fixed_block]
+ STR a3,[v2,#aw_fixed_size]
+ STR sl,[v2,#aw_sl]
+ STR fp,[v2,#aw_fp]
+ ADR a2,aw_callback
+ MOV lr,pc
+ MOV pc,v1
+ MOVVC a1,#0
+
+ @ return updated block ptr & size to caller
+
+ LDR a2,[fp,#-28]
+ LDR a3,[fp,#-24]
+ LDR ip,[v2,#aw_rsz_block]
+ LDR lr,[v2,#aw_rsz_size]
+ STR ip,[a2]
+ STR lr,[a3]
+
+ LDMEA fp,{v1,v2,fp,sp,pc}
+
+
+@ os_error *awrender_render(const char *doc,
+@ const struct awinfo_block *info,
+@ const os_trfm *trans,
+@ const int *vdu_vars,
+@ char **rsz_block,
+@ size_t *rsz_size,
+@ int wysiwyg_setting,
+@ int output_dest,
+@ size_t doc_size,
+@ void *routine,
+@ void *workspace);
+
+ .global awrender_render
+awrender_render: MOV ip,sp
+ STMFD sp!,{v1-v4,fp,ip,lr,pc}
+ SUB fp,ip,#4
+ SUB ip,sp,#512
+ CMP ip,sl
+ BLMI __rt_stkovf_split_big
+
+ LDR R12,[fp,#20]
+ LDR R14,=aw_temp
+ LDR R5,[fp,#4]
+ LDR R6,[fp,#12]
+ LDR R4,[R5] @ resizable block
+ LDR R7,[fp,#16]
+ STR R4,[R14,#aw_rsz_block]
+ STR R0,[R14,#aw_fixed_block] @ document ptr
+ STR R12,[R14,#aw_fixed_size] @ document size
+ LDR R12,[fp,#8]
+
+ STR R5,[sp,#-4]! @ ptr to receive block
+ STR R12,[sp,#-4]! @ ptr to receive size
+
+ LDR R12,[R12]
+ ADR R5,aw_callback
+ STR R12,[R14,#aw_rsz_size]
+
+ STR sl,[R14,#aw_sl]
+ STR fp,[R14,#aw_fp]
+
+ LDR R12,[fp,#28]
+ MOV lr,pc
+ LDR pc,[fp,#24]
+ MOVVC a1,#0
+
+ @ return updated block ptr & size to caller
+
+ LDR R7,=aw_temp
+ LDR R12,[sp],#4
+ LDR R4,[sp],#4
+ LDR R5,[R7,#aw_rsz_size]
+ LDR R6,[R7,#aw_rsz_block]
+ STR R5,[R12]
+ STR R6,[R4]
+
+ LDMEA fp,{v1-v4,fp,sp,pc}
+
+
+@ Callback routine for block resizing
+@ (passed to AWRender init and render routines)
+@
+@ entry R11 = reason code
+@ 0 = CallBackReason_Memory
+@ 3 = CallBackReason_Interface
+@ (0 => return capabilities)
+@ exit R0 => base of resizable block
+@ R1 = size of resizable block
+@ R2 => base of fixed block (or -1 if no fixed block)
+@ R3 = size of fixed block (or document in resizable block)
+@ VC if resize successful, VS and R0 => error otherwise
+
+aw_callback: TEQ R11,#3
+ TEQEQ R0,#0
+ MOVEQ R0,#1<<10 @ background colour supplied
+ TEQ R11,#0
+ LDREQ R11,=aw_temp
+ MOVNE PC,R14
+
+ CMP R0,#-1 @ read block size?
+ LDRNE R2,[R11,#aw_rsz_size]
+ MOVNE R1,R0 @ new block size
+ LDR R0,[R11,#aw_rsz_block]
+ BEQ aw_read
+
+ @ Note: because ArtworksRenderer seems to call
+ @ this routine for every scanline rendered
+ @ we never call realloc unless we have to in
+ @ order to expand the block. Also it calls
+ @ us with a size request of 0 which we must
+ @ safely ignore otherwise rendering will stop.
+
+ CMP R1,R2
+ BLS aw_read
+
+ STMFD R13!,{R1,R10-R12,R14}
+ LDR sl,[R11,#aw_sl]
+ LDR fp,[R11,#aw_fp]
+ BL realloc
+ LDMFD R13!,{R1,R10-R12,R14}
+
+ CMP R0,#0 @ did it work?
+ BEQ aw_nomem
+
+ STR R0,[R11]
+ STR R1,[R11,#aw_rsz_size]
+
+aw_read: @ return details of fixed block
+
+ LDR R2,[R11,#aw_fixed_block]
+ LDR R3,[R11,#aw_fixed_size]
+ SUBS R11,R11,R11 @ clear V
+ MOV PC,R14
+
+aw_nomem: STMFD R13!,{R10,R12,R14}
+ LDR sl,[R11,#aw_sl]
+ LDR fp,[R11,#aw_fp]
+ ADR R0,tok_nomem
+ BL messages_get
+ MOV a2,a1
+ LDR a1,=errblk + 4
+ BL strcpy
+ SUB R0,R0,#4 @ error number already 0
+ MOV R11,#0 @ restore reason code
+ CMP PC,#1<<31 @ set V
+ LDMFD R13!,{R10,R12,PC}
+
+tok_nomem: .asciz "NoMemory"
+ .align
+
+ .bss
+
+aw_temp: .space sizeof_aw
+ .type aw_temp, %object
+ .size aw_temp, . - aw_temp
+
+errblk: .space 256
+ .type errblk, %object
+ .size errblk, . - errblk
+
+ .end
+#endif
+
diff --git a/frontends/riscos/content-handlers/draw.c b/frontends/riscos/content-handlers/draw.c
new file mode 100644
index 000000000..f2bee16dc
--- /dev/null
+++ b/frontends/riscos/content-handlers/draw.c
@@ -0,0 +1,254 @@
+/*
+ * Copyright 2003 John M Bell <jmb202@ecs.soton.ac.uk>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Content for image/x-drawfile (RISC OS implementation).
+ *
+ * The DrawFile module is used to plot the DrawFile.
+ */
+
+#include "utils/config.h"
+#ifdef WITH_DRAW
+
+#include <string.h>
+#include <stdlib.h>
+#include "oslib/drawfile.h"
+
+#include "utils/config.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/utils.h"
+#include "content/content_protected.h"
+#include "desktop/plotters.h"
+
+#include "riscos/content-handlers/draw.h"
+#include "riscos/gui.h"
+
+typedef struct draw_content {
+ struct content base;
+
+ int x0, y0;
+} draw_content;
+
+static nserror draw_create(const content_handler *handler,
+ lwc_string *imime_type, const struct http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c);
+static bool draw_convert(struct content *c);
+static void draw_destroy(struct content *c);
+static bool draw_redraw(struct content *c, struct content_redraw_data *data,
+ const struct rect *clip, const struct redraw_context *ctx);
+static nserror draw_clone(const struct content *old, struct content **newc);
+static content_type draw_content_type(void);
+
+static const content_handler draw_content_handler = {
+ .create = draw_create,
+ .data_complete = draw_convert,
+ .destroy = draw_destroy,
+ .redraw = draw_redraw,
+ .clone = draw_clone,
+ .type = draw_content_type,
+ .no_share = false,
+};
+
+static const char *draw_types[] = {
+ "application/drawfile",
+ "application/x-drawfile",
+ "image/drawfile",
+ "image/x-drawfile"
+};
+
+CONTENT_FACTORY_REGISTER_TYPES(draw, draw_types, draw_content_handler)
+
+nserror draw_create(const content_handler *handler,
+ lwc_string *imime_type, const struct http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c)
+{
+ draw_content *draw;
+ nserror error;
+
+ draw = calloc(1, sizeof(draw_content));
+ if (draw == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init(&draw->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ free(draw);
+ return error;
+ }
+
+ *c = (struct content *) draw;
+
+ return NSERROR_OK;
+}
+
+/**
+ * Convert a CONTENT_DRAW for display.
+ *
+ * No conversion is necessary. We merely read the DrawFile dimensions and
+ * bounding box bottom-left.
+ */
+
+bool draw_convert(struct content *c)
+{
+ draw_content *draw = (draw_content *) c;
+ union content_msg_data msg_data;
+ const char *source_data;
+ unsigned long source_size;
+ const void *data;
+ os_box bbox;
+ os_error *error;
+ char *title;
+
+ source_data = content__get_source_data(c, &source_size);
+ data = source_data;
+
+ /* BBox contents in Draw units (256*OS unit) */
+ error = xdrawfile_bbox(0, (drawfile_diagram *) data,
+ (int) source_size, 0, &bbox);
+ if (error) {
+ LOG("xdrawfile_bbox: 0x%x: %s", error->errnum, error->errmess);
+ msg_data.error = error->errmess;
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ return false;
+ }
+
+ if (bbox.x1 > bbox.x0 && bbox.y1 > bbox.y0) {
+ /* c->width & c->height stored as (OS units/2)
+ => divide by 512 to convert from draw units */
+ c->width = ((bbox.x1 - bbox.x0) / 512);
+ c->height = ((bbox.y1 - bbox.y0) / 512);
+ }
+ else
+ /* invalid/undefined bounding box */
+ c->height = c->width = 0;
+
+ draw->x0 = bbox.x0;
+ draw->y0 = bbox.y0;
+
+ title = messages_get_buff("DrawTitle",
+ nsurl_access_leaf(llcache_handle_get_url(c->llcache)),
+ c->width, c->height);
+ if (title != NULL) {
+ content__set_title(c, title);
+ free(title);
+ }
+
+ content_set_ready(c);
+ content_set_done(c);
+ /* Done: update status bar */
+ content_set_status(c, "");
+ return true;
+}
+
+
+/**
+ * Destroy a CONTENT_DRAW and free all resources it owns.
+ */
+
+void draw_destroy(struct content *c)
+{
+}
+
+
+/**
+ * Redraw a CONTENT_DRAW.
+ */
+
+bool draw_redraw(struct content *c, struct content_redraw_data *data,
+ const struct rect *clip, const struct redraw_context *ctx)
+{
+ draw_content *draw = (draw_content *) c;
+ os_trfm matrix;
+ const char *source_data;
+ unsigned long source_size;
+ const void *src_data;
+ os_error *error;
+
+ if (ctx->plot->flush && !ctx->plot->flush())
+ return false;
+
+ if (!c->width || !c->height)
+ return false;
+
+ source_data = content__get_source_data(c, &source_size);
+ src_data = source_data;
+
+ /* Scaled image. Transform units (65536*OS units) */
+ matrix.entries[0][0] = data->width * 65536 / c->width;
+ matrix.entries[0][1] = 0;
+ matrix.entries[1][0] = 0;
+ matrix.entries[1][1] = data->height * 65536 / c->height;
+ /* Draw units. (x,y) = bottom left */
+ matrix.entries[2][0] = ro_plot_origin_x * 256 + data->x * 512 -
+ draw->x0 * data->width / c->width;
+ matrix.entries[2][1] = ro_plot_origin_y * 256 -
+ (data->y + data->height) * 512 -
+ draw->y0 * data->height / c->height;
+
+ error = xdrawfile_render(0, (drawfile_diagram *) src_data,
+ (int) source_size, &matrix, 0, 0);
+ if (error) {
+ LOG("xdrawfile_render: 0x%x: %s", error->errnum, error->errmess);
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Clone a CONTENT_DRAW
+ */
+
+nserror draw_clone(const struct content *old, struct content **newc)
+{
+ draw_content *draw;
+ nserror error;
+
+ draw = calloc(1, sizeof(draw_content));
+ if (draw == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__clone(old, &draw->base);
+ if (error != NSERROR_OK) {
+ content_destroy(&draw->base);
+ return error;
+ }
+
+ /* Simply rerun convert */
+ if (old->status == CONTENT_STATUS_READY ||
+ old->status == CONTENT_STATUS_DONE) {
+ if (draw_convert(&draw->base) == false) {
+ content_destroy(&draw->base);
+ return NSERROR_CLONE_FAILED;
+ }
+ }
+
+ *newc = (struct content *) draw;
+
+ return NSERROR_OK;
+}
+
+content_type draw_content_type(void)
+{
+ return CONTENT_IMAGE;
+}
+
+#endif
diff --git a/frontends/riscos/content-handlers/draw.h b/frontends/riscos/content-handlers/draw.h
new file mode 100644
index 000000000..9f5baf6dc
--- /dev/null
+++ b/frontends/riscos/content-handlers/draw.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2003 John M Bell <jmb202@ecs.soton.ac.uk>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Content for image/x-drawfile (RISC OS interface).
+ */
+
+#ifndef _NETSURF_RISCOS_DRAW_H_
+#define _NETSURF_RISCOS_DRAW_H_
+
+#include "utils/config.h"
+#include "utils/errors.h"
+
+#ifdef WITH_DRAW
+
+nserror draw_init(void);
+
+#else
+
+static inline nserror draw_init(void)
+{
+ return NSERROR_OK;
+}
+
+#endif /* WITH_DRAW */
+
+#endif
diff --git a/frontends/riscos/content-handlers/sprite.c b/frontends/riscos/content-handlers/sprite.c
new file mode 100644
index 000000000..12fed4931
--- /dev/null
+++ b/frontends/riscos/content-handlers/sprite.c
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2003 John M Bell <jmb202@ecs.soton.ac.uk>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Content for image/x-riscos-sprite (RISC OS implementation).
+ *
+ * No conversion is necessary: we can render RISC OS sprites directly under
+ * RISC OS.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include "oslib/osspriteop.h"
+
+#include "utils/config.h"
+#include "utils/config.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/utils.h"
+#include "content/content_protected.h"
+#include "desktop/plotters.h"
+
+#include "riscos/gui.h"
+#include "riscos/image.h"
+#include "riscos/content-handlers/sprite.h"
+
+#ifdef WITH_SPRITE
+
+typedef struct sprite_content {
+ struct content base;
+
+ void *data;
+} sprite_content;
+
+static nserror sprite_create(const content_handler *handler,
+ lwc_string *imime_type, const struct http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c);
+static bool sprite_convert(struct content *c);
+static void sprite_destroy(struct content *c);
+static bool sprite_redraw(struct content *c, struct content_redraw_data *data,
+ const struct rect *clip, const struct redraw_context *ctx);
+static nserror sprite_clone(const struct content *old, struct content **newc);
+static content_type sprite_content_type(void);
+
+static const content_handler sprite_content_handler = {
+ .create = sprite_create,
+ .data_complete = sprite_convert,
+ .destroy = sprite_destroy,
+ .redraw = sprite_redraw,
+ .clone = sprite_clone,
+ .type = sprite_content_type,
+ .no_share = false,
+};
+
+static const char *sprite_types[] = {
+ "image/x-riscos-sprite"
+};
+
+CONTENT_FACTORY_REGISTER_TYPES(sprite, sprite_types, sprite_content_handler)
+
+nserror sprite_create(const content_handler *handler,
+ lwc_string *imime_type, const struct http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c)
+{
+ sprite_content *sprite;
+ nserror error;
+
+ sprite = calloc(1, sizeof(sprite_content));
+ if (sprite == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init(&sprite->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ free(sprite);
+ return error;
+ }
+
+ *c = (struct content *) sprite;
+
+ return NSERROR_OK;
+}
+
+/**
+ * Convert a CONTENT_SPRITE for display.
+ *
+ * No conversion is necessary. We merely read the sprite dimensions.
+ */
+
+bool sprite_convert(struct content *c)
+{
+ sprite_content *sprite = (sprite_content *) c;
+ os_error *error;
+ int w, h;
+ union content_msg_data msg_data;
+ const char *source_data;
+ unsigned long source_size;
+ const void *sprite_data;
+ char *title;
+
+ source_data = content__get_source_data(c, &source_size);
+
+ sprite_data = source_data - 4;
+ osspriteop_area *area = (osspriteop_area*) sprite_data;
+ sprite->data = area;
+
+ /* check for bad data */
+ if ((int)source_size + 4 != area->used) {
+ msg_data.error = messages_get("BadSprite");
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ return false;
+ }
+
+ error = xosspriteop_read_sprite_info(osspriteop_PTR,
+ (osspriteop_area *)0x100,
+ (osspriteop_id) ((char *) area + area->first),
+ &w, &h, NULL, NULL);
+ if (error) {
+ LOG("xosspriteop_read_sprite_info: 0x%x: %s", error->errnum, error->errmess);
+ msg_data.error = error->errmess;
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ return false;
+ }
+
+ c->width = w;
+ c->height = h;
+
+ /* set title text */
+ title = messages_get_buff("SpriteTitle",
+ nsurl_access_leaf(llcache_handle_get_url(c->llcache)),
+ c->width, c->height);
+ if (title != NULL) {
+ content__set_title(c, title);
+ free(title);
+ }
+ content_set_ready(c);
+ content_set_done(c);
+ /* Done: update status bar */
+ content_set_status(c, "");
+ return true;
+}
+
+
+/**
+ * Destroy a CONTENT_SPRITE and free all resources it owns.
+ */
+
+void sprite_destroy(struct content *c)
+{
+ /* do not free c->data.sprite.data at it is simply a pointer to
+ * 4 bytes beforec->source_data. */
+}
+
+
+/**
+ * Redraw a CONTENT_SPRITE.
+ */
+
+bool sprite_redraw(struct content *c, struct content_redraw_data *data,
+ const struct rect *clip, const struct redraw_context *ctx)
+{
+ sprite_content *sprite = (sprite_content *) c;
+
+ if (ctx->plot->flush && !ctx->plot->flush())
+ return false;
+
+ return image_redraw(sprite->data,
+ ro_plot_origin_x + data->x * 2,
+ ro_plot_origin_y - data->y * 2,
+ data->width, data->height,
+ c->width,
+ c->height,
+ data->background_colour,
+ false, false, false,
+ IMAGE_PLOT_OS);
+}
+
+nserror sprite_clone(const struct content *old, struct content **newc)
+{
+ sprite_content *sprite;
+ nserror error;
+
+ sprite = calloc(1, sizeof(sprite_content));
+ if (sprite == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__clone(old, &sprite->base);
+ if (error != NSERROR_OK) {
+ content_destroy(&sprite->base);
+ return error;
+ }
+
+ /* Simply rerun convert */
+ if (old->status == CONTENT_STATUS_READY ||
+ old->status == CONTENT_STATUS_DONE) {
+ if (sprite_convert(&sprite->base) == false) {
+ content_destroy(&sprite->base);
+ return NSERROR_CLONE_FAILED;
+ }
+ }
+
+ *newc = (struct content *) sprite;
+
+ return NSERROR_OK;
+}
+
+content_type sprite_content_type(void)
+{
+ return CONTENT_IMAGE;
+}
+
+#endif
+
+
+/**
+ * Returns the bit depth of a sprite
+ *
+ * \param s sprite
+ * \return depth in bpp
+ */
+
+byte sprite_bpp(const osspriteop_header *s)
+{
+ /* bit 31 indicates the presence of a full alpha channel
+ * rather than a binary mask */
+ int type = ((unsigned)s->mode >> osspriteop_TYPE_SHIFT) & 15;
+ byte bpp = 0;
+
+ switch (type) {
+ case osspriteop_TYPE_OLD:
+ {
+ bits psr;
+ int val;
+ if (!xos_read_mode_variable(s->mode,
+ os_MODEVAR_LOG2_BPP, &val, &psr) &&
+ !(psr & _C))
+ bpp = 1 << val;
+ }
+ break;
+ case osspriteop_TYPE1BPP: bpp = 1; break;
+ case osspriteop_TYPE2BPP: bpp = 2; break;
+ case osspriteop_TYPE4BPP: bpp = 4; break;
+ case osspriteop_TYPE8BPP: bpp = 8; break;
+ case osspriteop_TYPE16BPP: bpp = 16; break;
+ case osspriteop_TYPE32BPP: bpp = 32; break;
+ case osspriteop_TYPE_CMYK: bpp = 32; break;
+ }
+ return bpp;
+}
diff --git a/frontends/riscos/content-handlers/sprite.h b/frontends/riscos/content-handlers/sprite.h
new file mode 100644
index 000000000..ab6d312a5
--- /dev/null
+++ b/frontends/riscos/content-handlers/sprite.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2003 John M Bell <jmb202@ecs.soton.ac.uk>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Content for image/x-riscos-sprite (RISC OS interface).
+ */
+
+#ifndef _NETSURF_RISCOS_SPRITE_H_
+#define _NETSURF_RISCOS_SPRITE_H_
+
+#include "utils/config.h"
+#include "utils/errors.h"
+
+#ifdef WITH_SPRITE
+
+nserror sprite_init(void);
+
+#else
+
+static inline nserror sprite_init(void)
+{
+ return NSERROR_OK;
+}
+
+#endif
+
+byte sprite_bpp(const osspriteop_header *s);
+
+#endif
diff --git a/frontends/riscos/cookies.c b/frontends/riscos/cookies.c
new file mode 100644
index 000000000..93c9f39cf
--- /dev/null
+++ b/frontends/riscos/cookies.c
@@ -0,0 +1,385 @@
+/*
+ * Copyright 2006 Richard Wilson <info@tinct.net>
+ * Copyright 2010 Stephen Fryatt <stevef@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Cookies (implementation).
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "oslib/wimp.h"
+#include "oslib/wimpspriteop.h"
+
+#include "utils/nsoption.h"
+#include "utils/messages.h"
+#include "utils/log.h"
+#include "content/urldb.h"
+#include "desktop/cookie_manager.h"
+#include "desktop/tree.h"
+#include "desktop/textinput.h"
+
+#include "riscos/cookies.h"
+#include "riscos/dialog.h"
+#include "riscos/menus.h"
+#include "riscos/toolbar.h"
+#include "riscos/treeview.h"
+#include "riscos/wimp.h"
+#include "riscos/wimp_event.h"
+
+static void ro_gui_cookies_toolbar_update_buttons(void);
+static void ro_gui_cookies_toolbar_save_buttons(char *config);
+static bool ro_gui_cookies_menu_prepare(wimp_w w, wimp_i i, wimp_menu *menu,
+ wimp_pointer *pointer);
+static void ro_gui_cookies_menu_warning(wimp_w w, wimp_i i, wimp_menu *menu,
+ wimp_selection *selection, menu_action action);
+static bool ro_gui_cookies_menu_select(wimp_w w, wimp_i i, wimp_menu *menu,
+ wimp_selection *selection, menu_action action);
+static void ro_gui_cookies_toolbar_click(button_bar_action action);
+
+struct ro_treeview_callbacks ro_cookies_treeview_callbacks = {
+ ro_gui_cookies_toolbar_click,
+ ro_gui_cookies_toolbar_update_buttons,
+ ro_gui_cookies_toolbar_save_buttons
+};
+
+/* The RISC OS cookie window, toolbar and treeview data. */
+
+static struct ro_cookies_window {
+ wimp_w window;
+ struct toolbar *toolbar;
+ ro_treeview *tv;
+ wimp_menu *menu;
+} cookies_window;
+
+/**
+ * Pre-Initialise the cookies tree. This is called for things that
+ * need to be done at the gui_init() stage, such as loading templates.
+ */
+
+void ro_gui_cookies_preinitialise(void)
+{
+ /* Create our window. */
+
+ cookies_window.window = ro_gui_dialog_create("tree");
+ ro_gui_set_window_title(cookies_window.window,
+ messages_get("Cookies"));
+}
+
+/**
+ * Initialise cookies tree, at the gui_init2() stage.
+ */
+
+void ro_gui_cookies_postinitialise(void)
+{
+ /* Create our toolbar. */
+
+ cookies_window.toolbar = ro_toolbar_create(NULL, cookies_window.window,
+ THEME_STYLE_COOKIES_TOOLBAR, TOOLBAR_FLAGS_NONE,
+ ro_treeview_get_toolbar_callbacks(), NULL,
+ "HelpCookiesToolbar");
+ if (cookies_window.toolbar != NULL) {
+ ro_toolbar_add_buttons(cookies_window.toolbar,
+ cookies_toolbar_buttons,
+ nsoption_charp(toolbar_cookies));
+ ro_toolbar_rebuild(cookies_window.toolbar);
+ }
+
+ /* Create the treeview with the window and toolbar. */
+
+ cookies_window.tv = ro_treeview_create(cookies_window.window,
+ cookies_window.toolbar, &ro_cookies_treeview_callbacks,
+ TREE_COOKIES);
+ if (cookies_window.tv == NULL) {
+ LOG("Failed to allocate treeview");
+ return;
+ }
+
+ ro_toolbar_update_client_data(cookies_window.toolbar,
+ cookies_window.tv);
+
+ /* Build the cookies window menu. */
+
+ static const struct ns_menu cookies_definition = {
+ "Cookies", {
+ { "Cookies", NO_ACTION, 0 },
+ { "Cookies.Expand", TREE_EXPAND_ALL, 0 },
+ { "Cookies.Expand.All", TREE_EXPAND_ALL, 0 },
+ { "Cookies.Expand.Folders", TREE_EXPAND_FOLDERS, 0 },
+ { "Cookies.Expand.Links", TREE_EXPAND_LINKS, 0 },
+ { "Cookies.Collapse", TREE_COLLAPSE_ALL, 0 },
+ { "Cookies.Collapse.All", TREE_COLLAPSE_ALL, 0 },
+ { "Cookies.Collapse.Folders", TREE_COLLAPSE_FOLDERS, 0 },
+ { "Cookies.Collapse.Links", TREE_COLLAPSE_LINKS, 0 },
+ { "Cookies.Toolbars", NO_ACTION, 0 },
+ { "_Cookies.Toolbars.ToolButtons", TOOLBAR_BUTTONS, 0 },
+ { "Cookies.Toolbars.EditToolbar",TOOLBAR_EDIT, 0 },
+ { "Selection", TREE_SELECTION, 0 },
+ { "Selection.Delete", TREE_SELECTION_DELETE, 0 },
+ { "SelectAll", TREE_SELECT_ALL, 0 },
+ { "Clear", TREE_CLEAR_SELECTION, 0 },
+ {NULL, 0, 0}
+ }
+ };
+ cookies_window.menu = ro_gui_menu_define_menu(&cookies_definition);
+
+ ro_gui_wimp_event_register_menu(cookies_window.window,
+ cookies_window.menu, false, false);
+ ro_gui_wimp_event_register_menu_prepare(cookies_window.window,
+ ro_gui_cookies_menu_prepare);
+ ro_gui_wimp_event_register_menu_selection(cookies_window.window,
+ ro_gui_cookies_menu_select);
+ ro_gui_wimp_event_register_menu_warning(cookies_window.window,
+ ro_gui_cookies_menu_warning);
+}
+
+/**
+ * Destroy the cookies window.
+ */
+
+void ro_gui_cookies_destroy(void)
+{
+ if (cookies_window.tv == NULL)
+ return;
+
+ ro_treeview_destroy(cookies_window.tv);
+}
+
+/**
+ * Open the cookies window.
+ *
+ */
+
+void ro_gui_cookies_open(void)
+{
+ ro_gui_cookies_toolbar_update_buttons();
+
+ if (!ro_gui_dialog_open_top(cookies_window.window,
+ cookies_window.toolbar, 600, 800)) {
+ ro_treeview_set_origin(cookies_window.tv, 0,
+ -(ro_toolbar_height(cookies_window.toolbar)));
+ }
+}
+
+
+/**
+ * Handle toolbar button clicks.
+ *
+ * \param action The action to handle
+ */
+
+void ro_gui_cookies_toolbar_click(button_bar_action action)
+{
+ switch (action) {
+ case TOOLBAR_BUTTON_DELETE:
+ cookie_manager_keypress(NS_KEY_DELETE_LEFT);
+ break;
+
+ case TOOLBAR_BUTTON_EXPAND:
+ cookie_manager_expand(false);
+ break;
+
+ case TOOLBAR_BUTTON_COLLAPSE:
+ cookie_manager_contract(false);
+ break;
+
+ case TOOLBAR_BUTTON_OPEN:
+ cookie_manager_expand(true);
+ break;
+
+ case TOOLBAR_BUTTON_CLOSE:
+ cookie_manager_contract(true);
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+/**
+ * Update the button state in the cookies toolbar.
+ */
+
+void ro_gui_cookies_toolbar_update_buttons(void)
+{
+ ro_toolbar_set_button_shaded_state(cookies_window.toolbar,
+ TOOLBAR_BUTTON_DELETE,
+ !cookie_manager_has_selection());
+}
+
+
+/**
+ * Save a new button arrangement in the cookies toolbar.
+ *
+ * \param *config The new button configuration string.
+ */
+
+void ro_gui_cookies_toolbar_save_buttons(char *config)
+{
+ nsoption_set_charp(toolbar_cookies, config);
+ ro_gui_save_options();
+}
+
+
+/**
+ * Prepare the cookies menu for opening
+ *
+ * \param w The window owning the menu.
+ * \param i The icon owning the menu.
+ * \param *menu The menu about to be opened.
+ * \param *pointer Pointer to the relevant wimp event block, or
+ * NULL for an Adjust click.
+ * \return true if the event was handled; else false.
+ */
+
+bool ro_gui_cookies_menu_prepare(wimp_w w, wimp_i i, wimp_menu *menu,
+ wimp_pointer *pointer)
+{
+ bool selection;
+
+ if (menu != cookies_window.menu)
+ return false;
+
+ selection = cookie_manager_has_selection();
+
+ ro_gui_menu_set_entry_shaded(cookies_window.menu,
+ TREE_SELECTION, !selection);
+ ro_gui_menu_set_entry_shaded(cookies_window.menu,
+ TREE_CLEAR_SELECTION, !selection);
+
+ ro_gui_menu_set_entry_shaded(menu, TOOLBAR_BUTTONS,
+ ro_toolbar_menu_option_shade(cookies_window.toolbar));
+ ro_gui_menu_set_entry_ticked(menu, TOOLBAR_BUTTONS,
+ ro_toolbar_menu_buttons_tick(cookies_window.toolbar));
+
+ ro_gui_menu_set_entry_shaded(menu, TOOLBAR_EDIT,
+ ro_toolbar_menu_edit_shade(cookies_window.toolbar));
+ ro_gui_menu_set_entry_ticked(menu, TOOLBAR_EDIT,
+ ro_toolbar_menu_edit_tick(cookies_window.toolbar));
+
+ return true;
+}
+
+/**
+ * Handle submenu warnings for the cookies menu
+ *
+ * \param w The window owning the menu.
+ * \param i The icon owning the menu.
+ * \param *menu The menu to which the warning applies.
+ * \param *selection The wimp menu selection data.
+ * \param action The selected menu action.
+ */
+
+void ro_gui_cookies_menu_warning(wimp_w w, wimp_i i, wimp_menu *menu,
+ wimp_selection *selection, menu_action action)
+{
+ /* Do nothing */
+}
+
+/**
+ * Handle selections from the cookies menu
+ *
+ * \param w The window owning the menu.
+ * \param i The icon owning the menu.
+ * \param *menu The menu from which the selection was made.
+ * \param *selection The wimp menu selection data.
+ * \param action The selected menu action.
+ * \return true if action accepted; else false.
+ */
+
+bool ro_gui_cookies_menu_select(wimp_w w, wimp_i i, wimp_menu *menu,
+ wimp_selection *selection, menu_action action)
+{
+ switch (action) {
+ case TREE_EXPAND_ALL:
+ cookie_manager_expand(false);
+ return true;
+ case TREE_EXPAND_FOLDERS:
+ cookie_manager_expand(true);
+ return true;
+ case TREE_EXPAND_LINKS:
+ cookie_manager_expand(false);
+ return true;
+ case TREE_COLLAPSE_ALL:
+ cookie_manager_contract(true);
+ return true;
+ case TREE_COLLAPSE_FOLDERS:
+ cookie_manager_contract(true);
+ return true;
+ case TREE_COLLAPSE_LINKS:
+ cookie_manager_contract(false);
+ return true;
+ case TREE_SELECTION_DELETE:
+ cookie_manager_keypress(NS_KEY_DELETE_LEFT);
+ return true;
+ case TREE_SELECT_ALL:
+ cookie_manager_keypress(NS_KEY_SELECT_ALL);
+ return true;
+ case TREE_CLEAR_SELECTION:
+ cookie_manager_keypress(NS_KEY_CLEAR_SELECTION);
+ return true;
+ case TOOLBAR_BUTTONS:
+ ro_toolbar_set_display_buttons(cookies_window.toolbar,
+ !ro_toolbar_get_display_buttons(
+ cookies_window.toolbar));
+ return true;
+ case TOOLBAR_EDIT:
+ ro_toolbar_toggle_edit(cookies_window.toolbar);
+ return true;
+ default:
+ return false;
+ }
+
+ return false;
+}
+
+/**
+ * Check if a particular window handle is the cookies window
+ *
+ * \param window the window in question
+ * \return true if this window is the cookies
+ */
+
+bool ro_gui_cookies_check_window(wimp_w window)
+{
+ if (cookies_window.window == window)
+ return true;
+ else
+ return false;
+}
+
+/**
+ * Check if a particular menu handle is the cookies menu
+ *
+ * \param *menu The menu in question.
+ * \return true if this menu is the cookies menu
+ */
+
+bool ro_gui_cookies_check_menu(wimp_menu *menu)
+{
+ if (cookies_window.menu == menu)
+ return true;
+ else
+ return false;
+}
+
diff --git a/frontends/riscos/cookies.h b/frontends/riscos/cookies.h
new file mode 100644
index 000000000..b7313393e
--- /dev/null
+++ b/frontends/riscos/cookies.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2006 Richard Wilson <info@tinct.net>
+ * Copyright 2010 Stephen Fryatt <stevef@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Cookies (interface).
+ */
+
+#ifndef _NETSURF_RISCOS_COOKIES_H_
+#define _NETSURF_RISCOS_COOKIES_H_
+
+#include "riscos/menus.h"
+
+void ro_gui_cookies_preinitialise(void);
+void ro_gui_cookies_postinitialise(void);
+void ro_gui_cookies_destroy(void);
+bool ro_gui_cookies_check_window(wimp_w window);
+bool ro_gui_cookies_check_menu(wimp_menu *menu);
+
+void ro_gui_cookies_open(void);
+
+#endif
+
diff --git a/frontends/riscos/dialog.c b/frontends/riscos/dialog.c
new file mode 100644
index 000000000..d4356086d
--- /dev/null
+++ b/frontends/riscos/dialog.c
@@ -0,0 +1,816 @@
+/*
+ * Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
+ * Copyright 2005 James Bursa <bursa@users.sourceforge.net>
+ * Copyright 2003 John M Bell <jmb202@ecs.soton.ac.uk>
+ * Copyright 2005 Richard Wilson <info@tinct.net>
+ * Copyright 2004 Andrew Timmins <atimmins@blueyonder.co.uk>
+ * Copyright 2005 Adrian Lees <adrianl@users.sourceforge.net>
+ * Copyright 2014 Stephen Fryatt <stevef@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "utils/config.h"
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <oslib/colourtrans.h>
+#include <oslib/osfile.h>
+#include <oslib/osgbpb.h>
+#include <oslib/osspriteop.h>
+#include <oslib/wimp.h>
+
+#include "utils/nsoption.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/nsurl.h"
+#include "desktop/version.h"
+#include "desktop/browser.h"
+
+#include "riscos/configure.h"
+#include "riscos/cookies.h"
+#include "riscos/dialog.h"
+#include "riscos/global_history.h"
+#include "riscos/gui.h"
+#include "riscos/hotlist.h"
+#include "riscos/menus.h"
+#include "riscos/save.h"
+#include "riscos/sslcert.h"
+#include "riscos/toolbar.h"
+#include "riscos/url_complete.h"
+#include "riscos/url_suggest.h"
+#include "riscos/wimp.h"
+#include "riscos/wimp_event.h"
+#include "riscos/wimputils.h"
+
+#define ICON_ZOOM_VALUE 1
+#define ICON_ZOOM_DEC 2
+#define ICON_ZOOM_INC 3
+#define ICON_ZOOM_FRAMES 5
+#define ICON_ZOOM_CANCEL 7
+#define ICON_ZOOM_OK 8
+
+/* The maximum number of persistent dialogues
+*/
+#define MAX_PERSISTENT 64
+
+
+wimp_w dialog_info, dialog_saveas,
+ dialog_401li,
+ dialog_zoom, dialog_pageinfo, dialog_objinfo, dialog_tooltip,
+ dialog_warning,
+ dialog_folder, dialog_entry, dialog_search, dialog_print,
+ dialog_url_complete, dialog_openurl;
+
+struct gui_window *ro_gui_current_zoom_gui;
+
+
+/* A simple mapping of parent and child
+*/
+static struct {
+ wimp_w dialog;
+ wimp_w parent;
+} persistent_dialog[MAX_PERSISTENT];
+
+
+static bool ro_gui_dialog_open_url_init(void);
+static bool ro_gui_dialog_openurl_apply(wimp_w w);
+static bool ro_gui_dialog_open_url_menu_prepare(wimp_w w, wimp_i i,
+ wimp_menu *menu, wimp_pointer *pointer);
+
+static bool ro_gui_dialog_zoom_apply(wimp_w w);
+
+/**
+ * Load and create dialogs from template file.
+ */
+
+void ro_gui_dialog_init(void)
+{
+ /* warning dialog */
+ dialog_warning = ro_gui_dialog_create("warning");
+ ro_gui_wimp_event_register_ok(dialog_warning, ICON_WARNING_CONTINUE,
+ NULL);
+ ro_gui_wimp_event_set_help_prefix(dialog_warning, "HelpWarning");
+
+ /* tooltip for history */
+ dialog_tooltip = ro_gui_dialog_create("tooltip");
+
+ /* configure window */
+ ro_gui_configure_initialise();
+
+ /* 401 login window */
+ ro_gui_401login_init();
+
+ /* theme installation */
+ dialog_theme_install = ro_gui_dialog_create("theme_inst");
+ ro_gui_wimp_event_register_cancel(dialog_theme_install,
+ ICON_THEME_INSTALL_CANCEL);
+ ro_gui_wimp_event_register_ok(dialog_theme_install,
+ ICON_THEME_INSTALL_INSTALL,
+ ro_gui_theme_install_apply);
+ ro_gui_wimp_event_set_help_prefix(dialog_theme_install, "HelpThemeInst");
+
+ /* search */
+ ro_gui_search_init();
+
+ /* print */
+ ro_gui_print_init();
+
+ /* about us */
+ dialog_info = ro_gui_dialog_create("info");
+ ro_gui_set_icon_string(dialog_info, 4, netsurf_version, true);
+ ro_gui_wimp_event_set_help_prefix(dialog_info, "HelpAppInfo");
+
+ /* page info */
+ dialog_pageinfo = ro_gui_dialog_create("pageinfo");
+ ro_gui_wimp_event_set_help_prefix(dialog_pageinfo, "HelpPageInfo");
+
+ /* object info */
+ dialog_objinfo = ro_gui_dialog_create("objectinfo");
+ ro_gui_wimp_event_set_help_prefix(dialog_objinfo, "HelpObjInfo");
+
+ /* save as */
+ dialog_saveas = ro_gui_saveas_create("saveas");
+ ro_gui_wimp_event_register_button(dialog_saveas, ICON_SAVE_ICON,
+ ro_gui_save_start_drag);
+ ro_gui_wimp_event_register_text_field(dialog_saveas, ICON_SAVE_PATH);
+ ro_gui_wimp_event_register_cancel(dialog_saveas, ICON_SAVE_CANCEL);
+ ro_gui_wimp_event_register_ok(dialog_saveas, ICON_SAVE_OK,
+ ro_gui_save_ok);
+ ro_gui_wimp_event_set_help_prefix(dialog_saveas, "HelpSaveAs");
+
+ /* url suggestion */
+ dialog_url_complete = ro_gui_dialog_create("url_suggest");
+ ro_gui_wimp_event_register_mouse_click(dialog_url_complete,
+ ro_gui_url_complete_click);
+ ro_gui_wimp_event_register_pointer_entering_window(dialog_url_complete,
+ ro_gui_url_complete_entering);
+ ro_gui_wimp_event_register_redraw_window(dialog_url_complete,
+ ro_gui_url_complete_redraw);
+ ro_gui_wimp_event_set_help_prefix(dialog_url_complete, "HelpAutoURL");
+
+ /* open URL */
+ ro_gui_dialog_open_url_init();
+
+ /* scale view */
+ dialog_zoom = ro_gui_dialog_create("zoom");
+ ro_gui_wimp_event_register_numeric_field(dialog_zoom, ICON_ZOOM_VALUE,
+ ICON_ZOOM_INC, ICON_ZOOM_DEC, 10, 1600, 10, 0);
+ ro_gui_wimp_event_register_checkbox(dialog_zoom, ICON_ZOOM_FRAMES);
+ ro_gui_wimp_event_register_cancel(dialog_zoom, ICON_ZOOM_CANCEL);
+ ro_gui_wimp_event_register_ok(dialog_zoom, ICON_ZOOM_OK,
+ ro_gui_dialog_zoom_apply);
+ ro_gui_wimp_event_set_help_prefix(dialog_zoom, "HelpScaleView");
+
+ /* Treeview initialisation has moved to the end, to allow any
+ * associated dialogues to be set up first.
+ */
+
+ /* certificate verification window */
+ ro_gui_cert_preinitialise();
+
+ /* hotlist window */
+ ro_gui_hotlist_preinitialise();
+
+ /* global history window */
+ ro_gui_global_history_preinitialise();
+
+ /* cookies window */
+ ro_gui_cookies_preinitialise();
+}
+
+
+/**
+ * Create a window from a template.
+ *
+ * \param template_name name of template to load
+ * \return window handle
+ *
+ * Exits through die() on error.
+ */
+
+wimp_w ro_gui_dialog_create(const char *template_name)
+{
+ wimp_window *window;
+ wimp_w w;
+ os_error *error;
+
+ window = ro_gui_dialog_load_template(template_name);
+
+ /* create window */
+ window->sprite_area = gui_sprites;
+ error = xwimp_create_window(window, &w);
+ if (error) {
+ LOG("xwimp_create_window: 0x%x: %s", error->errnum, error->errmess);
+ xwimp_close_template();
+ die(error->errmess);
+ }
+
+ /* the window definition is copied by the wimp and may be freed */
+ free(window);
+
+ return w;
+}
+
+
+/**
+ * Load a template without creating a window.
+ *
+ * \param template_name name of template to load
+ * \return window block
+ *
+ * Exits through die() on error.
+ */
+
+wimp_window * ro_gui_dialog_load_template(const char *template_name)
+{
+ char name[20];
+ int context, window_size, data_size;
+ char *data;
+ wimp_window *window;
+ os_error *error;
+
+ /* Template names must be <= 11 chars long */
+ assert(strlen(template_name) <= 11);
+
+ /* wimp_load_template won't accept a const char * */
+ strncpy(name, template_name, sizeof name);
+
+ /* find required buffer sizes */
+ error = xwimp_load_template(wimp_GET_SIZE, 0, 0, wimp_NO_FONTS,
+ name, 0, &window_size, &data_size, &context);
+ if (error) {
+ LOG("xwimp_load_template: 0x%x: %s", error->errnum, error->errmess);
+ xwimp_close_template();
+ die(error->errmess);
+ }
+ if (!context) {
+ LOG("template '%s' missing", template_name);
+ xwimp_close_template();
+ die("Template");
+ }
+
+ /* allocate space for indirected data and temporary window buffer */
+ data = malloc(data_size);
+ window = malloc(window_size);
+ if (!data || !window) {
+ xwimp_close_template();
+ die("NoMemory");
+ }
+
+ /* load template */
+ error = xwimp_load_template(window, data, data + data_size,
+ wimp_NO_FONTS, name, 0, 0, 0, 0);
+ if (error) {
+ LOG("xwimp_load_template: 0x%x: %s", error->errnum, error->errmess);
+ xwimp_close_template();
+ die(error->errmess);
+ }
+
+ return window;
+}
+
+
+/**
+ * Open a dialog box, centred on the screen.
+ */
+
+void ro_gui_dialog_open(wimp_w w)
+{
+ int screen_x, screen_y, dx, dy;
+ wimp_window_state state;
+ os_error *error;
+
+ /* find screen centre in os units */
+ ro_gui_screen_size(&screen_x, &screen_y);
+ screen_x /= 2;
+ screen_y /= 2;
+
+ /* centre and open */
+ state.w = w;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+ dx = (state.visible.x1 - state.visible.x0) / 2;
+ dy = (state.visible.y1 - state.visible.y0) / 2;
+ state.visible.x0 = screen_x - dx;
+ state.visible.x1 = screen_x + dx;
+ state.visible.y0 = screen_y - dy;
+ state.visible.y1 = screen_y + dy;
+ state.next = wimp_TOP;
+ ro_gui_open_window_request(PTR_WIMP_OPEN(&state));
+
+ /* Set the caret position */
+ ro_gui_set_caret_first(w);
+}
+
+
+/**
+ * Close a dialog box.
+ */
+
+void ro_gui_dialog_close(wimp_w close)
+{
+ int i;
+ wimp_caret caret;
+ os_error *error;
+
+ /* Check if we're a persistent window */
+ for (i = 0; i < MAX_PERSISTENT; i++) {
+ if (persistent_dialog[i].dialog == close) {
+ /* We are => invalidate record */
+ persistent_dialog[i].parent = NULL;
+ persistent_dialog[i].dialog = NULL;
+ break;
+ }
+ }
+
+ /* Close any child windows */
+ ro_gui_dialog_close_persistent(close);
+
+ /* Give the caret back to the parent window. This code relies on
+ the fact that only tree windows and browser windows open
+ persistent dialogues, as the caret gets placed to no icon.
+ */
+ error = xwimp_get_caret_position(&caret);
+ if (error) {
+ LOG("xwimp_get_caret_position: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ } else if (caret.w == close) {
+ /* Check if we are a persistent window */
+ if (i < MAX_PERSISTENT) {
+ error = xwimp_set_caret_position(
+ persistent_dialog[i].parent,
+ wimp_ICON_WINDOW, -100, -100,
+ 32, -1);
+ /* parent may have been closed first */
+ if ((error) && (error->errnum != 0x287)) {
+ LOG("xwimp_set_caret_position: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+ }
+ }
+
+ error = xwimp_close_window(close);
+ if (error) {
+ LOG("xwimp_close_window: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+}
+
+
+/**
+ * Moves a window to the top of the stack.
+ *
+ * If the window is currently closed then:
+ *
+ * * The window is opened in the centre of the screen (at the supplied size)
+ * * Any toolbar editing session is stopped
+ * * The scroll position is set to the top of the window
+ *
+ * If the window is currently open then:
+ *
+ * * The window is brought to the top of the stack
+ *
+ * \param w the window to show
+ * \param toolbar the toolbar to consider
+ * \param width the window width if it is currently closed (or 0 to retain)
+ * \param height the window height if it is currently closed (or 0 to retain)
+ * \return true if the window was previously open
+ */
+bool ro_gui_dialog_open_top(wimp_w w, struct toolbar *toolbar,
+ int width, int height) {
+ os_error *error;
+ int screen_width, screen_height;
+ wimp_window_state state;
+ bool open;
+
+ state.w = w;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ ro_warn_user("WimpError", error->errmess);
+ return false;
+ }
+
+ /* if we're open we jump to the top of the stack, if not then we
+ * open in the centre of the screen. */
+ open = state.flags & wimp_WINDOW_OPEN;
+ if (!open) {
+ int dimension;
+ int scroll_width;
+ /* cancel any editing */
+ if (ro_toolbar_get_editing(toolbar))
+ ro_toolbar_toggle_edit(toolbar);
+
+ /* move to the centre */
+ ro_gui_screen_size(&screen_width, &screen_height);
+ dimension = ((width == 0) ?
+ (state.visible.x1 - state.visible.x0) : width);
+ scroll_width = ro_get_vscroll_width(w);
+ state.visible.x0 = (screen_width - (dimension + scroll_width)) / 2;
+ state.visible.x1 = state.visible.x0 + dimension;
+ dimension = ((height == 0) ?
+ (state.visible.y1 - state.visible.y0) : height);
+ state.visible.y0 = (screen_height - dimension) / 2;
+ state.visible.y1 = state.visible.y0 + dimension;
+ state.xscroll = 0;
+ state.yscroll = 0;
+ if (toolbar)
+ state.yscroll = ro_toolbar_height(toolbar);
+ }
+
+ /* open the window at the top of the stack */
+ state.next = wimp_TOP;
+ ro_gui_open_window_request(PTR_WIMP_OPEN(&state));
+ return open;
+}
+
+
+/**
+ * Open window at the location of the pointer.
+ */
+
+void ro_gui_dialog_open_at_pointer(wimp_w w)
+{
+ wimp_pointer ptr;
+ os_error *error;
+
+ /* get the pointer position */
+ error = xwimp_get_pointer_info(&ptr);
+ if (error) {
+ LOG("xwimp_get_pointer_info: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ ro_gui_dialog_open_xy(w, ptr.pos.x - 64, ptr.pos.y);
+}
+
+
+/**
+ * Open window at a specified location.
+ */
+
+void ro_gui_dialog_open_xy(wimp_w w, int x, int y)
+{
+ wimp_window_state state;
+ os_error *error;
+ int dx, dy;
+
+ /* move the window */
+ state.w = w;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+ dx = (state.visible.x1 - state.visible.x0);
+ dy = (state.visible.y1 - state.visible.y0);
+ state.visible.x0 = x;
+ state.visible.x1 = x + dx;
+ state.visible.y0 = y - dy;
+ state.visible.y1 = y;
+
+ /* if the window is already open, close it first so that it opens fully
+ * on screen */
+ error = xwimp_close_window(w);
+ if (error) {
+ LOG("xwimp_close_window: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ /* open the window at the top of the stack */
+ state.next = wimp_TOP;
+ ro_gui_open_window_request(PTR_WIMP_OPEN(&state));
+}
+
+
+/**
+ * Opens a window at the centre of either another window or the screen
+ *
+ * /param parent the parent window (NULL for centre of screen)
+ * /param child the child window
+ */
+void ro_gui_dialog_open_centre_parent(wimp_w parent, wimp_w child) {
+ os_error *error;
+ wimp_window_state state;
+ int mid_x, mid_y;
+ int dimension, scroll_width;
+
+ /* get the parent window state */
+ if (parent) {
+ state.w = parent;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+ scroll_width = ro_get_vscroll_width(parent);
+ mid_x = (state.visible.x0 + state.visible.x1 + scroll_width);
+ mid_y = (state.visible.y0 + state.visible.y1);
+ } else {
+ ro_gui_screen_size(&mid_x, &mid_y);
+ }
+ mid_x /= 2;
+ mid_y /= 2;
+
+ /* get the child window state */
+ state.w = child;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ /* move to the centre of the parent at the top of the stack */
+ dimension = state.visible.x1 - state.visible.x0;
+ scroll_width = ro_get_vscroll_width(history_window);
+ state.visible.x0 = mid_x - (dimension + scroll_width) / 2;
+ state.visible.x1 = state.visible.x0 + dimension;
+ dimension = state.visible.y1 - state.visible.y0;
+ state.visible.y0 = mid_y - dimension / 2;
+ state.visible.y1 = state.visible.y0 + dimension;
+ state.next = wimp_TOP;
+ ro_gui_open_window_request(PTR_WIMP_OPEN(&state));
+}
+
+
+/**
+ * Open a persistent dialog box relative to the pointer.
+ *
+ * \param parent the owning window (NULL for no owner)
+ * \param w the dialog window
+ * \param pointer open the window at the pointer (centre of the parent
+ * otherwise)
+ */
+
+void ro_gui_dialog_open_persistent(wimp_w parent, wimp_w w, bool pointer) {
+
+ if (pointer)
+ ro_gui_dialog_open_at_pointer(w);
+ else
+ ro_gui_dialog_open_centre_parent(parent, w);
+
+ /* todo: use wimp_event definitions rather than special cases */
+ if ((w == dialog_pageinfo) || (w == dialog_objinfo))
+ ro_gui_wimp_update_window_furniture(w, wimp_WINDOW_CLOSE_ICON,
+ wimp_WINDOW_CLOSE_ICON);
+ ro_gui_dialog_add_persistent(parent, w);
+ ro_gui_set_caret_first(w);
+}
+
+
+void ro_gui_dialog_add_persistent(wimp_w parent, wimp_w w) {
+ int i;
+
+ /* all persistant windows have a back icon */
+ ro_gui_wimp_update_window_furniture(w, wimp_WINDOW_BACK_ICON,
+ wimp_WINDOW_BACK_ICON);
+
+ /* Add a mapping
+ */
+ if ((parent == NULL) || (parent == wimp_ICON_BAR))
+ return;
+ for (i = 0; i < MAX_PERSISTENT; i++) {
+ if (persistent_dialog[i].dialog == NULL ||
+ persistent_dialog[i].dialog == w) {
+ persistent_dialog[i].dialog = w;
+ persistent_dialog[i].parent = parent;
+ return;
+ }
+ }
+ LOG("Unable to map persistent dialog to parent.");
+ return;
+}
+
+
+/**
+ * Close persistent dialogs associated with a window.
+ *
+ * \param parent the window to close children of
+ */
+
+void ro_gui_dialog_close_persistent(wimp_w parent) {
+ int i;
+ wimp_w w;
+
+ /* Check our mappings.
+ *
+ * The window handle is copied into w before proceeding, as
+ * ro_gui_dialog_close() will NULL persistent_dialog[i].dialog as
+ * part of the closing process. This would mean that the subsequent
+ * event dispatch would fail. (These events are logged to allow
+ * side effects to be investigated -- this code hasn't worked before).
+ */
+ for (i = 0; i < MAX_PERSISTENT; i++) {
+ if (persistent_dialog[i].parent == parent &&
+ persistent_dialog[i].dialog != NULL) {
+ w = persistent_dialog[i].dialog;
+ ro_gui_dialog_close(w);
+ if (ro_gui_wimp_event_close_window(w))
+ LOG("Persistent dialog close event: 0x%x", (unsigned)w);
+ persistent_dialog[i].parent = NULL;
+ persistent_dialog[i].dialog = NULL;
+ }
+ }
+}
+
+
+/**
+ * Save the current options.
+ */
+
+void ro_gui_save_options(void)
+{
+ nsoption_write("<NetSurf$ChoicesSave>", NULL, NULL);
+}
+
+bool ro_gui_dialog_zoom_apply(wimp_w w) {
+ unsigned int scale;
+ bool all;
+
+ scale = atoi(ro_gui_get_icon_string(w, ICON_ZOOM_VALUE));
+ all = ro_gui_get_icon_selected_state(w, ICON_ZOOM_FRAMES);
+ ro_gui_window_set_scale(ro_gui_current_zoom_gui, scale * 0.01);
+ return true;
+}
+
+
+/**
+ * Prepares the Scale view dialog.
+ */
+
+void ro_gui_dialog_prepare_zoom(struct gui_window *g)
+{
+ char scale_buffer[8];
+ sprintf(scale_buffer, "%.0f", browser_window_get_scale(g->bw) * 100);
+ ro_gui_set_icon_string(dialog_zoom, ICON_ZOOM_VALUE, scale_buffer, true);
+ ro_gui_set_icon_selected_state(dialog_zoom, ICON_ZOOM_FRAMES, true);
+ ro_gui_set_icon_shaded_state(dialog_zoom, ICON_ZOOM_FRAMES, true);
+ ro_gui_current_zoom_gui = g;
+ ro_gui_wimp_event_memorise(dialog_zoom);
+}
+
+/**
+ * Update the Scale View dialog to reflect the current window settings
+ *
+ * \param g the gui_window to update for
+ */
+void ro_gui_dialog_update_zoom(struct gui_window *g) {
+ if (g == ro_gui_current_zoom_gui)
+ ro_gui_dialog_prepare_zoom(g);
+}
+
+
+/**
+ * Create the Open URL dialogue, allocating storage for the URL field icon
+ * as we go.
+ *
+ * \return true on success; false on failure (although errors with
+ * the templates or memory allocation will exit via die()).
+ */
+
+static bool ro_gui_dialog_open_url_init(void)
+{
+ wimp_window *definition;
+ char *buffer;
+ os_error *error;
+
+ definition = ro_gui_dialog_load_template("open_url");
+
+ /* _load_template() should die on any error, so we trust its data. */
+
+ assert(definition != NULL);
+
+ /* Create the dialogue, with modifications. */
+
+ if ((definition->icons[ICON_OPENURL_URL].flags & wimp_ICON_INDIRECTED)
+ == 0) {
+ LOG("open_url URL icon not indirected");
+ xwimp_close_template();
+ die("Template");
+ }
+
+ buffer = malloc(RO_GUI_MAX_URL_SIZE);
+ if (buffer == NULL) {
+ xwimp_close_template();
+ die("NoMemory");
+ }
+
+ definition->icons[ICON_OPENURL_URL].data.indirected_text.text = buffer;
+ definition->icons[ICON_OPENURL_URL].data.indirected_text.size =
+ RO_GUI_MAX_URL_SIZE;
+ definition->sprite_area = gui_sprites;
+
+ error = xwimp_create_window(definition, &dialog_openurl);
+ if (error != NULL) {
+ LOG("xwimp_create_window: 0x%x: %s", error->errnum, error->errmess);
+ xwimp_close_template();
+ die(error->errmess);
+ }
+
+ free(definition);
+
+ ro_gui_wimp_event_register_menu_gright(dialog_openurl, ICON_OPENURL_URL,
+ ICON_OPENURL_MENU, ro_gui_url_suggest_menu);
+ ro_gui_wimp_event_register_cancel(dialog_openurl, ICON_OPENURL_CANCEL);
+ ro_gui_wimp_event_register_ok(dialog_openurl, ICON_OPENURL_OPEN,
+ ro_gui_dialog_openurl_apply);
+ ro_gui_wimp_event_register_menu_prepare(dialog_openurl,
+ ro_gui_dialog_open_url_menu_prepare);
+ ro_gui_wimp_event_set_help_prefix(dialog_openurl, "HelpOpenURL");
+
+ return true;
+}
+
+
+
+bool ro_gui_dialog_openurl_apply(wimp_w w) {
+ const char *urltxt;
+ char *url2;
+ nsurl *url;
+ nserror error;
+
+ urltxt = ro_gui_get_icon_string(w, ICON_OPENURL_URL);
+ url2 = strdup(urltxt); /** @todo why is this copied */
+ if (url2 == NULL) {
+ return false;
+ }
+
+ error = nsurl_create(url2, &url);
+ free(url2);
+ if (error == NSERROR_OK) {
+ error = browser_window_create(BW_CREATE_HISTORY,
+ url,
+ NULL,
+ NULL,
+ NULL);
+ nsurl_unref(url);
+ }
+ if (error != NSERROR_OK) {
+ ro_warn_user(messages_get_errorcode(error), 0);
+ return false;
+ }
+
+ return true;
+
+}
+
+
+/**
+ * Prepares the Open URL dialog.
+ */
+
+void ro_gui_dialog_prepare_open_url(void)
+{
+ ro_gui_set_icon_string(dialog_openurl, ICON_OPENURL_URL, "", true);
+ ro_gui_set_icon_shaded_state(dialog_openurl,
+ ICON_OPENURL_MENU, !ro_gui_url_suggest_prepare_menu());
+ ro_gui_wimp_event_memorise(dialog_openurl);
+}
+
+
+/**
+ * Callback to prepare menus in the Open URL dialog. At present, this
+ * only has to handle the URL Suggestion pop-up.
+ *
+ * \param w The window handle owning the menu.
+ * \param i The icon handle owning the menu.
+ * \param *menu The menu to be prepared.
+ * \param *pointer The associated mouse click event block, or NULL
+ * on an Adjust-click re-opening.
+ * \return true if the event was handled; false if not.
+ */
+
+bool ro_gui_dialog_open_url_menu_prepare(wimp_w w, wimp_i i, wimp_menu *menu,
+ wimp_pointer *pointer)
+{
+ if (menu != ro_gui_url_suggest_menu || i != ICON_OPENURL_MENU)
+ return false;
+
+ if (pointer != NULL)
+ return ro_gui_url_suggest_prepare_menu();
+
+ return true;
+}
diff --git a/frontends/riscos/dialog.h b/frontends/riscos/dialog.h
new file mode 100644
index 000000000..463048436
--- /dev/null
+++ b/frontends/riscos/dialog.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2005 Richard Wilson <info@tinct.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _NETSURF_RISCOS_DIALOG_H_
+#define _NETSURF_RISCOS_DIALOG_H_
+
+struct toolbar;
+struct gui_window;
+
+void ro_gui_dialog_init(void);
+wimp_w ro_gui_dialog_create(const char *template_name);
+wimp_window * ro_gui_dialog_load_template(const char *template_name);
+
+void ro_gui_dialog_open(wimp_w w);
+void ro_gui_dialog_close(wimp_w close);
+
+bool ro_gui_dialog_open_top(wimp_w w, struct toolbar *toolbar,
+ int width, int height);
+void ro_gui_dialog_open_at_pointer(wimp_w w);
+void ro_gui_dialog_open_xy(wimp_w, int x, int y);
+void ro_gui_dialog_open_centre_parent(wimp_w parent, wimp_w w);
+
+void ro_gui_dialog_open_persistent(wimp_w parent, wimp_w w, bool pointer);
+void ro_gui_dialog_add_persistent(wimp_w parent, wimp_w w);
+void ro_gui_dialog_close_persistent(wimp_w parent);
+
+
+
+
+void ro_gui_dialog_click(wimp_pointer *pointer);
+void ro_gui_dialog_prepare_zoom(struct gui_window *g);
+void ro_gui_dialog_update_zoom(struct gui_window *g);
+void ro_gui_dialog_prepare_open_url(void);
+void ro_gui_save_options(void);
+void ro_gui_dialog_open_config(void);
+void ro_gui_dialog_proxyauth_menu_selection(int item);
+void ro_gui_dialog_image_menu_selection(int item);
+void ro_gui_dialog_languages_menu_selection(const char *lang);
+void ro_gui_dialog_font_menu_selection(int item);
+#endif
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Cache/!Boot,feb b/frontends/riscos/distribution/!Boot/Resources/!Cache/!Boot,feb
new file mode 100644
index 000000000..485bd521d
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Cache/!Boot,feb
@@ -0,0 +1,17 @@
+If (("<Cache$AppDir>" = "") OR ("<Cache$ForceVars>" = "1")) Then Set Cache$AppDir <Obey$Dir>
+
+IconSprites <Cache$AppDir>.!Sprites
+
+| Find and set up resource paths
+WimpSlot -min 64k -max 64k
+Run <Cache$AppDir>.Resources.ResFind CacheApp
+If (("<Cache$Meta>" = "") OR ("<Cache$ForceVars>" = "1")) Then Set Cache$Meta CacheAppRes:!Meta
+
+| Work out where the cache directory should be -- use Choices$User if set or Default, otherwise.
+Set Cache$Suffix "<Choices$User>"
+If "<Cache$Suffix>" = "" Then Set Cache$Suffix "Default"
+If (("<Cache$Dir>" = "") OR ("<Cache$ForceVars>" = "1")) Then Set Cache$Dir "<Cache$AppDir>.Caches.<Cache$Suffix>"
+Unset Cache$Suffix
+
+| Ensure cache directory exists (sadly, unavoidable)
+CDir <Cache$Dir>
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Cache/!Help,feb b/frontends/riscos/distribution/!Boot/Resources/!Cache/!Help,feb
new file mode 100644
index 000000000..35eeeb31b
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Cache/!Help,feb
@@ -0,0 +1,2 @@
+If "<CacheAppRes$Path>" = "" Then Run <Cache$AppDir>.Resources.ResFind CacheApp
+Filer_Run CacheAppRes:Help \ No newline at end of file
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Cache/!Run,feb b/frontends/riscos/distribution/!Boot/Resources/!Cache/!Run,feb
new file mode 100644
index 000000000..8aead9733
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Cache/!Run,feb
@@ -0,0 +1,9 @@
+Set Cache$ForceVars 1
+Run <Obey$Dir>.!Boot
+Unset Cache$ForceVars
+
+RMEnsure SysLog 0.17 IfThere <SysLog$Dir>.!Run Then Run <SysLog$Dir>.!Run
+RMEnsure SysLog 0.17 Set Cache$SysLogMissing "True"
+
+Wimpslot -min 128k -max 128k
+Run <Cache$AppDir>.!RunImage
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Cache/!RunImage,ffb b/frontends/riscos/distribution/!Boot/Resources/!Cache/!RunImage,ffb
new file mode 100644
index 000000000..61752af99
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Cache/!RunImage,ffb
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Cache/!Sprites,ff9 b/frontends/riscos/distribution/!Boot/Resources/!Cache/!Sprites,ff9
new file mode 100644
index 000000000..b71a51cf3
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Cache/!Sprites,ff9
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Cache/!Sprites22,ff9 b/frontends/riscos/distribution/!Boot/Resources/!Cache/!Sprites22,ff9
new file mode 100644
index 000000000..e43f88c89
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Cache/!Sprites22,ff9
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Cache/Caches/Blank b/frontends/riscos/distribution/!Boot/Resources/!Cache/Caches/Blank
new file mode 100644
index 000000000..898dc5872
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Cache/Caches/Blank
@@ -0,0 +1 @@
+This is here just to stop the directory structure getting lost when unzipping. \ No newline at end of file
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/MultiError,ffb b/frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/MultiError,ffb
new file mode 100644
index 000000000..ec348b0e9
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/MultiError,ffb
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/ResFind,ffb b/frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/ResFind,ffb
new file mode 100644
index 000000000..7766cc928
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/ResFind,ffb
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/UK/!Meta b/frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/UK/!Meta
new file mode 100644
index 000000000..2de40bd7c
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/UK/!Meta
@@ -0,0 +1,9 @@
+# Meta file for Cache
+Help:<CacheAppRes$Dir>.Help
+Version:1.13
+Web:http://www.snowstone.org.uk/riscos/
+Title:Cache
+Publisher:Adam Richardson
+Description:Cache provides a central location for semi-permanent data on your system.
+Email:riscos@snowstone.org.uk
+
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/UK/Help b/frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/UK/Help
new file mode 100644
index 000000000..aad9bf0b1
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/UK/Help
@@ -0,0 +1,60 @@
+Cache
+-----
+
+Cache provides a shared location for cached data. This location can be
+used by application authors to store semi-permanent data. Cache can be
+placed anywhere on your computer where it will be "seen" by the Filer
+during start up. (For instance, the "Resources" directory inside !Boot.)
+
+Once "seen" it will set up a cache location, which can be shown by
+double-clicking on !Cache.
+
+
+Application Authors
+----------- -------
+
+Use Cache in a similar way to using Scrap. You *must not* assume that
+Cache is present on the user's system however, as Cache is not an
+official part of the system (like Scrap).
+
+To use Cache you should:
+ * Check for the presence of "<Cache$Dir>" before proceeding
+ * Read from and write data to "<Cache$Dir>.APPNAME" where APPNAME has
+ been allocated to you by the allocations service. See:
+ http://www.riscosopen.com/content/allocate
+ * If the APPNAME directory does not exist, you should create it.
+
+This version of Cache is published by Adam Richardson who can be
+contacted at riscos@snowstone.org.uk.
+
+The website for Cache is: http://www.snowstone.org.uk/riscos/
+
+
+Credits
+-------
+
+Cache is (c) Adam Richardson, 2007.
+Thanks to Rob Kendrick for the initial idea and input.
+
+
+License
+-------
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/UK/Messages b/frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/UK/Messages
new file mode 100644
index 000000000..366122292
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/UK/Messages
@@ -0,0 +1,8 @@
+# Messages for Cache
+
+multiuser:Multi-user system present.
+singleuser:No multi-user system present.
+location:Cache directory set to:
+opendir:Opening cache location...
+fatalerror:Cache has suffered a fatal error and has quit.
+
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/UK/Templates,fec b/frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/UK/Templates,fec
new file mode 100644
index 000000000..22f910ad9
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/UK/Templates,fec
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Boot,feb b/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Boot,feb
new file mode 100644
index 000000000..7c0c46241
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Boot,feb
@@ -0,0 +1,5 @@
+| Unicode Boot file
+|
+Set Unicode$Dir <Obey$Dir>
+SetMacro Unicode$Path <Unicode$Dir>.,Resources:$.Resources.Unicode.
+IconSprites Unicode:!Sprites
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Help b/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Help
new file mode 100644
index 000000000..8c0488185
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Help
@@ -0,0 +1 @@
+This application contains resources for Unicode support in applications.
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Run,feb b/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Run,feb
new file mode 100644
index 000000000..bd70e96ac
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Run,feb
@@ -0,0 +1,5 @@
+| Unicode Run file
+|
+Set Unicode$Dir <Obey$Dir>
+SetMacro Unicode$Path <Unicode$Dir>.,Resources:$.Resources.Unicode.
+IconSprites Unicode:!Sprites
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Sprites,ff9 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Sprites,ff9
new file mode 100644
index 000000000..3eb5b44b7
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Sprites,ff9
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Sprites11,ff9 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Sprites11,ff9
new file mode 100644
index 000000000..48986b41e
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Sprites11,ff9
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Sprites22,ff9 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Sprites22,ff9
new file mode 100644
index 000000000..63a6e6122
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Sprites22,ff9
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Acorn/Latin1 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Acorn/Latin1
new file mode 100644
index 000000000..bdf5d3b67
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Acorn/Latin1
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/CentEuro b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/CentEuro
new file mode 100644
index 000000000..5ab69ff2e
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/CentEuro
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Cyrillic b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Cyrillic
new file mode 100644
index 000000000..670fd6cdc
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Cyrillic
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Roman b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Roman
new file mode 100644
index 000000000..254579e2c
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Roman
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Ukrainian b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Ukrainian
new file mode 100644
index 000000000..a220587ba
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Ukrainian
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/BigFive b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/BigFive
new file mode 100644
index 000000000..c659cef19
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/BigFive
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/C0/40[ISO646] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/C0/40[ISO646]
new file mode 100644
index 000000000..cd92b5486
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/C0/40[ISO646]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/C1/43[IS6429] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/C1/43[IS6429]
new file mode 100644
index 000000000..74002a168
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/C1/43[IS6429]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/40[646old] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/40[646old]
new file mode 100644
index 000000000..00e2d1096
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/40[646old]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/41[646-GB] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/41[646-GB]
new file mode 100644
index 000000000..c293f93d6
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/41[646-GB]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/42[646IRV] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/42[646IRV]
new file mode 100644
index 000000000..e0b4bcadb
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/42[646IRV]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/43[FinSwe] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/43[FinSwe]
new file mode 100644
index 000000000..7d4646905
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/43[FinSwe]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/47[646-SE] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/47[646-SE]
new file mode 100644
index 000000000..a6b091a22
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/47[646-SE]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/48[646-SE] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/48[646-SE]
new file mode 100644
index 000000000..9bd24ab29
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/48[646-SE]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/49[JS201K] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/49[JS201K]
new file mode 100644
index 000000000..20ce8d498
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/49[JS201K]
@@ -0,0 +1 @@
+aÿbÿcÿdÿeÿfÿgÿhÿiÿjÿkÿlÿmÿnÿoÿpÿqÿrÿsÿtÿuÿvÿwÿxÿyÿzÿ{ÿ|ÿ}ÿ~ÿÿ€ÿÿ‚ÿƒÿ„ÿ…ÿ†ÿ‡ÿˆÿ‰ÿŠÿ‹ÿŒÿÿŽÿÿÿ‘ÿ’ÿ“ÿ”ÿ•ÿ–ÿ—ÿ˜ÿ™ÿšÿ›ÿœÿÿžÿŸÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ \ No newline at end of file
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4A[JS201R] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4A[JS201R]
new file mode 100644
index 000000000..21d2a479b
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4A[JS201R]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4B[646-DE] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4B[646-DE]
new file mode 100644
index 000000000..a2e284e1b
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4B[646-DE]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4C[646-PT] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4C[646-PT]
new file mode 100644
index 000000000..e076e2517
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4C[646-PT]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/54[GB1988] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/54[GB1988]
new file mode 100644
index 000000000..3b43719ce
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/54[GB1988]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/56[Teltxt] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/56[Teltxt]
new file mode 100644
index 000000000..73ce49e17
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/56[Teltxt]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/59[646-IT] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/59[646-IT]
new file mode 100644
index 000000000..f1ae81962
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/59[646-IT]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/5A[646-ES] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/5A[646-ES]
new file mode 100644
index 000000000..674fc2d70
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/5A[646-ES]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/60[646-NO] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/60[646-NO]
new file mode 100644
index 000000000..fc92892ee
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/60[646-NO]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/66[646-FR] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/66[646-FR]
new file mode 100644
index 000000000..8dd604679
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/66[646-FR]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/69[646-HU] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/69[646-HU]
new file mode 100644
index 000000000..65300b2c5
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/69[646-HU]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/6B[Arabic] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/6B[Arabic]
new file mode 100644
index 000000000..c47689914
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/6B[Arabic]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/6C[IS6937] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/6C[IS6937]
new file mode 100644
index 000000000..93453f5de
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/6C[IS6937]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/7A[SerbCr] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/7A[SerbCr]
new file mode 100644
index 000000000..9740e784e
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/7A[SerbCr]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/40[JS6226] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/40[JS6226]
new file mode 100644
index 000000000..a677dfc3d
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/40[JS6226]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/41[GB2312] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/41[GB2312]
new file mode 100644
index 000000000..679608ad2
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/41[GB2312]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/42[JIS208] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/42[JIS208]
new file mode 100644
index 000000000..532b1f4f3
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/42[JIS208]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/43[KS1001] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/43[KS1001]
new file mode 100644
index 000000000..36186c864
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/43[KS1001]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/44[JIS212] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/44[JIS212]
new file mode 100644
index 000000000..f5343a30e
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/44[JIS212]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/47[CNS1] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/47[CNS1]
new file mode 100644
index 000000000..da07f45d3
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/47[CNS1]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/48[CNS2] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/48[CNS2]
new file mode 100644
index 000000000..44ee24c91
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/48[CNS2]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/49[CNS3] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/49[CNS3]
new file mode 100644
index 000000000..a8464e5aa
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/49[CNS3]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4A[CNS4] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4A[CNS4]
new file mode 100644
index 000000000..a8f3e3270
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4A[CNS4]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4B[CNS5] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4B[CNS5]
new file mode 100644
index 000000000..535b0f4b5
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4B[CNS5]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4C[CNS6] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4C[CNS6]
new file mode 100644
index 000000000..7bfb2b1d4
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4C[CNS6]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4D[CNS7] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4D[CNS7]
new file mode 100644
index 000000000..be14c7279
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4D[CNS7]
@@ -0,0 +1,2 @@
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿö5ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿUVÿÿÿÿÿÿÿÿÿÿÿÿg6ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿaÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ’9ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿE:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÉ;ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿU=ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿè>ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¶?ÿÿÿÿÿÿ½?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖ@ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿqAÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ˜BÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÍEÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿöFÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿzGÿÿÿÿÿÿÿÿÿÿÿÿ¸GÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿHÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ/Iÿÿÿÿÿÿÿÿÿÿ1IÿÿÿÿÿÿÿÿÿÿÿÿÿÿœIÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿæIÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ8Kÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ:Lÿÿÿÿ±LÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGMÿÿQMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG7ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ8ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ£8ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ;ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ×qÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿš>ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÂ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÜ@ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ³Aÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿf†ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÙEÿÿÝEÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüFÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿIÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ=“ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¨IÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÊJÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿKÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÀLÿÿÿÿÿÿÿÿÿÿÿÿÊLÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ%MÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿJMÿÿSMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ6ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð;ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ>ÿÿÿÿÿÿÿÿÿÿÿÿ#>ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿCÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ]EÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿZFÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ…Gÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ Iÿÿÿÿÿÿÿÿÿÿÿÿ9Iÿÿÿÿÿÿ7IÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿkJÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÍJÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿMLÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ5ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ{6ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ8ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿõdÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ';ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÏ?ÿÿÿÿÿÿÍ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‚AÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿRBÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿQDÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿZEÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿeFÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¯HÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿAIÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ)Jÿÿÿÿÿÿÿÿÿÿÿÿÿÿ*Jÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ–JÿÿÿÿÿÿÿÿÿÿÿÿKÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ~6áXÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ§9ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ Cÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿé|ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿeEÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿdGÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ#HÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÙ•ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¹4ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿK<ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿñ@ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿgFÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‰Hÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ LÿÿÿÿÿÿLÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿmLÿÿpLÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíLÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ§4ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿgÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿZ>ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¯BÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿkEÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿcIÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€J„JJÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿñJÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGšÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¨4ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‹Aÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ+CÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿzEÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ FÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿmFÿÿÿÿÿÿÿÿÿÿGÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿjIlIÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ²KÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿLÿÿÿÿÿÿ-LÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿEMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
+Fÿÿÿÿÿÿÿÿ Fÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ.HÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿLÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ1Cÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¼K»KÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿLÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ6ÿÿÿÿÿÿÿÿÿÿr7ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿtvÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìKÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿyBÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ \ No newline at end of file
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/41[Lat1] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/41[Lat1]
new file mode 100644
index 000000000..97e6b1106
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/41[Lat1]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/42[Lat2] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/42[Lat2]
new file mode 100644
index 000000000..b753c40fe
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/42[Lat2]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/43[Lat3] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/43[Lat3]
new file mode 100644
index 000000000..88d477886
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/43[Lat3]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/44[Lat4] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/44[Lat4]
new file mode 100644
index 000000000..a40662d45
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/44[Lat4]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/46[Greek] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/46[Greek]
new file mode 100644
index 000000000..c42397388
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/46[Greek]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/47[Arabic] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/47[Arabic]
new file mode 100644
index 000000000..4507f467a
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/47[Arabic]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/48[Hebrew] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/48[Hebrew]
new file mode 100644
index 000000000..70f39cca6
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/48[Hebrew]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/4C[Cyrill] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/4C[Cyrill]
new file mode 100644
index 000000000..8ff0115e4
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/4C[Cyrill]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/4D[Lat5] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/4D[Lat5]
new file mode 100644
index 000000000..6381e607e
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/4D[Lat5]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/50[LatSup] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/50[LatSup]
new file mode 100644
index 000000000..a320c7fe8
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/50[LatSup]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/52[IS6937] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/52[IS6937]
new file mode 100644
index 000000000..dff6ccba4
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/52[IS6937]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/54[Thai] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/54[Thai]
new file mode 100644
index 000000000..d74377759
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/54[Thai]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/56[Lat6] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/56[Lat6]
new file mode 100644
index 000000000..4e3e4f313
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/56[Lat6]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/58[L6Sami] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/58[L6Sami]
new file mode 100644
index 000000000..4dfd9188c
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/58[L6Sami]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/59[Lat7] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/59[Lat7]
new file mode 100644
index 000000000..256a88e76
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/59[Lat7]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5C[Welsh] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5C[Welsh]
new file mode 100644
index 000000000..b5e00509f
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5C[Welsh]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5D[Sami] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5D[Sami]
new file mode 100644
index 000000000..15734c036
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5D[Sami]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5E[Hebrew] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5E[Hebrew]
new file mode 100644
index 000000000..a6593b071
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5E[Hebrew]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5F[Lat8] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5F[Lat8]
new file mode 100644
index 000000000..c15713e82
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5F[Lat8]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/62[Lat9] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/62[Lat9]
new file mode 100644
index 000000000..5bf449d58
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/62[Lat9]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/66[Lat10] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/66[Lat10]
new file mode 100644
index 000000000..e8ba925d3
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/66[Lat10]
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/KOI8-R b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/KOI8-R
new file mode 100644
index 000000000..8063cd4bc
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/KOI8-R
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1250 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1250
new file mode 100644
index 000000000..7a0d35ceb
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1250
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1251 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1251
new file mode 100644
index 000000000..3d6009cab
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1251
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1252 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1252
new file mode 100644
index 000000000..6d3bf293d
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1252
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1253 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1253
new file mode 100644
index 000000000..50a48be13
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1253
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1254 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1254
new file mode 100644
index 000000000..45ecfe907
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1254
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1256 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1256
new file mode 100644
index 000000000..7fc95a92f
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1256
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP866 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP866
new file mode 100644
index 000000000..cd214d24b
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP866
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP874 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP874
new file mode 100644
index 000000000..26a6fc8c3
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP874
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP932 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP932
new file mode 100644
index 000000000..2c0c111f9
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP932
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Files/Aliases b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Files/Aliases
new file mode 100644
index 000000000..8978ede4c
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Files/Aliases
@@ -0,0 +1,303 @@
+# > Unicode:Files.Aliases
+# Mapping of character set encoding names to their canonical form
+#
+# Lines starting with a '#' are comments, blank lines are ignored.
+#
+# Based on http://www.iana.org/assignments/character-sets and
+# http://www.iana.org/assignments/ianacharset-mib
+#
+# Canonical Form MIBenum Aliases...
+#
+US-ASCII 3 iso-ir-6 ANSI_X3.4-1986 ISO_646.irv:1991 ASCII ISO646-US ANSI_X3.4-1968 us IBM367 cp367 csASCII
+ISO-10646-UTF-1 27 csISO10646UTF1
+ISO_646.basic:1983 28 ref csISO646basic1983
+INVARIANT 29 csINVARIANT
+ISO_646.irv:1983 30 iso-ir-2 irv csISO2IntlRefVersion
+BS_4730 20 iso-ir-4 ISO646-GB gb uk csISO4UnitedKingdom
+NATS-SEFI 31 iso-ir-8-1 csNATSSEFI
+NATS-SEFI-ADD 32 iso-ir-8-2 csNATSSEFIADD
+NATS-DANO 33 iso-ir-9-1 csNATSDANO
+NATS-DANO-ADD 34 iso-ir-9-2 csNATSDANOADD
+SEN_850200_B 35 iso-ir-10 FI ISO646-FI ISO646-SE se csISO10Swedish
+SEN_850200_C 21 iso-ir-11 ISO646-SE2 se2 csISO11SwedishForNames
+KS_C_5601-1987 36 iso-ir-149 KS_C_5601-1989 KSC_5601 korean csKSC56011987
+ISO-2022-KR 37 csISO2022KR
+EUC-KR 38 csEUCKR EUCKR
+ISO-2022-JP 39 csISO2022JP
+ISO-2022-JP-2 40 csISO2022JP2
+ISO-2022-CN 104
+ISO-2022-CN-EXT 105
+JIS_C6220-1969-jp 41 JIS_C6220-1969 iso-ir-13 katakana x0201-7 csISO13JISC6220jp
+JIS_C6220-1969-ro 42 iso-ir-14 jp ISO646-JP csISO14JISC6220ro
+IT 22 iso-ir-15 ISO646-IT csISO15Italian
+PT 43 iso-ir-16 ISO646-PT csISO16Portuguese
+ES 23 iso-ir-17 ISO646-ES csISO17Spanish
+greek7-old 44 iso-ir-18 csISO18Greek7Old
+latin-greek 45 iso-ir-19 csISO19LatinGreek
+DIN_66003 24 iso-ir-21 de ISO646-DE csISO21German
+NF_Z_62-010_(1973) 46 iso-ir-25 ISO646-FR1 csISO25French
+Latin-greek-1 47 iso-ir-27 csISO27LatinGreek1
+ISO_5427 48 iso-ir-37 csISO5427Cyrillic
+JIS_C6226-1978 49 iso-ir-42 csISO42JISC62261978
+BS_viewdata 50 iso-ir-47 csISO47BSViewdata
+INIS 51 iso-ir-49 csISO49INIS
+INIS-8 52 iso-ir-50 csISO50INIS8
+INIS-cyrillic 53 iso-ir-51 csISO51INISCyrillic
+ISO_5427:1981 54 iso-ir-54 ISO5427Cyrillic1981
+ISO_5428:1980 55 iso-ir-55 csISO5428Greek
+GB_1988-80 56 iso-ir-57 cn ISO646-CN csISO57GB1988
+GB_2312-80 57 iso-ir-58 chinese csISO58GB231280
+NS_4551-1 25 iso-ir-60 ISO646-NO no csISO60DanishNorwegian csISO60Norwegian1
+NS_4551-2 58 ISO646-NO2 iso-ir-61 no2 csISO61Norwegian2
+NF_Z_62-010 26 iso-ir-69 ISO646-FR fr csISO69French
+videotex-suppl 59 iso-ir-70 csISO70VideotexSupp1
+PT2 60 iso-ir-84 ISO646-PT2 csISO84Portuguese2
+ES2 61 iso-ir-85 ISO646-ES2 csISO85Spanish2
+MSZ_7795.3 62 iso-ir-86 ISO646-HU hu csISO86Hungarian
+JIS_C6226-1983 63 iso-ir-87 x0208 JIS_X0208-1983 csISO87JISX0208
+greek7 64 iso-ir-88 csISO88Greek7
+ASMO_449 65 ISO_9036 arabic7 iso-ir-89 csISO89ASMO449
+iso-ir-90 66 csISO90
+JIS_C6229-1984-a 67 iso-ir-91 jp-ocr-a csISO91JISC62291984a
+JIS_C6229-1984-b 68 iso-ir-92 ISO646-JP-OCR-B jp-ocr-b csISO92JISC62991984b
+JIS_C6229-1984-b-add 69 iso-ir-93 jp-ocr-b-add csISO93JIS62291984badd
+JIS_C6229-1984-hand 70 iso-ir-94 jp-ocr-hand csISO94JIS62291984hand
+JIS_C6229-1984-hand-add 71 iso-ir-95 jp-ocr-hand-add csISO95JIS62291984handadd
+JIS_C6229-1984-kana 72 iso-ir-96 csISO96JISC62291984kana
+ISO_2033-1983 73 iso-ir-98 e13b csISO2033
+ANSI_X3.110-1983 74 iso-ir-99 CSA_T500-1983 NAPLPS csISO99NAPLPS
+ISO-8859-1 4 iso-ir-100 ISO_8859-1 ISO_8859-1:1987 latin1 l1 IBM819 CP819 csISOLatin1 8859_1 ISO8859-1
+ISO-8859-2 5 iso-ir-101 ISO_8859-2 ISO_8859-2:1987 latin2 l2 csISOLatin2 8859_2 ISO8859-2
+T.61-7bit 75 iso-ir-102 csISO102T617bit
+T.61-8bit 76 T.61 iso-ir-103 csISO103T618bit
+ISO-8859-3 6 iso-ir-109 ISO_8859-3 ISO_8859-3:1988 latin3 l3 csISOLatin3 8859_3 ISO8859-3
+ISO-8859-4 7 iso-ir-110 ISO_8859-4 ISO_8859-4:1988 latin4 l4 csISOLatin4 8859_4 ISO8859-4
+ECMA-cyrillic 77 iso-ir-111 KOI8-E csISO111ECMACyrillic
+CSA_Z243.4-1985-1 78 iso-ir-121 ISO646-CA csa7-1 ca csISO121Canadian1
+CSA_Z243.4-1985-2 79 iso-ir-122 ISO646-CA2 csa7-2 csISO122Canadian2
+CSA_Z243.4-1985-gr 80 iso-ir-123 csISO123CSAZ24341985gr
+ISO-8859-6 9 iso-ir-127 ISO_8859-6 ISO_8859-6:1987 ECMA-114 ASMO-708 arabic csISOLatinArabic
+ISO-8859-6-E 81 csISO88596E ISO_8859-6-E
+ISO-8859-6-I 82 csISO88596I ISO_8859-6-I
+ISO-8859-7 10 iso-ir-126 ISO_8859-7 ISO_8859-7:1987 ELOT_928 ECMA-118 greek greek8 csISOLatinGreek 8859_7 ISO8859-7
+T.101-G2 83 iso-ir-128 csISO128T101G2
+ISO-8859-8 11 iso-ir-138 ISO_8859-8 ISO_8859-8:1988 hebrew csISOLatinHebrew 8859_8 ISO8859-8
+ISO-8859-8-E 84 csISO88598E ISO_8859-8-E
+ISO-8859-8-I 85 csISO88598I ISO_8859-8-I
+CSN_369103 86 iso-ir-139 csISO139CSN369103
+JUS_I.B1.002 87 iso-ir-141 ISO646-YU js yu csISO141JUSIB1002
+ISO_6937-2-add 14 iso-ir-142 csISOTextComm
+IEC_P27-1 88 iso-ir-143 csISO143IECP271
+ISO-8859-5 8 iso-ir-144 ISO_8859-5 ISO_8859-5:1988 cyrillic csISOLatinCyrillic 8859_5 ISO8859-5
+JUS_I.B1.003-serb 89 iso-ir-146 serbian csISO146Serbian
+JUS_I.B1.003-mac 90 macedonian iso-ir-147 csISO147Macedonian
+ISO-8859-9 12 iso-ir-148 ISO_8859-9 ISO_8859-9:1989 latin5 l5 csISOLatin5 8859_9 ISO8859-9
+greek-ccitt 91 iso-ir-150 csISO150 csISO150GreekCCITT
+NC_NC00-10:81 92 cuba iso-ir-151 ISO646-CU csISO151Cuba
+ISO_6937-2-25 93 iso-ir-152 csISO6937Add
+GOST_19768-74 94 ST_SEV_358-88 iso-ir-153 csISO153GOST1976874
+ISO_8859-supp 95 iso-ir-154 latin1-2-5 csISO8859Supp
+ISO_10367-box 96 iso-ir-155 csISO10367Box
+ISO-8859-10 13 iso-ir-157 l6 ISO_8859-10:1992 csISOLatin6 latin6 8859_10 ISO8859-10
+latin-lap 97 lap iso-ir-158 csISO158Lap
+JIS_X0212-1990 98 x0212 iso-ir-159 csISO159JISX02121990
+DS_2089 99 DS2089 ISO646-DK dk csISO646Danish
+us-dk 100 csUSDK
+dk-us 101 csDKUS
+JIS_X0201 15 X0201 csHalfWidthKatakana
+KSC5636 102 ISO646-KR csKSC5636
+ISO-10646-UCS-2 1000 csUnicode UCS-2 UCS2
+ISO-10646-UCS-4 1001 csUCS4 UCS-4 UCS4
+DEC-MCS 2008 dec csDECMCS
+hp-roman8 2004 roman8 r8 csHPRoman8
+macintosh 2027 mac csMacintosh MACROMAN MAC-ROMAN X-MAC-ROMAN
+IBM037 2028 cp037 ebcdic-cp-us ebcdic-cp-ca ebcdic-cp-wt ebcdic-cp-nl csIBM037
+IBM038 2029 EBCDIC-INT cp038 csIBM038
+IBM273 2030 CP273 csIBM273
+IBM274 2031 EBCDIC-BE CP274 csIBM274
+IBM275 2032 EBCDIC-BR cp275 csIBM275
+IBM277 2033 EBCDIC-CP-DK EBCDIC-CP-NO csIBM277
+IBM278 2034 CP278 ebcdic-cp-fi ebcdic-cp-se csIBM278
+IBM280 2035 CP280 ebcdic-cp-it csIBM280
+IBM281 2036 EBCDIC-JP-E cp281 csIBM281
+IBM284 2037 CP284 ebcdic-cp-es csIBM284
+IBM285 2038 CP285 ebcdic-cp-gb csIBM285
+IBM290 2039 cp290 EBCDIC-JP-kana csIBM290
+IBM297 2040 cp297 ebcdic-cp-fr csIBM297
+IBM420 2041 cp420 ebcdic-cp-ar1 csIBM420
+IBM423 2042 cp423 ebcdic-cp-gr csIBM423
+IBM424 2043 cp424 ebcdic-cp-he csIBM424
+IBM437 2011 cp437 437 csPC8CodePage437
+IBM500 2044 CP500 ebcdic-cp-be ebcdic-cp-ch csIBM500
+IBM775 2087 cp775 csPC775Baltic
+IBM850 2009 cp850 850 csPC850Multilingual
+IBM851 2045 cp851 851 csIBM851
+IBM852 2010 cp852 852 csPCp852
+IBM855 2046 cp855 855 csIBM855
+IBM857 2047 cp857 857 csIBM857
+IBM860 2048 cp860 860 csIBM860
+IBM861 2049 cp861 861 cp-is csIBM861
+IBM862 2013 cp862 862 csPC862LatinHebrew
+IBM863 2050 cp863 863 csIBM863
+IBM864 2051 cp864 csIBM864
+IBM865 2052 cp865 865 csIBM865
+IBM866 2086 cp866 866 csIBM866
+IBM868 2053 CP868 cp-ar csIBM868
+IBM869 2054 cp869 869 cp-gr csIBM869
+IBM870 2055 CP870 ebcdic-cp-roece ebcdic-cp-yu csIBM870
+IBM871 2056 CP871 ebcdic-cp-is csIBM871
+IBM880 2057 cp880 EBCDIC-Cyrillic csIBM880
+IBM891 2058 cp891 csIBM891
+IBM903 2059 cp903 csIBM903
+IBM904 2060 cp904 904 csIBBM904
+IBM905 2061 CP905 ebcdic-cp-tr csIBM905
+IBM918 2062 CP918 ebcdic-cp-ar2 csIBM918
+IBM1026 2063 CP1026 csIBM1026
+EBCDIC-AT-DE 2064 csIBMEBCDICATDE
+EBCDIC-AT-DE-A 2065 csEBCDICATDEA
+EBCDIC-CA-FR 2066 csEBCDICCAFR
+EBCDIC-DK-NO 2067 csEBCDICDKNO
+EBCDIC-DK-NO-A 2068 csEBCDICDKNOA
+EBCDIC-FI-SE 2069 csEBCDICFISE
+EBCDIC-FI-SE-A 2070 csEBCDICFISEA
+EBCDIC-FR 2071 csEBCDICFR
+EBCDIC-IT 2072 csEBCDICIT
+EBCDIC-PT 2073 csEBCDICPT
+EBCDIC-ES 2074 csEBCDICES
+EBCDIC-ES-A 2075 csEBCDICESA
+EBCDIC-ES-S 2076 csEBCDICESS
+EBCDIC-UK 2077 csEBCDICUK
+EBCDIC-US 2078 csEBCDICUS
+UNKNOWN-8BIT 2079 csUnknown8BiT
+MNEMONIC 2080 csMnemonic
+MNEM 2081 csMnem
+VISCII 2082 csVISCII
+VIQR 2083 csVIQR
+KOI8-R 2084 csKOI8R
+KOI8-U 2088
+IBM00858 2089 CCSID00858 CP00858 PC-Multilingual-850+euro
+IBM00924 2090 CCSID00924 CP00924 ebcdic-Latin9--euro
+IBM01140 2091 CCSID01140 CP01140 ebcdic-us-37+euro
+IBM01141 2092 CCSID01141 CP01141 ebcdic-de-273+euro
+IBM01142 2093 CCSID01142 CP01142 ebcdic-dk-277+euro ebcdic-no-277+euro
+IBM01143 2094 CCSID01143 CP01143 ebcdic-fi-278+euro ebcdic-se-278+euro
+IBM01144 2095 CCSID01144 CP01144 ebcdic-it-280+euro
+IBM01145 2096 CCSID01145 CP01145 ebcdic-es-284+euro
+IBM01146 2097 CCSID01146 CP01146 ebcdic-gb-285+euro
+IBM01147 2098 CCSID01147 CP01147 ebcdic-fr-297+euro
+IBM01148 2099 CCSID01148 CP01148 ebcdic-international-500+euro
+IBM01149 2100 CCSID01149 CP01149 ebcdic-is-871+euro
+Big5-HKSCS 2101
+IBM1047 2102 IBM-1047
+PTCP154 2103 csPTCP154 PT154 CP154 Cyrillic-Asian
+Amiga-1251 2104 Ami1251 Amiga1251 Ami-1251
+KOI7-switched 2105
+UNICODE-1-1 1010 csUnicode11
+SCSU 1011
+UTF-7 1012
+UTF-16BE 1013
+UTF-16LE 1014
+UTF-16 1015
+CESU-8 1016 csCESU-8
+UTF-32 1017
+UTF-32BE 1018
+UTF-32LE 1019
+BOCU-1 1020 csBOCU-1
+UNICODE-1-1-UTF-7 103 csUnicode11UTF7
+UTF-8 106 UNICODE-1-1-UTF-8 UNICODE-2-0-UTF-8 utf8
+ISO-8859-13 109 8859_13 ISO8859-13
+ISO-8859-14 110 iso-ir-199 ISO_8859-14:1998 ISO_8859-14 latin8 iso-celtic l8 8859_14 ISO8859-14
+ISO-8859-15 111 ISO_8859-15 Latin-9 8859_15 ISO8859-15
+ISO-8859-16 112 iso-ir-226 ISO_8859-16:2001 ISO_8859-16 latin10 l10
+GBK 113 CP936 MS936 windows-936
+GB18030 114
+OSD_EBCDIC_DF04_15 115
+OSD_EBCDIC_DF03_IRV 116
+OSD_EBCDIC_DF04_1 117
+JIS_Encoding 16 csJISEncoding
+Shift_JIS 17 MS_Kanji csShiftJIS X-SJIS Shift-JIS
+EUC-JP 18 csEUCPkdFmtJapanese Extended_UNIX_Code_Packed_Format_for_Japanese EUCJP
+Extended_UNIX_Code_Fixed_Width_for_Japanese 19 csEUCFixWidJapanese
+ISO-10646-UCS-Basic 1002 csUnicodeASCII
+ISO-10646-Unicode-Latin1 1003 csUnicodeLatin1 ISO-10646
+ISO-Unicode-IBM-1261 1005 csUnicodeIBM1261
+ISO-Unicode-IBM-1268 1006 csUnicodeIBM1268
+ISO-Unicode-IBM-1276 1007 csUnicodeIBM1276
+ISO-Unicode-IBM-1264 1008 csUnicodeIBM1264
+ISO-Unicode-IBM-1265 1009 csUnicodeIBM1265
+ISO-8859-1-Windows-3.0-Latin-1 2000 csWindows30Latin1
+ISO-8859-1-Windows-3.1-Latin-1 2001 csWindows31Latin1
+ISO-8859-2-Windows-Latin-2 2002 csWindows31Latin2
+ISO-8859-9-Windows-Latin-5 2003 csWindows31Latin5
+Adobe-Standard-Encoding 2005 csAdobeStandardEncoding
+Ventura-US 2006 csVenturaUS
+Ventura-International 2007 csVenturaInternational
+PC8-Danish-Norwegian 2012 csPC8DanishNorwegian
+PC8-Turkish 2014 csPC8Turkish
+IBM-Symbols 2015 csIBMSymbols
+IBM-Thai 2016 csIBMThai
+HP-Legal 2017 csHPLegal
+HP-Pi-font 2018 csHPPiFont
+HP-Math8 2019 csHPMath8
+Adobe-Symbol-Encoding 2020 csHPPSMath
+HP-DeskTop 2021 csHPDesktop
+Ventura-Math 2022 csVenturaMath
+Microsoft-Publishing 2023 csMicrosoftPublishing
+Windows-31J 2024 csWindows31J
+GB2312 2025 csGB2312 EUC-CN EUCCN CN-GB
+Big5 2026 csBig5 BIG-FIVE BIG-5 CN-BIG5 BIG_FIVE x-x-big5
+windows-1250 2250 CP1250 MS-EE
+windows-1251 2251 CP1251 MS-CYRL
+windows-1252 2252 CP1252 MS-ANSI
+windows-1253 2253 CP1253 MS-GREEK
+windows-1254 2254 CP1254 MS-TURK
+windows-1255 2255
+windows-1256 2256 CP1256 MS-ARAB
+windows-1257 2257 CP1257 WINBALTRIM
+windows-1258 2258
+TIS-620 2259
+HZ-GB-2312 2085
+
+# Additional encodings not defined by IANA
+
+# Arbitrary allocations
+#CP737 3001
+#CP853 3002
+#CP856 3003
+CP874 3004 WINDOWS-874
+#CP922 3005
+#CP1046 3006
+#CP1124 3007
+#CP1125 3008 WINDOWS-1125
+#CP1129 3009
+#CP1133 3010 IBM-CP1133
+#CP1161 3011 IBM-1161 IBM1161 CSIBM1161
+#CP1162 3012 IBM-1162 IBM1162 CSIBM1162
+#CP1163 3013 IBM-1163 IBM1163 CSIBM1163
+#GEORGIAN-ACADEMY 3014
+#GEORGIAN-PS 3015
+#KOI8-RU 3016
+#KOI8-T 3017
+#MACARABIC 3018 X-MAC-ARABIC MAC-ARABIC
+#MACCROATIAN 3019 X-MAC-CROATIAN MAC-CROATIAN
+#MACGREEK 3020 X-MAC-GREEK MAC-GREEK
+#MACHEBREW 3021 X-MAC-HEBREW MAC-HEBREW
+#MACICELAND 3022 X-MAC-ICELAND MAC-ICELAND
+#MACROMANIA 3023 X-MAC-ROMANIA MAC-ROMANIA
+#MACTHAI 3024 X-MAC-THAI MAC-THAI
+#MACTURKISH 3025 X-MAC-TURKISH MAC-TURKISH
+#MULELAO-1 3026
+CP949 3027 WINDOWS-949
+
+# From Unicode Lib
+ISO-IR-182 4000
+ISO-IR-197 4002
+ISO-2022-JP-1 4008
+MACCYRILLIC 4009 X-MAC-CYRILLIC MAC-CYRILLIC
+MACUKRAINE 4010 X-MAC-UKRAINIAN MAC-UKRAINIAN
+MACCENTRALEUROPE 4011 X-MAC-CENTRALEURROMAN MAC-CENTRALEURROMAN
+JOHAB 4012
+ISO-8859-11 4014 iso-ir-166 ISO_8859-11 ISO8859-11 8859_11
+X-CURRENT 4999 X-SYSTEM
+X-ACORN-LATIN1 5001
+X-ACORN-FUZZY 5002
diff --git a/frontends/riscos/distribution/!System/310/Modules/CryptRand,ffa b/frontends/riscos/distribution/!System/310/Modules/CryptRand,ffa
new file mode 100644
index 000000000..f403843b3
--- /dev/null
+++ b/frontends/riscos/distribution/!System/310/Modules/CryptRand,ffa
Binary files differ
diff --git a/frontends/riscos/distribution/!System/310/Modules/Iconv,ffa b/frontends/riscos/distribution/!System/310/Modules/Iconv,ffa
new file mode 100644
index 000000000..8a9cc3adb
--- /dev/null
+++ b/frontends/riscos/distribution/!System/310/Modules/Iconv,ffa
Binary files differ
diff --git a/frontends/riscos/distribution/!System/310/Modules/Network/URI,ffa b/frontends/riscos/distribution/!System/310/Modules/Network/URI,ffa
new file mode 100644
index 000000000..431535e21
--- /dev/null
+++ b/frontends/riscos/distribution/!System/310/Modules/Network/URI,ffa
Binary files differ
diff --git a/frontends/riscos/distribution/!System/310/Modules/SharedULib,ffa b/frontends/riscos/distribution/!System/310/Modules/SharedULib,ffa
new file mode 100755
index 000000000..8dd0dd2c9
--- /dev/null
+++ b/frontends/riscos/distribution/!System/310/Modules/SharedULib,ffa
Binary files differ
diff --git a/frontends/riscos/distribution/!System/310/Modules/Tinct,ffa b/frontends/riscos/distribution/!System/310/Modules/Tinct,ffa
new file mode 100644
index 000000000..b8fda27b8
--- /dev/null
+++ b/frontends/riscos/distribution/!System/310/Modules/Tinct,ffa
Binary files differ
diff --git a/frontends/riscos/distribution/3rdParty/AcornURI/!ReadMe b/frontends/riscos/distribution/3rdParty/AcornURI/!ReadMe
new file mode 100644
index 000000000..4f4ca1e24
--- /dev/null
+++ b/frontends/riscos/distribution/3rdParty/AcornURI/!ReadMe
@@ -0,0 +1,34 @@
+AcornURI 1.04
+-------------
+
+Hi. This is a complete reimplementation of Acorn's URI module such that it
+works on Iyonix. This allows simple URI / URL launching from applications.
+Merge this !System with your own, then (re)launch your favourite browser to
+ensure it's running.
+
+This has a few advantages over the official offering: it's smaller,
+compatible with more browsers and more tolerant of errors.
+
+This is released under the terms of the LGPL, which is included in this
+archive as the file Copying. Previous versions of this module were released
+under the GPL, and are still available from sudden.recoil.org.
+
+Source is available from the same place you downloaded this archive, ie
+<http://sudden.recoil.org/others/acornuri/acornuri104src.zip>
+
+
+Changelog
+---------
+
+v1.04 20-May-06 Relicensed under the LGPL (rather than GPL)
+
+v1.03 11-May-04 Changed the order of things to try, so it now
+ always prefers browsers which are already loaded
+
+v1.02 19-Feb-04 Fixed claiming of URIs where I'd misread the spec
+ Added automatic fall-back to the ANT protocol
+ Removed some service calls to improve reliability
+
+--
+Christian Ludlam
+chris@recoil.org \ No newline at end of file
diff --git a/frontends/riscos/distribution/3rdParty/AcornURI/Copying b/frontends/riscos/distribution/3rdParty/AcornURI/Copying
new file mode 100644
index 000000000..5ab7695ab
--- /dev/null
+++ b/frontends/riscos/distribution/3rdParty/AcornURI/Copying
@@ -0,0 +1,504 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/frontends/riscos/distribution/3rdParty/CryptRand/Copyright b/frontends/riscos/distribution/3rdParty/CryptRand/Copyright
new file mode 100644
index 000000000..abb4a9b80
--- /dev/null
+++ b/frontends/riscos/distribution/3rdParty/CryptRand/Copyright
@@ -0,0 +1,46 @@
+CryptRandom
+
+Upstream sources were downloaded and built by
+the GCCSDK Autobuilder.
+
+For information on the autobuilder see the URL:
+
+http://www.riscos.info/index.php/GCCSDK#GCCSDK_Autobuilder
+
+The source used for this build can be found at
+
+http://www.riscos.info/packages/src/System
+
+Upstream source fetched by CVS with
+
+CVS root theom@chiark.greenend.org.uk:/u3/theom/cvs-pub
+Module cryptrandom
+Upstream source fetched using SVN from
+
+
+# For AOF builds needing another branch (if this is not defined AB_SVN is
+
+Copyright
+---------
+
+Copyright 2000-11 Theo Markettos <theo@markettos.org.uk>
+Portions copyright Simon Tatham, Gary S. Brown and Eric Young
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including without
+limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+SIMON TATHAM OR THEO MARKETTOS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
diff --git a/frontends/riscos/distribution/3rdParty/Iconv/ReadMe b/frontends/riscos/distribution/3rdParty/Iconv/ReadMe
new file mode 100644
index 000000000..907c2c7c8
--- /dev/null
+++ b/frontends/riscos/distribution/3rdParty/Iconv/ReadMe
@@ -0,0 +1,45 @@
+What is Iconv?
+==============
+
+Iconv is a module which provides character set conversion akin to that provided
+by the C iconv() function.
+
+Iconv Installation instructions
+===============================
+
+To install the Iconv module, simply use the System merge utility provided by
+Configure to merge the !System directory provided with the one on your system.
+
+Use the Boot merge facility in Configure to merge the provided !Boot directory
+with the one on your system. If there is no !Boot merge facility provided on
+your system, simply drag the !Boot directory over your existing boot structure.
+
+Further documentation can be found in the "doc" directory.
+
+Note for developers:
+~~~~~~~~~~~~~~~~~~~~
+The "stubs" directory contains source for a set of C stubs.
+See the ReadMe file in that directory for further information.
+
+Licence
+=======
+
+Iconv is Copyright © 2004-13 J-M Bell
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+ * The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/frontends/riscos/distribution/3rdParty/Iconv/doc/API b/frontends/riscos/distribution/3rdParty/Iconv/doc/API
new file mode 100644
index 000000000..13fa22fce
--- /dev/null
+++ b/frontends/riscos/distribution/3rdParty/Iconv/doc/API
@@ -0,0 +1,132 @@
+Iconv Module API
+================
+
+If using C, then you really should be using the libiconv stubs provided
+(or UnixLib, if appropriate). See the iconv.h header file for further
+documentation of these calls.
+
+Iconv_Open (&57540)
+-------------------
+
+ Create a conversion descriptor
+
+ On Entry: r0 -> string containing name of destination encoding (eg "UTF-8")
+ r1 -> string containing name of source encoding (eg "CP1252")
+
+ On Exit: r0 = conversion descriptor
+ All others preserved
+
+ Either encoding name may have a number of parameters appended to them.
+ Parameters are separated by a pair of forward-slashes ("//").
+ Currently defined parameters are:
+
+ Parameter: Destination: Source:
+
+ TRANSLIT Transliterate unrepresentable None
+ output.
+
+ The conversion descriptor is an opaque value. The user should not,
+ therefore, assume anything about its meaning, nor modify it in any way.
+ Doing so is guaranteed to result in undefined behaviour.
+
+
+Iconv_Iconv (&57541)
+--------------------
+
+ This SWI is deprecated and Iconv_Convert should be used instead.
+
+
+Iconv_Close (&57542)
+--------------------
+
+ Destroy a conversion descriptor
+
+ On Entry: r0 = conversion descriptor to destroy
+
+ On Exit: r0 = 0
+ All others preserved
+
+
+Iconv_Convert (&57543)
+---------------------
+
+ Convert a byte sequence to another encoding
+
+ On Entry: r0 = conversion descriptor returned by Iconv_Open
+ r1 -> input buffer (or NULL to reset encoding context)
+ r2 = length of buffer pointed to by r1
+ r3 -> output buffer
+ r4 = length of buffer pointed to by r3
+
+ On Exit: r0 = number of non-reversible conversions performed (always 0)
+ r1 -> updated input buffer pointer (after last input read)
+ r2 = number of bytes remaining in input buffer
+ r3 -> updated output buffer pointer (i.e. end of output)
+ r4 = number of free bytes in the output buffer
+ All others preserved
+
+ Note that all strings should be NUL-terminated so, if calling from BASIC,
+ some terminating character munging may be needed.
+
+
+Errors:
+
+Should an error occur, the SWI will return with V set and r0 -> error buffer.
+Note that only the error number will be filled in and may be one of:
+
+ ICONV_NOMEM (&81b900)
+ ICONV_INVAL (&81b901)
+ ICONV_2BIG (&81b902)
+ ICONV_ILSEQ (&81b903)
+
+These map directly to the corresponding C errno values.
+
+
+Iconv_CreateMenu (&57544)
+-------------------------
+
+ Create a menu data structure containing all available encodings.
+
+ On Entry: r0 = flags. All bits reserved, must be 0
+ r1 -> buffer, or 0 to read required length
+ r2 = length of buffer in r1
+ r3 -> currently selected encoding name, or 0 if none selected
+ r4 -> buffer for indirected data, or 0 to read length
+ r5 = length of buffer in r4
+
+ On Exit: r2 = required size of buffer in r1 if r1 = 0 on entry,
+ or length of data placed in buffer
+ r5 = required size of buffer in r4 if r4 = 0 on entry,
+ or length of data placed in buffer
+
+ Menu titles are direct form text buffers. Menu entries are indirect text.
+ Entry text is stored in the buffer pointed to by R4 on entry to this call.
+
+
+Iconv_DecodeMenu (&57545)
+-------------------------
+
+ Decode a selection in a menu generated by Iconv_CreateMenu.
+ Places the corresponding encoding name in the result buffer.
+
+ On Entry: r0 = flags. All bits reserved, must be 0
+ r1 -> menu definition
+ r2 -> menu selections, as per Wimp_Poll
+ r3 -> buffer for result or 0 to read required length
+ r4 = buffer length
+
+ On Exit: r4 = required size of buffer if r3 = 0 on entry,
+ or length of data placed in buffer (0 if no selected
+ encoding)
+
+ The menu selections block pointed to by r2 on entry should be based at
+ the root of the encodings menu structure (i.e. index 0 in the block
+ should correspond to the selection in the main encoding menu).
+
+ This call will update the selection status of the menu(s) appropriately.
+
+
+Example Code:
+=============
+
+Example code may be found in the IconvEg BASIC file.
diff --git a/frontends/riscos/distribution/3rdParty/Iconv/doc/ChangeLog b/frontends/riscos/distribution/3rdParty/Iconv/doc/ChangeLog
new file mode 100644
index 000000000..3a22a45fa
--- /dev/null
+++ b/frontends/riscos/distribution/3rdParty/Iconv/doc/ChangeLog
@@ -0,0 +1,114 @@
+Iconv Changelog
+===============
+
+0.01 10-Sep-2004
+----------------
+
+ - Initial version - unreleased.
+
+0.02 27-Sep-2004
+----------------
+
+ - Use allocated SWI & error chunks.
+ - Fix issues in 8bit encoding handling.
+ - First public release.
+
+0.03 22-Jan-2005
+----------------
+
+ - Add Iconv_Convert SWI with improved interface.
+ - Deprecate Iconv_Iconv SWI.
+ - Add encoding name alias handling.
+ - Bundle !Unicode resource.
+
+0.04 08-Apr-2005
+----------------
+
+ - Improve parameter checking.
+ - Fix potential memory leaks.
+ - Add encoding menu creation and selection handling.
+
+0.05 27-Jun-2005
+----------------
+
+ - Improve encoding alias support, using external data file.
+ - Add StubsG build for A9home users.
+
+0.06 05-Nov-2005
+----------------
+
+ - Modified menu creation API to store indirected text in a
+ user-provided buffer. This change is backwards incompatible.
+
+0.07 11-Feb-2006
+----------------
+
+ - Corrected output values for E2BIG errors.
+ - Fixed input pointer update after successful conversion.
+
+0.08 11-Mar-2007
+----------------
+
+ - Tightened up parameter checking in various places.
+ - Improve aliases hash function.
+ - Make 8bit write function's return values match encoding_write
+ with encoding_WRITE_STRICT set.
+ - Fix bug in 8bit writing which resulted in the remaining buffer
+ size being reduced even if nothing was written.
+ - Improve support for endian-specific Unicode variants.
+ - Work around issue in UnicodeLib where remaining buffer size is
+ reduced if an attempt is made to write an unrepresentable character.
+ - Add rudimentary //TRANSLIT support - simply replaces with '?' for now.
+ - Make UnicodeLib handle raw ISO-8859-{1,2,9,10,15} and not attempt
+ ISO-6937-2-25 shift sequences.
+ - Remove StubsG build as A9home now has a C99 capable C library.
+ - Overhaul documentation.
+
+0.09 20-Nov-2008
+----------------
+
+ - Restructured source tree into cross-platform and RO-specific parts.
+ - New build system to go with this.
+ - Fixes for compiling with GCC4.
+ - Introduce *Iconv command which performs command line conversion.
+ - Fixes/improvements to the handlers for:
+ + US-ASCII
+ + UTF-8
+ + ISO-8859-7
+ + ISO-8859-8
+ + ISO-8859-11
+ + Windows-1256
+ + MacRoman
+ + JIS X 0208
+ + JIS X 0212
+ + KS X 1001
+ + EUC-JP
+ + Any ISO-2022 based charset that uses a 94x94 table in GR
+ + Johab
+ + ShiftJIS
+ - Add support for ISO-8859-16 (Latin 10)
+ - Significantly improve detection and reporting of error conditions
+
+0.10 29-Nov-2008
+----------------
+
+ - Fixes to the *Iconv command parameter parsing
+ - Ensure *Iconv outputs all converted data when the input is invalid
+ - Fix handling of illegal UTF-8 byte sequences
+ - Fix handling of incomplete multibyte input sequences.
+
+0.11 04-Jan-2011
+----------------
+
+ - Detect missing mapping file when using 8bit codecs. This prevents spurious
+ memory exhaustion errors.
+ - Toolchain used to build 0.10 turns out to have produced broken code.
+ - Minor additions to the charset alias mapping file.
+
+0.12 20-Jan-2013
+---------------
+
+ - Master alias mapping file now lives in ROOL repository.
+ - Correct handling of trailing valid shift sequences. Previously would
+ erroneously report EINVAL, instead of silently accepting them.
+ - Add proper transliteration behaviour when requested using //TRANSLIT.
diff --git a/frontends/riscos/distribution/3rdParty/Iconv/doc/Uni-iconv b/frontends/riscos/distribution/3rdParty/Iconv/doc/Uni-iconv
new file mode 100644
index 000000000..caea2d0f1
--- /dev/null
+++ b/frontends/riscos/distribution/3rdParty/Iconv/doc/Uni-iconv
@@ -0,0 +1,204 @@
+Introduction:
+=============
+
+This file documents an approximate correlation between the data files
+provided in the !Unicode distribution and the encoding headers in GNU
+libiconv 1.9.1.
+
+Those with '?' in the iconv column either are not represented in iconv
+or I've missed the relevant header file ;)
+
+A number of encodings are present in the iconv distribution but not
+in !Unicode. These are documented at the end of this file.
+
+Changelog:
+==========
+
+v 0.01 (09-Sep-2004)
+~~~~~~~~~~~~~~~~~~~~
+Initial Incarnation
+
+v 0.02 (11-Sep-2004)
+~~~~~~~~~~~~~~~~~~~~
+Documented additional encodings supported by the Iconv module.
+Corrected list of !Unicode deficiencies.
+
+
+!Unicode->iconv:
+================
+
+Unicode: iconv: notes:
+
+Acorn.Latin1 riscos1.h
+
+Apple.CentEuro mac_centraleurope.h
+Apple.Cyrillic mac_cyrillic.h
+Apple.Roman mac_roman.h
+Apple.Ukrainian mac_ukraine.h
+
+BigFive big5.h
+
+ISO2022.C0.40[ISO646] ?
+
+ISO2022.C1.43[IS6429] ?
+
+ISO2022.G94.40[646old] iso646_cn.h
+ISO2022.G94.41[646-GB] ?
+ISO2022.G94.42[646IRV] ?
+ISO2022.G94.43[FinSwe] ?
+ISO2022.G94.47[646-SE] ?
+ISO2022.G94.48[646-SE] ?
+ISO2022.G94.49[JS201K] jisx0201.h top of JIS range
+ISO2022.G94.4A[JS201R] jisx0201.h iso646_jp.h bottom of JIS range
+ISO2022.G94.4B[646-DE] ?
+ISO2022.G94.4C[646-PT] ?
+ISO2022.G94.54[GB1988] ?
+ISO2022.G94.56[Teltxt] ?
+ISO2022.G94.59[646-IT] ?
+ISO2022.G94.5A[646-ES] ?
+ISO2022.G94.60[646-NO] ?
+ISO2022.G94.66[646-FR] ?
+ISO2022.G94.69[646-HU] ?
+ISO2022.G94.6B[Arabic] ?
+ISO2022.G94.6C[IS6397] ?
+ISO2022.G94.7A[SerbCr] ?
+
+ISO2022.G94x94.40[JS6226] ?
+ISO2022.G94x94.41[GB2312] gb2312.h
+ISO2022.G94x94.42[JIS208] jis0x208.h
+ISO2022.G94x94.43[KS1001] ksc5601.h
+ISO2022.G94x94.44[JIS212] jis0x212.h
+ISO2022.G94x94.47[CNS1] cns11643_1.h the tables differ
+ISO2022.G94x94.48[CNS2] cns11643_2.h
+ISO2022.G94x94.49[CNS3] cns11643_3.h
+ISO2022.G94x94.4A[CNS4] cns11643_4.h
+ISO2022.G94x94.4B[CNS5] cns11643_5.h
+ISO2022.G94x94.4C[CNS6] cns11643_6.h
+ISO2022.G94x94.4D[CNS7] cns11643_7.h
+
+ISO2022.G96.41[Lat1] iso8859_1.h
+ISO2022.G96.42[Lat2] iso8859_2.h
+ISO2022.G96.43[Lat3] iso8859_3.h
+ISO2022.G96.44[Lat4] iso8859_4.h
+ISO2022.G96.46[Greek] ?
+ISO2022.G96.47[Arabic] iso8859_6.h ISO-8859-6 ignored
+ISO2022.G96.48[Hebrew] ?
+ISO2022.G96.4C[Cyrill] ?
+ISO2022.G96.4D[Lat5] iso8859_5.h
+ISO2022.G96.50[LatSup] ?
+ISO2022.G96.52[IS6397] ?
+ISO2022.G96.54[Thai] tis620.h
+ISO2022.G96.56[Lat6] iso8859_6.h
+ISO2022.G96.58[L6Sami] ?
+ISO2022.G96.59[Lat7] iso8859_7.h
+ISO2022.G96.5C[Welsh] ?
+ISO2022.G96.5D[Sami] ?
+ISO2022.G96.5E[Hebrew] ?
+ISO2022.G96.5F[Lat8] iso8859_8.h
+ISO2022.G96.62[Lat9] iso8859_9.h
+
+KOI8-R koi8_r.h
+
+Microsoft.CP1250 cp1250.h
+Microsoft.CP1251 cp1251.h
+Microsoft.CP1252 cp1252.h
+Microsoft.CP1254 cp1254.h
+Microsoft.CP866 cp866.h
+Microsoft.CP932 cp932.h cp932ext.h
+
+iconv->!Unicode:
+================
+
+Iconv has the following encodings, which are not present in !Unicode.
+Providing a suitable data file for !Unicode is trivial. Whether UnicodeLib
+will then act upon the addition of these is unknown.
+This list is ordered as per libiconv's NOTES file.
+
+European & Semitic languages:
+
+ ISO-8859-16 (iso8859_16.h)
+ KOI8-{U,RU,T} (koi8_xx.h)
+ CP125{3,5,6,7} (cp125n.h)
+ CP850 (cp850.h)
+ CP862 (cp862.h)
+ Mac{Croatian,Romania,Greek,Turkish,Hebrew,Arabic} (mac_foo.h)
+
+Japanese:
+
+ None afaikt.
+
+Simplified Chinese:
+
+ GB18030 (gb18030.h, gb18030ext.h)
+ HZ-GB-2312 (hz.h)
+
+Traditional Chinese:
+
+ CP950 (cp950.h)
+ BIG5-HKSCS (big5hkscs.h)
+
+Korean:
+
+ CP949 (cp949.h)
+
+Armenian:
+
+ ARMSCII-8 (armscii_8.h)
+
+Georgian:
+
+ Georgian-Academy, Georgian-PS (georgian_academy.h, georgian_ps.h)
+
+Thai:
+
+ CP874 (cp874.h)
+ MacThai (mac_thai.h)
+
+Laotian:
+
+ MuleLao-1, CP1133 (mulelao.h, cp1133.h)
+
+Vietnamese:
+
+ VISCII, TCVN (viscii.h, tcvn.h)
+ CP1258 (cp1258.h)
+
+Unicode:
+
+ BE/LE variants of normal encodings. I assume UnicodeLib handles
+ these, but can't be sure.
+ C99 / JAVA - well, yes.
+
+
+Iconv Module:
+=============
+
+The iconv module is effectively a thin veneer around UnicodeLib. However,
+8bit encodings are implemented within the module rather than using the
+support in UnicodeLib. The rationale for this is simply that, although
+UnicodeLib will understand (and act upon - reportedly...) additions to
+the ISO2022 Unicode resource, other encodings are ignored. As the vast
+majority of outstanding encodings fall into this category, and the code
+is fairly simple, it made sense to implement it within the module.
+
+With use of the iconv module, the list of outstanding encodings is
+reduced to:
+
+ CP1255 (requires state-based transcoding)
+
+ GB18030 (not 8bit - reportedly a requirement of PRC)
+ HZ-GB-2312 (not 8bit - supported by IE4)
+
+ CP950 (not 8bit - a (MS) variant of Big5)
+ BIG5-HKSCS (not 8bit - again, a Big5 variant)
+
+ CP949 (not 8bit)
+
+ ARMSCII-8 (easily implemented, if required)
+
+ VISCII (easily implemented, if required)
+ CP1258, TCVN (requires state-based transcoding)
+
+Additionally, the rest of the CodePage encodings implemented in iconv
+but not listed above (due to omissions from the iconv documentation)
+are implemented by the iconv module.
diff --git a/frontends/riscos/distribution/3rdParty/SharedULib/Copyright b/frontends/riscos/distribution/3rdParty/SharedULib/Copyright
new file mode 100644
index 000000000..b6784ed06
--- /dev/null
+++ b/frontends/riscos/distribution/3rdParty/SharedULib/Copyright
@@ -0,0 +1,761 @@
+UnixLib Copyright
+-----------------
+
+UnixLib is Copyright (c) 1995-1999 Simon Callan, Nick Burrett,
+Nicholas Clark and Peter Burwood.
+
+These contributors have expressed "no interest" in any further licensing or
+copyright in regards to UnixLib.
+
+Other sections are (c) 1999-2006 Nick Burrett, John Tytgat, Peter Naulls,
+Peter Teichmann, Alex Waugh, Christian Ludlam, Theo Markettos, Graham Shaw,
+James Bursa and John-Mark Bell.
+
+In January 2005, permission was obtained from all relevant contributors
+by Peter Naulls to license all past and present contributions to UnixLib
+(where possible) under the revised BSD license. The license is included
+in the next section and is applicable to all code in UnixLib that does not
+have an explicit license in its source.
+
+Prior to 4th January 2005 and after May 2001, UnixLib contained code licensed
+under the GNU General Public License, and versions of UnixLib produced
+between these dates are subject to the provisions of the GPL. We realised
+that this might cause potential problems with the wider use of UnixLib in
+RISC OS, and along with the desire to clarify the overall licensing status of
+UnixLib, GPL code was removed from UnixLib and the above permission from all
+copyright holders allowed UnixLib contributions to be relicensed as per the
+revised BSD license. The GPL is therefore not included in this notice
+as it is no longer relevant to UnixLib.
+
+
+Practical notes on using UnixLib in your own programs:
+
+This is a plain English version of guidelines for use of UnixLib in
+your programs. It does not override any of the licenses included
+below, but is intended to state instances when it may be used in
+free and non-free software. Where there is contradiction or
+ambiguity in this wording, please refer to the specifics of the licence
+in question. These recommendations are based upon our understading
+of the GPL/LGPL and BSD licenses and are subject to change should
+our understanding of the topics improve.
+
+ - Because UnixLib contains code that is subject to the Lesser GNU
+ Public License, the LGPL is the overriding consideration when
+ linking UnixLib to programs (unless the program itself is GPL).
+
+ - You are free to use sections of UnixLib in your own programs
+ subject to the conditions of that code. If the entirety of
+ that code is under a BSD license, then you can generally use
+ that code as you see fit, and there is no further obligation
+ from you as long as the copyright notice remains. If you
+ use LGPL code in your program, then your program must also be
+ distributed under the LGPL (or GPL).
+
+ - If you use UnixLib in its intended original form - that is as a
+ supporting library for ported programs to RISC OS - then your program
+ is subject to the LGPL; or the GPL if the program is covered by that.
+ Note that you must make the source and any modifications available to for
+ both if requested. This is of course equally true if you write an original
+ GPL program using UnixLib. In most cases, no additional action is
+ required of you, especially since source is usually readibly available.
+
+ - If you use UnixLib for a non-free program - whether that's commercial or
+ otherwise, then you should carefully read section 6 of the LGPL. This
+ applies, because at the present time, there is no practical method of
+ dynamic linking on RISC OS. At such time that UnixLib is available as a
+ shared library, then programs dynamically linking to it will no longer be
+ subject to the LPGL as applied to UnixLib.
+
+ - Section 6 means that in practice, you must supply, or offer to
+ supply either source or object code for your program.
+ This is mainly to allow rebuilding of the executable program
+ with later or modified versions of UnixLib. You must of course
+ supply (or better, contribute to the GCCSDK project) any
+ modifications you make to UnixLib upon request.
+
+
+Recommended reading:
+
+Frequently Asked Questions about the GNU GPL
+http://www.fsf.org/licenses/gpl-faq.html (has some sections on LGPL)
+
+About the justifications for using LGPL
+http://www.fsf.org/licenses/why-not-lgpl.html
+
+
+
+===========================================================================
+
+ Copyright (c) 1995-2005 UnixLib Developers
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+===========================================================================
+
+Portions of UnixLib are copyright The Regents of the University of
+California.
+
+Portions of this library are copyright Sun Microsystems, Inc. The
+
+Portions of this library are derived from the GNU C Library and fall under
+the GNU Library General Public License.
+
+Portions of this library are copyright Henry Spencer.
+
+Portions of this library are copyright The Regents of the University of
+California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState
+Corporation and other parties.
+
+Portions of this library are copyright PostgreSQL Global Development Group.
+
+The licenses for the above are duplicated below.
+
+
+===========================================================================
+
+ Copyright (c) The Regents of the University of California.
+ All rights reserved.
+
+ This code is derived from software contributed to Berkeley by
+ Chris Torek.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement:
+ This product includes software developed by the University of
+ California, Berkeley and its contributors.
+ 4. Neither the name of the University nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+
+===========================================================================
+
+ Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+
+ Developed at SunPro, a Sun Microsystems, Inc. business.
+ Permission to use, copy, modify, and distribute this
+ software is freely granted, provided that this notice
+ is preserved.
+
+===========================================================================
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+===========================================================================
+
+Copyright (c) 1998, 1999 Henry Spencer. All rights reserved.
+
+Development of this software was funded, in part, by Cray Research Inc.,
+UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
+Corporation, none of whom are responsible for the results. The author
+thanks all of them.
+
+Redistribution and use in source and binary forms -- with or without
+modification -- are permitted for any purpose, provided that
+redistributions in source form retain this entire copyright notice and
+indicate the origin and nature of any modifications.
+
+I'd appreciate being given credit for this package in the documentation
+of software which uses it, but that is not a requirement.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+===========================================================================
+
+This software is copyrighted by the Regents of the University of
+California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState
+Corporation and other parties. The following terms apply to all files
+associated with the software unless explicitly disclaimed in
+individual files.
+
+The authors hereby grant permission to use, copy, modify, distribute,
+and license this software and its documentation for any purpose, provided
+that existing copyright notices are retained in all copies and that this
+notice is included verbatim in any distributions. No written agreement,
+license, or royalty fee is required for any of the authorized uses.
+Modifications to this software may be copyrighted by their authors
+and need not follow the licensing terms described here, provided that
+the new terms are clearly indicated on the first page of each file where
+they apply.
+
+IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
+FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
+DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
+IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
+NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+MODIFICATIONS.
+
+GOVERNMENT USE: If you are acquiring this software on behalf of the
+U.S. government, the Government shall have only "Restricted Rights"
+in the software and related documentation as defined in the Federal
+Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you
+are acquiring the software on behalf of the Department of Defense, the
+software shall be classified as "Commercial Computer Software" and the
+Government shall have only "Restricted Rights" as defined in Clause
+252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
+authors grant the U.S. Government and others acting in its behalf
+permission to use and distribute the software in accordance with the
+terms specified in this license.
+
+===========================================================================
+
+PostgreSQL Database Management System
+(formerly known as Postgres, then as Postgres95)
+
+Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
+
+Portions Copyright (c) 1994, The Regents of the University of California
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose, without fee, and without a written agreement
+is hereby granted, provided that the above copyright notice and this
+paragraph and the following two paragraphs appear in all copies.
+
+IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
+LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
+DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO
+PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
diff --git a/frontends/riscos/distribution/3rdParty/Tinct/!Help b/frontends/riscos/distribution/3rdParty/Tinct/!Help
new file mode 100644
index 000000000..2e27e354f
--- /dev/null
+++ b/frontends/riscos/distribution/3rdParty/Tinct/!Help
@@ -0,0 +1,304 @@
+Tinct
+=====
+This module provides the necessary functionality to display alpha-blended
+sprites both scaled and otherwise. It also provides functions for dithering,
+error diffusion and performing bi-linear filtering to improve their appearance.
+
+
+Technical information
+¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
+To ensure future compatibility, this module does not patch the OS in any way
+and works in a totally legal way. It also does not write to itself in any
+way, so is suitable for running from ROM.
+ Redirection to sprites is supported, although due to the overheads involved
+with caching the colour translation tables it is not recommended that this is
+done frequently. There are some exceptions to this, however, as redirecting to
+a 16bpp or 32bpp mode sprite does not require any translation tables, and
+redirecting to a sprite that has the same mode and palette as the previous
+destination that Tinct was used for causes a minimum overhead as the
+translation tables are checked and cached values are used if possible.
+
+Format of a sprite with 8-bit alpha channel
+¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨
+The sprite format used by Tinct differs from those used by RISC OS Select,
+and whilst facilities are supplied to convert sprites into the required format,
+no facilities are provided to manipulate them.
+ All sprites used by Tinct must be 32bpp, and cannot have a standard RISC OS
+mask specified. The basic format of the sprite is shown below, with the
+restrictions to the standard sprite format marked with an asterisk (*):
+
+ [+0] Offset to next sprite
+ [+4] Sprite name, up to 12 characters with trailing zeroes
+ [+16] Width in words - 1
+ [+20] Height in scan lines - 1
+ [+24] First bit used
+ [+28] Last bit used
+ [+32] Offset to sprite image
+ [+36] * Offset to sprite image (no mask allowed)
+ [+40] * Sprite type (must be 0x301680B5)
+
+Whereas for normal sprites the sprite image would be a series of colour words
+of the format RrGgBb00, alpha-blended sprites use the empty byte to specify
+the alpha value, ie RrGgBbAa.
+ The alpha values represent the blending level on a linear scale where 0x00
+represents that the source pixel is totally transparent and 0xff that it is
+totally opaque. It should be noted that as a standard 32bpp sprite (eg as
+created with !Paint) will have the alpha channel set to 0x00 by default no
+output will be visible when plotting as an alpha-blended sprite.
+
+Error handling
+¨¨¨¨¨¨¨¨¨¨¨¨¨¨
+If an incorrect sprite is attempted to be used, Tinct currently always returns
+error number 0x700 (SBadSpriteFile) rather than the specific cause of the
+problem (eg. BadDPI, BadMSFlags or BadPixelDepth) as OS_SpriteOp would do.
+There are several technical reasons for this behaviour, and future versions of
+Tinct may return more descriptive errors depending on the cause.
+
+
+SWIs provided
+¯¯¯¯¯¯¯¯¯¯¯¯¯
+Tinct provides four SWIs to plot sprites and one to convert sprites to their
+32bpp equivalent. All values supplied to Tinct must be in OS units, and the
+current OS clipping rectangle is used.
+ The sprite pointers provided are equivalent to calling OS_SpriteOp with
+bit 9 of the reason code set. To plot a sprite by name, the sprite should
+first be found by using OS_SpriteOp with reason code 0x18 and using the
+returned sprite address.
+
+Tinct_PlotAlpha (0x57240)
+¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨
+Plots an alpha-blended sprite at the specified coordinates.
+
+-> R2 Sprite pointer
+ R3 X coordinate
+ R4 Y coordinate
+ R7 Flag word
+
+
+Tinct_PlotScaledAlpha (0x57241)
+¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨
+Plots a scaled alpha-blended sprite at the specified coordinates.
+
+-> R2 Sprite pointer
+ R3 X coordinate
+ R4 Y coordinate
+ R5 Scaled sprite width
+ R6 Scaled sprite height
+ R7 Flag word
+
+
+Tinct_Plot (0x57242)
+¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨
+Plots a sprite at the specified coordinates with a constant 0xff value for
+the alpha channel, ie without a mask.
+
+-> R2 Sprite pointer
+ R3 X coordinate
+ R4 Y coordinate
+ R7 Flag word
+
+
+Tinct_PlotScaled (0x57243)
+¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨
+Plots a scaled sprite at the specified coordinates with a constant 0xff value
+for the alpha channel, ie without a mask.
+
+-> R2 Sprite pointer
+ R3 X coordinate
+ R4 Y coordinate
+ R5 Scaled sprite width
+ R6 Scaled sprite height
+ R7 Flag word
+
+
+Tinct_ConvertSprite (0x57244)
+¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨
+Converts a paletted sprite into its 32bpp equivalent. Sufficient memory must
+have previously been allocated for the sprite (44 + width * height * 4).
+ As sprites with 16bpp or 32bpp do not have palettes, conversion cannot be
+performed on these variants. All sprites must be supplied with a full palette,
+eg 8bpp must have 256 palette entries.
+
+-> R2 Source sprite pointer
+ R3 Destination sprite pointer
+
+
+Tinct_AvailableFeatures (0x57245)
+¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨
+Returns the features available to the caller by specifying bits in the flag
+word. The features available are unique for each mode, although the current
+version of Tinct supports the same subset of features for all modes.
+
+-> R0 Feature to test for, or 0 for all features
+<- R0 Features available
+
+
+Tinct_Compress (0x57246)
+¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨
+Compresses an image using a fast algorithm. Sufficient memory must have been
+previously allocated for the maximum possible compressed size. This value is
+equal to 28 + (width * height * 4) * 33 / 32.
+
+-> R0 Source sprite pointer
+ R2 Output data buffer
+ R3 Output bytes available
+ R7 Flag word
+<- R0 Size of compressed data
+
+
+Tinct_Decompress (0x57247)
+¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨
+Decompresses an image previously compressed. Sufficient memory must have been
+previously allocated for the decompressed data (44 + width * height * 4) where
+width and height are available at +0 and +4 of the compressed data respectively.
+
+-> R0 Input data buffer
+ R2 Output data buffer
+ R7 Flag word (currently 0)
+<- R0 Size of decompressed data
+
+
+Flag word (plotting)
+¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
+All the SWIs provided by Tinct for plotting use a common flag word to
+describe the manner in which the plot is performed. Each bit controls a
+particular characteristic of the plotting:
+
+ 0 Forcibly read the screen base (only use if hardware scrolling)
+ 1 Use bi-linear filtering when scaling sprites
+ 2 Dither colours in 16bpp and below
+ 3 Perform error diffusion if bit 2 clear, invert dither pattern if set
+ 4 Horizontally fill the current graphics window with the sprite
+ 5 Vertically fill the current graphics window with the sprite
+ 6 Forcibly read the palette (only use if changing palette outside of
+ the WIMP)
+ 7 Use OS_SpriteOp to perform final plotting (see note)
+ 8+ Reserved (must be 0) if bit 7 is clear, background colour to
+ blend the alpha channel to otherwise
+
+If a bit is set in the flag word that cannot be honoured by the current
+version of Tinct then it is ignored. Tinct_AvailableFeatures can be used
+to test in advance what flags will be honoured.
+
+Bi-linear filtering
+¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨
+Although bi-linear filtering is only relevant during scaled plotting, this
+situation occurs when the EigFactors of the mode are not equal. As such, an
+application should always set their preferred flags to ensure consistency. The
+case of XEig * 2 = YEig (rectangular pixel modes) for even height sprites is a
+special case and has optimised code implemented.
+ There is an upper limit to the size of sprite that can be bi-linear filtered.
+The checks that are currently made are:
+
+ scaled_width / sprite_width < 256
+ scaled_height / sprite_height < 256
+ scaled_width * max(sprite_height, scaled_height) < 32,768
+
+ It should be noted that as bi-linear filtering is performed as a pre-filter,
+it carries a sizable overhead. However, as all scaling calculations are
+performed during this filter, tiled plotting (bits 4 and 5) are affected by
+a smaller margin (in certain cases a speed gain can be achieved).
+ As bi-linear filtering is performed using a pre-filter, it can be used in
+association with OS_SpriteOp rendering.
+
+Error diffusion and dithering
+¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨
+If both error diffusion and dithering are enabled then the image is plotted
+using only dithering, but with the dither pattern inverted. This enables an
+application to provide the user with what appears to be a higher quality image
+by redrawing every frame with the flag toggled.
+ There is a significant speed difference between dithering and error diffusion,
+and Tinct does not support error diffusion in all colour depths. If error
+diffusion is requested, but cannot be performed by Tinct then dithering with
+an inverted pattern is used (as if bits 2 and 3 were set).
+ There is an upper limit to the size of sprite that Tinct can perform error
+diffusion on. This is currently set to a display width of 2047 pixels wide with
+an unlimited height. Any attempt to use a higher resolution will result in
+dithered rendering with an inverted pattern (ie bits 2 and 3 set).
+ As error diffusion and dithering are implemented during the plot cycle, it is
+not possible to use them in association with OS_SpriteOp rendering. However,
+the bits should be set as future versions of Tinct may respect them for users
+of RISC OS 3.1 where true colour sprites are not supported.
+
+Sprite filling
+¨¨¨¨¨¨¨¨¨¨¨¨¨¨
+If filling is specified, then the supplied co-ordinate is the offset of the
+pattern relative to (0, 0) used for the fill. For example, a 64x64 sprite that
+is plotted with bits 4 and 5 set and a position of (32, 16) would fill the
+current graphics window with multiple copies of the image stating with the
+first image plotted at (-32, -48).
+ The caller should not concern itself with the size of the image being tiled
+as small images are internally optimised where possible to maximise the
+plotting speed.
+
+Rendering using OS_SpriteOp
+¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨
+It can be useful to use Tinct to perform the rendering to using OS_SpriteOp.
+There are two general situations where this may be useful:
+
+ 1) To output to a printer driver
+ 2) To allow hardware acceleraton (such as a ViewFinder card)
+
+By using Tinct rather than a direct OS_SpriteOp call, it allows the caller to
+retain certain features Tinct provides (such as sprite filling and a limited
+version of the standard alpha blending) and allows the caller to have a common
+plotting interface.
+ When using this feature for alpha-blended sprites, the background colour
+specified in the top 24-bits of the flag word is used for blending with any
+pixels that are not transparent. This requires that Tinct requires a second
+copy of the sprite in memory to modify which may present a significant overhead
+in some situations. Plotting opaquely does not have any such overheads.
+ Using OS_SpriteOp rendering does not currently work on RISC OS 3.1 or earlier
+due to the lack of support for true colour sprites. Future versions of Tinct
+may remove this restriction.
+
+
+Flag word (compression)
+¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
+The flag word used by Tinct_Compress can be used to improve the compression
+ratio by performing pre-filtering on the data. The flags below relate only to
+compression and should not be passed to Tinct_Decompress.
+
+ 0 Image is opaque, remove the alpha channel prior to compression
+
+All unspecified bits are reserved for future expansion and as such should be
+set to 0.
+
+Compressed data format
+¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨
+Certain aspects of the compressed data format are guaranteed to remain constant,
+so may be used by applications.
+
+ +0 Sprite width
+ +4 Sprite height
+ +8 Sprite name (12 chars)
+ +20 Compression flags
+ +24 Number of bytes of data following
+
+The method of compression is not guaranteed to remain constant over future
+revisions of Tinct, but subsequent versions will decompress data compressed
+with previous versions.
+
+
+Contact details
+¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
+If you would like to report a problem relating to Tinct, provide feedback, or
+request a licence for a commercial product, please use the details below:
+
+Address: 5 Queens Close, East Markham, Newark, Nottinghamshire, NG22 0QY. UK
+E-mail: info@tinct.net
+Website: www.tinct.net
+
+
+Copyright and licence details
+¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
+Tinct is © copyright Richard Wilson, 2004.
+
+Distribution and usage
+¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨
+Unrestricted use of Tinct is hereby granted for any non-commercial product. Any
+use as part of a commercial product requires written consent from the author.
+No charge may be made relating to the distribution of this software, and this
+copyright information should be included in all copies of the software.
+ Modified versions of this program may not be distributed without the authors
+consent, nor may modified versions of the source code or relating files. \ No newline at end of file
diff --git a/frontends/riscos/distribution/LeesMij b/frontends/riscos/distribution/LeesMij
new file mode 100644
index 000000000..a0d3ff41f
--- /dev/null
+++ b/frontends/riscos/distribution/LeesMij
@@ -0,0 +1,73 @@
+NetSurf
+=======
+
+Dit is een ontwikkelversie van NetSurf, een webbrowser met open
+broncode.
+
+De nieuwste versie van NetSurf is verkrijgbaar via:
+
+ http://www.netsurf-browser.org/
+
+
+Installatie
+-----------
+
+De installatie gaat in drie stappen:
+
+ 1. Gebruik de samenvoegfaciliteit van !Boot (te openen via de
+ besturingssysteeminstellingen -> !Boot) om de meegeleverde
+ !Boot-map samen te voegen met die van het systeem.
+
+ Als het besturingssysteem geen !Boot-samenvoegfaciliteit
+ ondersteund, sleep dan de meegeleverde !Boot-map in de map
+ waarin de bestaande !Boot-structuur staat.
+
+ 2. Gebruik de samenvoegfaciliteit van !System (te openen via de
+ besturingssysteeminstellingen -> !System) om de meegeleverde
+ !System-map samen te voegen met die van het systeem.
+
+ 3. Sleep de !NetSurf-programmamap naar de gewenste map op de
+ harde schijf.
+
+Dubbelklik op het programma !NetSurf in de gekozen locatie om de
+NetSurf-browser te starten.
+
+
+Opmerking NetSurf vereist de WindowManager-module 3.80 of een
+ recentere versie. Deze is standaard aanwezig in RISC OS 4
+ of een recentere versie. Voor RISC OS 3-gebruikers zijn
+ er twee mogelijkheden om NetSurf te kunnen gebruiken:
+
+ - De 'Universal !Boot Sequence' van Acorn:
+ http://www.riscos.com/ftp_space/generic/uniboot/
+ - HardDisc4-schijfstructuur van RISC OS Open:
+ https://www.riscosopen.org/content/downloads/common/
+
+
+Opmerking RISC OS 3.1 of oudere versies worden niet ondersteund.
+
+
+Licenties
+---------
+
+NetSurf wordt geleverd onder de GPL, evenals verschillende andere
+licenties voor de verschillende componenten die het programma
+gebruikt. Bezoek in de NetSurf-browser het URL-adres 'about:licence'
+voor meer informatie.
+
+
+De meegeleverde !Boot- en !System-mappen bevatten items die door
+derden zijn geproduceerd. De bijbehorende licenties zijn meegeleverd
+in de map '3rdParty'.
+
+AcornURI
+ http://sudden.recoil.org/others/
+
+Iconv
+ http://www.netsurf-browser.org/iconv/
+
+SharedUnixLibrary
+ http://www.riscos.info/downloads/gccsdk/sharedunixlib/system.zip
+
+Tinct
+ http://www.tinct.net/tinct.asp
diff --git a/frontends/riscos/distribution/ReadMe b/frontends/riscos/distribution/ReadMe
new file mode 100644
index 000000000..eec39d6ab
--- /dev/null
+++ b/frontends/riscos/distribution/ReadMe
@@ -0,0 +1,61 @@
+NetSurf
+=======
+
+This is a development build of NetSurf, an open source web browser.
+
+The latest version of NetSurf is available from:
+
+ http://www.netsurf-browser.org/
+
+
+Installation
+------------
+
+Installation is a three step process:
+
+ 1. Use the Boot Merge facility provided by Configure to merge
+ the supplied !Boot directory with the one on your system.
+
+ If there is no !Boot merge facility on your system, simply
+ drag the supplied !Boot over your existing boot structure.
+
+ 2. Use the System Merge facility provided by Configure to merge
+ the supplied !System directory with the one on your system.
+
+ 3. Drag the !NetSurf application directory to a place on your
+ hard disc.
+
+Double click on !NetSurf in your chosen location to launch NetSurf.
+
+
+Note NetSurf requires WindowManager 3.80 or later. This comes
+ with RISC OS 4 and above. RISC OS 3 users should install
+ the Universal Boot Sequence from:
+ http://acorn.riscos.com/riscos/releases/UniBoot/
+
+Note RISC OS 3.1 and earlier are not supported.
+
+
+Licences
+--------
+
+NetSurf is provided under the GPL, as well as several other licences
+for different components it uses. Visit NetSurf's about:licence URL
+for details.
+
+
+The !Boot and !System directories contain items provided produced
+by third parties. Their licences are provided in the 3rd Party
+directory.
+
+AcornURI
+ http://sudden.recoil.org/others/
+
+Iconv
+ http://www.netsurf-browser.org/iconv/
+
+SharedUnixLibrary
+ http://www.riscos.info/downloads/gccsdk/sharedunixlib/system.zip
+
+Tinct
+ http://www.tinct.net/tinct.asp
diff --git a/frontends/riscos/download.c b/frontends/riscos/download.c
new file mode 100644
index 000000000..cddb449de
--- /dev/null
+++ b/frontends/riscos/download.c
@@ -0,0 +1,1629 @@
+/*
+ * Copyright 2004 James Bursa <bursa@users.sourceforge.net>
+ * Copyright 2003 Rob Jackson <jacko@xms.ms>
+ * Copyright 2005 Adrian Lees <adrianl@users.sourceforge.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * RISC OS download windows implementation.
+ *
+ * This file implements the interface given by desktop/gui_download.h
+ * for download windows. Each download window has an associated
+ * fetch. Downloads start by writing received data to a temporary
+ * file. At some point the user chooses a destination (by drag &
+ * drop), and the temporary file is then moved to the destination and
+ * the download continues until complete.
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <time.h>
+#include <curl/curl.h>
+#include <libwapcaplet/libwapcaplet.h>
+
+#include "oslib/mimemap.h"
+#include "oslib/osargs.h"
+#include "oslib/osfile.h"
+#include "oslib/osfind.h"
+#include "oslib/osfscontrol.h"
+#include "oslib/osgbpb.h"
+#include "oslib/wimp.h"
+#include "oslib/wimpspriteop.h"
+
+#include "utils/sys_time.h"
+#include "utils/nsoption.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/nsurl.h"
+#include "utils/utf8.h"
+#include "utils/utils.h"
+#include "utils/string.h"
+#include "utils/corestrings.h"
+#include "desktop/gui_download.h"
+#include "desktop/download.h"
+
+#include "riscos/gui.h"
+#include "riscos/dialog.h"
+#include "riscos/mouse.h"
+#include "riscos/save.h"
+#include "riscos/query.h"
+#include "riscos/wimp.h"
+#include "riscos/wimp_event.h"
+#include "riscos/ucstables.h"
+#include "riscos/filetype.h"
+
+#define ICON_DOWNLOAD_ICON 0
+#define ICON_DOWNLOAD_URL 1
+#define ICON_DOWNLOAD_PATH 2
+#define ICON_DOWNLOAD_DESTINATION 3
+#define ICON_DOWNLOAD_PROGRESS 5
+#define ICON_DOWNLOAD_STATUS 6
+
+#define RO_DOWNLOAD_MAX_PATH_LEN 255
+
+typedef enum
+{
+ QueryRsn_Quit,
+ QueryRsn_Abort,
+ QueryRsn_Overwrite
+} query_reason;
+
+
+/** Data for a download window. */
+struct gui_download_window {
+ /** Associated context, or 0 if the fetch has completed or aborted. */
+ download_context *ctx;
+ unsigned int received; /**< Amount of data received so far. */
+ unsigned int total_size; /**< Size of resource, or 0 if unknown. */
+
+ wimp_w window; /**< RISC OS window handle. */
+ bits file_type; /**< RISC OS file type. */
+
+ char url[256]; /**< Buffer for URL icon. */
+ char sprite_name[20]; /**< Buffer for sprite icon. */
+ char path[RO_DOWNLOAD_MAX_PATH_LEN]; /**< Buffer for pathname icon. */
+ char status[256]; /**< Buffer for status icon. */
+
+ /** User has chosen the destination, and it is being written. */
+ bool saved;
+ bool close_confirmed;
+ bool error; /**< Error occurred, aborted. */
+
+ /** RISC OS file handle, of temporary file when !saved, and of
+ * destination when saved. */
+ os_fw file;
+
+ query_id query;
+ query_reason query_rsn;
+
+ struct timeval start_time; /**< Time download started. */
+ struct timeval last_time; /**< Time status was last updated. */
+ unsigned int last_received; /**< Value of received at last_time. */
+ float average_rate; /**< Moving average download rate. */
+ unsigned int average_points; /**< Number of points in the average. */
+
+ bool send_dataload; /**< Should send DataLoad message when finished */
+ wimp_message save_message; /**< Copy of wimp DataSaveAck message */
+
+ struct gui_download_window *prev; /**< Previous in linked list. */
+ struct gui_download_window *next; /**< Next in linked list. */
+};
+
+
+/** List of all download windows. */
+static struct gui_download_window *download_window_list = 0;
+/** Download window with current save operation. */
+static struct gui_download_window *download_window_current = 0;
+
+/** Template for a download window. */
+static wimp_window *download_template;
+
+/** Width of progress bar at 100%. */
+static int download_progress_width;
+/** Coordinates of progress bar. */
+static int download_progress_x0;
+static int download_progress_y0;
+static int download_progress_y1;
+
+/** Current download directory. */
+static char *download_dir = NULL;
+static size_t download_dir_len;
+
+static void ro_gui_download_drag_end(wimp_dragged *drag, void *data);
+static const char *ro_gui_download_temp_name(struct gui_download_window *dw);
+static void ro_gui_download_update_status(struct gui_download_window *dw);
+static void ro_gui_download_update_status_wrapper(void *p);
+static void ro_gui_download_window_hide_caret(struct gui_download_window *dw);
+static char *ro_gui_download_canonicalise(const char *path);
+static bool ro_gui_download_check_space(struct gui_download_window *dw,
+ const char *dest_file, const char *orig_file);
+static os_error *ro_gui_download_move(struct gui_download_window *dw,
+ const char *dest_file, const char *src_file);
+static void ro_gui_download_remember_dir(const char *path);
+static bool ro_gui_download_save(struct gui_download_window *dw,
+ const char *file_name, bool force_overwrite);
+static void ro_gui_download_send_dataload(struct gui_download_window *dw);
+static void ro_gui_download_window_destroy_wrapper(void *p);
+static bool ro_gui_download_window_destroy(struct gui_download_window *dw, bool quit);
+static void ro_gui_download_close_confirmed(query_id, enum query_response res, void *p);
+static void ro_gui_download_close_cancelled(query_id, enum query_response res, void *p);
+static void ro_gui_download_overwrite_confirmed(query_id, enum query_response res, void *p);
+static void ro_gui_download_overwrite_cancelled(query_id, enum query_response res, void *p);
+
+static bool ro_gui_download_click(wimp_pointer *pointer);
+static bool ro_gui_download_keypress(wimp_key *key);
+static void ro_gui_download_close(wimp_w w);
+
+static const query_callback close_funcs =
+{
+ ro_gui_download_close_confirmed,
+ ro_gui_download_close_cancelled
+};
+
+static const query_callback overwrite_funcs =
+{
+ ro_gui_download_overwrite_confirmed,
+ ro_gui_download_overwrite_cancelled
+};
+
+
+/**
+ * Load the download window template.
+ */
+
+void ro_gui_download_init(void)
+{
+ download_template = ro_gui_dialog_load_template("download");
+ download_progress_width =
+ download_template->icons[ICON_DOWNLOAD_STATUS].extent.x1 -
+ download_template->icons[ICON_DOWNLOAD_STATUS].extent.x0;
+ download_progress_x0 =
+ download_template->icons[ICON_DOWNLOAD_PROGRESS].extent.x0;
+ download_progress_y0 =
+ download_template->icons[ICON_DOWNLOAD_PROGRESS].extent.y0;
+ download_progress_y1 =
+ download_template->icons[ICON_DOWNLOAD_PROGRESS].extent.y1;
+}
+
+
+/**
+ * Returns the pathname of a temporary file for this download.
+ *
+ * \param dw download window
+ * \return ptr to pathname
+ */
+
+const char *ro_gui_download_temp_name(struct gui_download_window *dw)
+{
+ static char temp_name[40];
+ snprintf(temp_name, sizeof temp_name, "<Wimp$ScrapDir>.ns%x",
+ (unsigned int) dw);
+ return temp_name;
+}
+
+/**
+ * Try and find the correct RISC OS filetype from a download context.
+ */
+static nserror download_ro_filetype(download_context *ctx, bits *ftype_out)
+{
+ nsurl *url = download_context_get_url(ctx);
+ bits ftype = 0;
+ lwc_string *scheme;
+
+ /* If the file is local try and read its filetype */
+ scheme = nsurl_get_component(url, NSURL_SCHEME);
+ if (scheme != NULL) {
+ bool filescheme;
+ if (lwc_string_isequal(scheme,
+ corestring_lwc_file,
+ &filescheme) != lwc_error_ok) {
+ filescheme = false;
+ }
+
+ if (filescheme) {
+ lwc_string *path = nsurl_get_component(url, NSURL_PATH);
+ if (path != NULL && lwc_string_length(path) != 0) {
+ char *raw_path;
+ raw_path = curl_unescape(lwc_string_data(path),
+ lwc_string_length(path));
+ if (raw_path != NULL) {
+ ftype = ro_filetype_from_unix_path(raw_path);
+ curl_free(raw_path);
+ }
+ }
+ }
+ }
+
+ /* If we still don't have a filetype (i.e. failed reading local
+ * one or fetching a remote object), then use the MIME type.
+ */
+ if (ftype == 0) {
+ /* convert MIME type to RISC OS file type */
+ os_error *error;
+ const char *mime_type;
+
+ mime_type = download_context_get_mime_type(ctx);
+ error = xmimemaptranslate_mime_type_to_filetype(mime_type, &ftype);
+ if (error) {
+ LOG("xmimemaptranslate_mime_type_to_filetype: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("MiscError", error->errmess);
+ ftype = 0xffd;
+ }
+ }
+
+ *ftype_out = ftype;
+ return NSERROR_OK;
+}
+
+/**
+ * Create and open a download progress window.
+ *
+ * \param ctx Download context
+ * \param gui The RISCOS gui window to download for.
+ * \return A new gui_download_window structure, or NULL on error and error
+ * reported
+ */
+
+static struct gui_download_window *
+gui_download_window_create(download_context *ctx, struct gui_window *gui)
+{
+ nsurl *url = download_context_get_url(ctx);
+ const char *temp_name;
+ char *filename = NULL;
+ struct gui_download_window *dw;
+ bool space_warning = false;
+ os_error *error;
+ char *local_path;
+ nserror err;
+ size_t i, last_dot;
+
+ dw = malloc(sizeof *dw);
+ if (!dw) {
+ ro_warn_user("NoMemory", 0);
+ return 0;
+ }
+
+ dw->ctx = ctx;
+ dw->saved = false;
+ dw->close_confirmed = false;
+ dw->error = false;
+ dw->query = QUERY_INVALID;
+ dw->received = 0;
+ dw->total_size = download_context_get_total_length(ctx);
+
+ /** @todo change this to take a reference to the nsurl and use
+ * that value directly rather than using a fixed buffer.
+ */
+ strncpy(dw->url, nsurl_access(url), sizeof dw->url);
+ dw->url[sizeof dw->url - 1] = 0;
+
+ dw->status[0] = 0;
+ gettimeofday(&dw->start_time, 0);
+ dw->last_time = dw->start_time;
+ dw->last_received = 0;
+ dw->file_type = 0;
+ dw->average_rate = 0;
+ dw->average_points = 0;
+
+ /* get filetype */
+ err = download_ro_filetype(ctx, &dw->file_type);
+ if (err != NSERROR_OK) {
+ ro_warn_user(messages_get_errorcode(err), 0);
+ free(dw);
+ return 0;
+ }
+
+ /* open temporary output file */
+ temp_name = ro_gui_download_temp_name(dw);
+ if (!ro_gui_download_check_space(dw, temp_name, NULL)) {
+ /* issue a warning but continue with the download because the
+ user can save it to another medium whilst it's downloading */
+ space_warning = true;
+ }
+ error = xosfind_openoutw(osfind_NO_PATH | osfind_ERROR_IF_DIR,
+ temp_name, 0, &dw->file);
+ if (error) {
+ LOG("xosfind_openoutw: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("SaveError", error->errmess);
+ free(dw);
+ return 0;
+ }
+
+ /* fill in download window icons */
+ download_template->icons[ICON_DOWNLOAD_URL].data.indirected_text.text =
+ dw->url;
+ download_template->icons[ICON_DOWNLOAD_URL].data.indirected_text.size =
+ sizeof dw->url;
+
+ download_template->icons[ICON_DOWNLOAD_STATUS].data.indirected_text.
+ text = dw->status;
+ download_template->icons[ICON_DOWNLOAD_STATUS].data.indirected_text.
+ size = sizeof dw->status;
+
+ sprintf(dw->sprite_name, "file_%.3x", dw->file_type);
+ if (!ro_gui_wimp_sprite_exists(dw->sprite_name))
+ strcpy(dw->sprite_name, "file_xxx");
+ download_template->icons[ICON_DOWNLOAD_ICON].data.indirected_sprite.id =
+ (osspriteop_id) dw->sprite_name;
+
+ /* Get a suitable path- and leafname for the download. */
+ temp_name = download_context_get_filename(dw->ctx);
+
+ if (temp_name == NULL)
+ temp_name = messages_get("SaveObject");
+
+ if (temp_name != NULL)
+ filename = strdup(temp_name);
+
+ if (filename == NULL) {
+ LOG("Failed to establish download filename.");
+ ro_warn_user("SaveError", error->errmess);
+ free(dw);
+ return 0;
+ }
+
+ for (i = 0, last_dot = (size_t) -1; filename[i] != '\0'; i++) {
+ const char c = filename[i];
+
+ if (c == '.') {
+ last_dot = i;
+ filename[i] = '/';
+ } else if (c <= ' ' || strchr(":*#$&@^%\\", c) != NULL)
+ filename[i] = '_';
+ }
+
+ if (nsoption_bool(strip_extensions) && last_dot != (size_t) -1)
+ filename[last_dot] = '\0';
+
+ if (download_dir != NULL && strlen(download_dir) > 0)
+ snprintf(dw->path, RO_DOWNLOAD_MAX_PATH_LEN, "%s.%s",
+ download_dir, filename);
+ else
+ snprintf(dw->path, RO_DOWNLOAD_MAX_PATH_LEN, "%s",
+ filename);
+
+ free(filename);
+
+ err = utf8_to_local_encoding(dw->path, 0, &local_path);
+ if (err != NSERROR_OK) {
+ /* badenc should never happen */
+ assert(err !=NSERROR_BAD_ENCODING);
+ LOG("utf8_to_local_encoding failed");
+ ro_warn_user("NoMemory", 0);
+ free(dw);
+ return 0;
+ }
+ else {
+ strncpy(dw->path, local_path, sizeof dw->path);
+ free(local_path);
+ }
+
+ download_template->icons[ICON_DOWNLOAD_PATH].data.indirected_text.text =
+ dw->path;
+ download_template->icons[ICON_DOWNLOAD_PATH].data.indirected_text.size =
+ sizeof dw->path;
+
+ download_template->icons[ICON_DOWNLOAD_DESTINATION].data.
+ indirected_text.text = dw->path;
+ download_template->icons[ICON_DOWNLOAD_DESTINATION].data.
+ indirected_text.size = sizeof dw->path;
+
+ download_template->icons[ICON_DOWNLOAD_DESTINATION].flags |=
+ wimp_ICON_DELETED;
+
+ /* create and open the download window */
+ error = xwimp_create_window(download_template, &dw->window);
+ if (error) {
+ LOG("xwimp_create_window: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ free(dw);
+ return 0;
+ }
+
+ dw->prev = 0;
+ dw->next = download_window_list;
+ if (download_window_list)
+ download_window_list->prev = dw;
+ download_window_list = dw;
+
+ ro_gui_download_update_status(dw);
+
+ ro_gui_dialog_open(dw->window);
+
+ ro_gui_wimp_event_set_user_data(dw->window, dw);
+ ro_gui_wimp_event_register_mouse_click(dw->window, ro_gui_download_click);
+ ro_gui_wimp_event_register_keypress(dw->window, ro_gui_download_keypress);
+ ro_gui_wimp_event_register_close_window(dw->window, ro_gui_download_close);
+
+ /* issue the warning now, so that it appears in front of the download
+ * window! */
+ if (space_warning)
+ ro_warn_user("DownloadWarn", messages_get("NoDiscSpace"));
+
+ return dw;
+}
+
+/**
+ * Handle failed downloads.
+ *
+ * \param dw download window
+ * \param error_msg error message
+ */
+
+static void gui_download_window_error(struct gui_download_window *dw,
+ const char *error_msg)
+{
+ os_error *error;
+
+ if (dw->ctx != NULL)
+ download_context_destroy(dw->ctx);
+ dw->ctx = NULL;
+ dw->error = true;
+
+ riscos_schedule(-1, ro_gui_download_update_status_wrapper, dw);
+
+ /* place error message in status icon in red */
+ strncpy(dw->status, error_msg, sizeof dw->status);
+ error = xwimp_set_icon_state(dw->window,
+ ICON_DOWNLOAD_STATUS,
+ wimp_COLOUR_RED << wimp_ICON_FG_COLOUR_SHIFT,
+ wimp_ICON_FG_COLOUR);
+ if (error) {
+ LOG("xwimp_set_icon_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+
+ /* grey out pathname icon */
+ error = xwimp_set_icon_state(dw->window, ICON_DOWNLOAD_PATH,
+ wimp_ICON_SHADED, 0);
+ if (error) {
+ LOG("xwimp_set_icon_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+
+ /* grey out file icon */
+ error = xwimp_set_icon_state(dw->window, ICON_DOWNLOAD_ICON,
+ wimp_ICON_SHADED, wimp_ICON_SHADED);
+ if (error) {
+ LOG("xwimp_set_icon_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+
+ ro_gui_download_window_hide_caret(dw);
+}
+
+/**
+ * Handle received download data.
+ *
+ * \param dw download window
+ * \param data pointer to block of data received
+ * \param size size of data
+ * \return NSERROR_OK on success, appropriate error otherwise
+ */
+
+static nserror gui_download_window_data(struct gui_download_window *dw,
+ const char *data, unsigned int size)
+{
+ while (true) {
+ const char *msg;
+ int unwritten;
+ os_error *error;
+
+ error = xosgbpb_writew(dw->file, (const byte *) data, size,
+ &unwritten);
+ if (error) {
+ LOG("xosgbpb_writew: 0x%x: %s", error->errnum, error->errmess);
+ msg = error->errmess;
+
+ } else if (unwritten) {
+ LOG("xosgbpb_writew: unwritten %i", unwritten);
+ msg = messages_get("Unwritten");
+ }
+ else {
+ dw->received += size;
+ return NSERROR_OK;
+ }
+
+ ro_warn_user("SaveError", msg);
+
+ if (dw->saved) {
+ /* try to continue with the temporary file */
+ const char *temp_name = ro_gui_download_temp_name(dw);
+
+ error = ro_gui_download_move(dw, temp_name, dw->path);
+ if (!error) {
+
+ /* re-allow saving */
+ dw->saved = false;
+
+ error = xwimp_set_icon_state(dw->window, ICON_DOWNLOAD_ICON,
+ wimp_ICON_SHADED, 0);
+ if (error) {
+ LOG("xwimp_set_icon_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+
+ error = xwimp_set_icon_state(dw->window, ICON_DOWNLOAD_DESTINATION,
+ wimp_ICON_DELETED, wimp_ICON_DELETED);
+ if (error) {
+ LOG("xwimp_set_icon_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+ error = xwimp_set_icon_state(dw->window,
+ ICON_DOWNLOAD_PATH, wimp_ICON_DELETED, 0);
+ if (error) {
+ LOG("xwimp_set_icon_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+
+ continue;
+ }
+ }
+
+ /* give up then */
+ assert(dw->ctx);
+ download_context_abort(dw->ctx);
+ gui_download_window_error(dw, msg);
+
+ return NSERROR_SAVE_FAILED;
+ }
+}
+
+
+/**
+ * Update the status text and progress bar.
+ *
+ * \param dw download window
+ */
+
+void ro_gui_download_update_status(struct gui_download_window *dw)
+{
+ char *total_size;
+ char *speed;
+ char time[20] = "?";
+ struct timeval t;
+ float dt;
+ unsigned int left;
+ float rate;
+ os_error *error;
+ int width;
+ char *local_status;
+ nserror err;
+
+ gettimeofday(&t, 0);
+ dt = (t.tv_sec + 0.000001 * t.tv_usec) - (dw->last_time.tv_sec +
+ 0.000001 * dw->last_time.tv_usec);
+ if (dt == 0)
+ dt = 0.001;
+
+ total_size = human_friendly_bytesize(max(dw->received, dw->total_size));
+
+ if (dw->ctx) {
+ char *received;
+ rate = (dw->received - dw->last_received) / dt;
+ received = human_friendly_bytesize(dw->received);
+ /* A simple 'modified moving average' download rate calculation
+ * to smooth out rate fluctuations: chosen for simplicity.
+ */
+ dw->average_points++;
+ dw->average_rate =
+ ((dw->average_points - 1) *
+ dw->average_rate + rate) /
+ dw->average_points;
+ speed = human_friendly_bytesize(dw->average_rate);
+ if (dw->total_size) {
+ float f;
+
+ if (dw->average_rate > 0) {
+ left = (dw->total_size - dw->received) /
+ dw->average_rate;
+ sprintf(time, "%u:%.2u", left / 60, left % 60);
+ }
+
+ /* convert to local encoding */
+ err = utf8_to_local_encoding(
+ messages_get("Download"), 0, &local_status);
+ if (err != NSERROR_OK) {
+ /* badenc should never happen */
+ assert(err != NSERROR_BAD_ENCODING);
+ /* hide nomem error */
+ snprintf(dw->status, sizeof dw->status,
+ messages_get("Download"),
+ received, total_size, speed, time);
+ }
+ else {
+ snprintf(dw->status, sizeof dw->status,
+ local_status,
+ received, total_size, speed, time);
+ free(local_status);
+ }
+
+ f = (float) dw->received / (float) dw->total_size;
+ width = download_progress_width * f;
+ } else {
+ left = t.tv_sec - dw->start_time.tv_sec;
+ sprintf(time, "%u:%.2u", left / 60, left % 60);
+
+ err = utf8_to_local_encoding(
+ messages_get("DownloadU"), 0, &local_status);
+ if (err != NSERROR_OK) {
+ /* badenc should never happen */
+ assert(err != NSERROR_BAD_ENCODING);
+ /* hide nomem error */
+ snprintf(dw->status, sizeof dw->status,
+ messages_get("DownloadU"),
+ received, speed, time);
+ }
+ else {
+ snprintf(dw->status, sizeof dw->status,
+ local_status,
+ received, speed, time);
+ free(local_status);
+ }
+
+ /* length unknown, stay at 0 til finished */
+ width = 0;
+ }
+ } else {
+ left = dw->last_time.tv_sec - dw->start_time.tv_sec;
+ if (left == 0)
+ left = 1;
+ rate = (float) dw->received / (float) left;
+ sprintf(time, "%u:%.2u", left / 60, left % 60);
+ speed = human_friendly_bytesize(rate);
+
+ err = utf8_to_local_encoding(messages_get("Downloaded"), 0,
+ &local_status);
+ if (err != NSERROR_OK) {
+ /* badenc should never happen */
+ assert(err != NSERROR_BAD_ENCODING);
+ /* hide nomem error */
+ snprintf(dw->status, sizeof dw->status,
+ messages_get("Downloaded"),
+ total_size, speed, time);
+ }
+ else {
+ snprintf(dw->status, sizeof dw->status, local_status,
+ total_size, speed, time);
+ free(local_status);
+ }
+
+ /* all done */
+ width = download_progress_width;
+ }
+
+ dw->last_time = t;
+ dw->last_received = dw->received;
+
+ error = xwimp_resize_icon(dw->window, ICON_DOWNLOAD_PROGRESS,
+ download_progress_x0,
+ download_progress_y0,
+ download_progress_x0 + width,
+ download_progress_y1);
+ if (error) {
+ LOG("xwimp_resize_icon: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+
+ error = xwimp_set_icon_state(dw->window, ICON_DOWNLOAD_STATUS, 0, 0);
+ if (error) {
+ LOG("xwimp_set_icon_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+
+ if (dw->ctx) {
+ riscos_schedule(1000, ro_gui_download_update_status_wrapper, dw);
+ } else {
+ riscos_schedule(-1, ro_gui_download_update_status_wrapper, dw);
+ }
+}
+
+
+/**
+ * Wrapper for ro_gui_download_update_status(), suitable for riscos_schedule().
+ */
+
+void ro_gui_download_update_status_wrapper(void *p)
+{
+ ro_gui_download_update_status((struct gui_download_window *) p);
+}
+
+
+
+/**
+ * Hide the caret but preserve input focus.
+ *
+ * \param dw download window
+ */
+
+void ro_gui_download_window_hide_caret(struct gui_download_window *dw)
+{
+ wimp_caret caret;
+ os_error *error;
+
+ error = xwimp_get_caret_position(&caret);
+ if (error) {
+ LOG("xwimp_get_caret_position: 0x%x : %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+ else if (caret.w == dw->window) {
+ error = xwimp_set_caret_position(dw->window, (wimp_i)-1, 0, 0, 1 << 25, -1);
+ if (error) {
+ LOG("xwimp_get_caret_position: 0x%x : %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+ }
+}
+
+
+
+
+/**
+ * Handle completed downloads.
+ *
+ * \param dw download window
+ */
+
+static void gui_download_window_done(struct gui_download_window *dw)
+{
+ os_error *error;
+
+ if (dw->ctx != NULL)
+ download_context_destroy(dw->ctx);
+ dw->ctx = NULL;
+ ro_gui_download_update_status(dw);
+
+ error = xosfind_closew(dw->file);
+ if (error) {
+ LOG("xosfind_closew: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("SaveError", error->errmess);
+ }
+ dw->file = 0;
+
+ if (dw->saved) {
+ error = xosfile_set_type(dw->path,
+ dw->file_type);
+ if (error) {
+ LOG("xosfile_set_type: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("SaveError", error->errmess);
+ }
+
+ if (dw->send_dataload) {
+ ro_gui_download_send_dataload(dw);
+ }
+
+ riscos_schedule(2000, ro_gui_download_window_destroy_wrapper, dw);
+ }
+}
+
+
+/**
+ * Handle Mouse_Click events in a download window.
+ *
+ * \param pointer block returned by Wimp_Poll
+ */
+
+bool ro_gui_download_click(wimp_pointer *pointer)
+{
+ struct gui_download_window *dw;
+
+ dw = (struct gui_download_window *)ro_gui_wimp_event_get_user_data(pointer->w);
+ if ((pointer->buttons & (wimp_DRAG_SELECT | wimp_DRAG_ADJUST)) &&
+ pointer->i == ICON_DOWNLOAD_ICON &&
+ !dw->error && !dw->saved) {
+ const char *sprite = ro_gui_get_icon_string(pointer->w, pointer->i);
+ int x = pointer->pos.x, y = pointer->pos.y;
+ wimp_window_state wstate;
+ wimp_icon_state istate;
+ /* start the drag from the icon's exact location, rather than the pointer */
+ istate.w = wstate.w = pointer->w;
+ istate.i = pointer->i;
+ if (!xwimp_get_window_state(&wstate) && !xwimp_get_icon_state(&istate)) {
+ x = (istate.icon.extent.x1 + istate.icon.extent.x0)/2 +
+ wstate.visible.x0 - wstate.xscroll;
+ y = (istate.icon.extent.y1 + istate.icon.extent.y0)/2 +
+ wstate.visible.y1 - wstate.yscroll;
+ }
+ ro_mouse_drag_start(ro_gui_download_drag_end, NULL, NULL, NULL);
+ download_window_current = dw;
+ ro_gui_drag_icon(x, y, sprite);
+
+ } else if (pointer->i == ICON_DOWNLOAD_DESTINATION) {
+ char command[256] = "Filer_OpenDir ";
+ char *dot;
+
+ strncpy(command + 14, dw->path, 242);
+ command[255] = 0;
+ dot = strrchr(command, '.');
+ if (dot) {
+ os_error *error;
+ *dot = 0;
+ error = xos_cli(command);
+ if (error) {
+ LOG("xos_cli: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("MiscError", error->errmess);
+ }
+ }
+ }
+ return true;
+}
+
+
+/**
+ * Handler Key_Press events in a download window.
+ *
+ * \param key key press returned by Wimp_Poll
+ * \return true iff key press handled
+ */
+
+bool ro_gui_download_keypress(wimp_key *key)
+{
+ struct gui_download_window *dw;
+
+ dw = (struct gui_download_window *)ro_gui_wimp_event_get_user_data(key->w);
+ switch (key->c)
+ {
+ case wimp_KEY_ESCAPE:
+ ro_gui_download_window_destroy(dw, false);
+ return true;
+
+ case wimp_KEY_RETURN: {
+ const char *name = ro_gui_get_icon_string(dw->window,
+ ICON_DOWNLOAD_PATH);
+ if (!strrchr(name, '.')) {
+ ro_warn_user("NoPathError", NULL);
+ return true;
+ }
+ ro_gui_convert_save_path(dw->path, sizeof dw->path, name);
+
+ dw->send_dataload = false;
+ if (ro_gui_download_save(dw, dw->path,
+ !nsoption_bool(confirm_overwrite)) && !dw->ctx)
+ {
+ /* finished already */
+ riscos_schedule(2000, ro_gui_download_window_destroy_wrapper, dw);
+ }
+ return true;
+ }
+ break;
+ }
+
+ /* ignore all other keypresses (F12 etc) */
+ return false;
+}
+
+
+/**
+ * Handle User_Drag_Box event for a drag from a download window.
+ *
+ * \param *drag block returned by Wimp_Poll
+ * \param *data NULL data to allow use as callback from ro_mouse.
+ */
+
+static void ro_gui_download_drag_end(wimp_dragged *drag, void *data)
+{
+ wimp_pointer pointer;
+ wimp_message message;
+ struct gui_download_window *dw = download_window_current;
+ const char *leaf;
+ os_error *error;
+
+ if (dw->saved || dw->error)
+ return;
+
+ error = xwimp_get_pointer_info(&pointer);
+ if (error) {
+ LOG("xwimp_get_pointer_info: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ /* ignore drags to the download window itself */
+ if (pointer.w == dw->window) return;
+
+ leaf = strrchr(dw->path, '.');
+ if (leaf)
+ leaf++;
+ else
+ leaf = dw->path;
+ ro_gui_convert_save_path(message.data.data_xfer.file_name, 212, leaf);
+
+ message.your_ref = 0;
+ message.action = message_DATA_SAVE;
+ message.data.data_xfer.w = pointer.w;
+ message.data.data_xfer.i = pointer.i;
+ message.data.data_xfer.pos.x = pointer.pos.x;
+ message.data.data_xfer.pos.y = pointer.pos.y;
+ message.data.data_xfer.est_size = dw->total_size ? dw->total_size :
+ dw->received;
+ message.data.data_xfer.file_type = dw->file_type;
+ message.size = 44 + ((strlen(message.data.data_xfer.file_name) + 4) &
+ (~3u));
+
+ error = xwimp_send_message_to_window(wimp_USER_MESSAGE, &message,
+ pointer.w, pointer.i, 0);
+ if (error) {
+ LOG("xwimp_send_message_to_window: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+
+ gui_current_drag_type = GUI_DRAG_DOWNLOAD_SAVE;
+}
+
+
+/**
+ * Handle Message_DataSaveAck for a drag from a download window.
+ *
+ * \param message block returned by Wimp_Poll
+ */
+
+void ro_gui_download_datasave_ack(wimp_message *message)
+{
+ struct gui_download_window *dw = download_window_current;
+
+ dw->send_dataload = true;
+ memcpy(&dw->save_message, message, sizeof(wimp_message));
+
+ if (!ro_gui_download_save(dw, message->data.data_xfer.file_name,
+ !nsoption_bool(confirm_overwrite)))
+ return;
+
+ if (!dw->ctx) {
+ /* Ack successful completed save with message_DATA_LOAD immediately
+ to reduce the chance of the target app getting confused by it
+ being delayed */
+
+ ro_gui_download_send_dataload(dw);
+
+ riscos_schedule(2000, ro_gui_download_window_destroy_wrapper, dw);
+ }
+}
+
+
+/**
+ * Return a pathname in canonical form
+ *
+ * \param path pathnamee to be canonicalised
+ * \return ptr to pathname in malloc block, or NULL
+ */
+
+char *ro_gui_download_canonicalise(const char *path)
+{
+ os_error *error;
+ int spare = 0;
+ char *buf;
+
+ error = xosfscontrol_canonicalise_path(path, NULL, NULL, NULL, 0, &spare);
+ if (error) {
+ LOG("xosfscontrol_canonicalise_path: 0x%x: %s", error->errnum, error->errmess);
+ return NULL;
+ }
+
+ buf = malloc(1 - spare);
+ if (buf) {
+ error = xosfscontrol_canonicalise_path(path, buf, NULL, NULL,
+ 1 - spare, NULL);
+ if (error) {
+ LOG("xosfscontrol_canonicalise_path: 0x%x: %s", error->errnum, error->errmess);
+
+ free(buf);
+ return NULL;
+ }
+ }
+
+ return buf;
+}
+
+
+/**
+ * Check the available space on the medium containing the destination file,
+ * taking into account any space currently occupied by the file at its
+ * original location.
+ *
+ * \param dw download window
+ * \param dest_file destination pathname
+ * \param orig_file current pathname, NULL if no existing file
+ * \return true iff there's enough space
+ */
+
+bool ro_gui_download_check_space(struct gui_download_window *dw,
+ const char *dest_file, const char *orig_file)
+{
+ /* is there enough free space for this file? */
+ int dest_len = strlen(dest_file);
+ os_error *error;
+ int max_file;
+ bits free_lo;
+ int free_hi;
+ char *dir;
+
+ dir = malloc(dest_len + 1);
+ if (!dir) return true;
+
+ while (dest_len > 0 && dest_file[--dest_len] != '.');
+
+ memcpy(dir, dest_file, dest_len);
+ dir[dest_len] = '\0';
+
+ /* try the 64-bit variant first (RO 3.6+) */
+ error = xosfscontrol_free_space64(dir, &free_lo, &free_hi,
+ &max_file, NULL, NULL);
+ if (error) {
+ LOG("xosfscontrol_free_space64: 0x%x: %s", error->errnum, error->errmess);
+
+ free_hi = 0;
+ error = xosfscontrol_free_space(dir, (int*)&free_lo,
+ &max_file, NULL);
+ if (error) {
+ LOG("xosfscontrol_free_space: 0x%x: %s", error->errnum, error->errmess);
+ /* close our eyes and hope */
+ free(dir);
+ return true;
+ }
+ }
+
+ free(dir);
+
+ if ((bits)max_file < dw->total_size || (!free_hi && free_lo < dw->total_size)) {
+ char *dest_canon, *orig_canon;
+ bits space;
+
+ if (!orig_file || !dw->file) {
+ /* no original file to take into account */
+ return false;
+ }
+
+ space = min((bits)max_file, free_lo);
+
+ dest_canon = ro_gui_download_canonicalise(dest_file);
+ if (!dest_canon) dest_canon = (char*)dest_file;
+
+ orig_canon = ro_gui_download_canonicalise(orig_file);
+ if (!orig_canon) orig_canon = (char*)orig_file;
+
+ /* not enough space; allow for the file's original location
+ when space is tight by comparing the first part of the two
+ pathnames (and assuming the FS isn't brain damaged!) */
+
+ char *dot = strchr(orig_canon, '.');
+ if (dot && !strncasecmp(dest_canon, orig_canon, (dot + 1) - orig_canon)) {
+ int allocation;
+
+ error = xosargs_read_allocation(dw->file,
+ &allocation);
+ if (error) {
+ LOG("xosargs_read_allocation: 0x%x : %s", error->errnum, error->errmess);
+ }
+ else {
+ space += allocation;
+ }
+ }
+
+ if (dest_canon != dest_file) free(dest_canon);
+ if (orig_canon != orig_file) free(orig_canon);
+
+ if (space >= dw->total_size) {
+ /* OK, renaming should work */
+ return true;
+ }
+
+ return false;
+ }
+ return true;
+}
+
+/**
+ * Move the downloading file to a new location and continue downloading there.
+ *
+ * \param dw download window
+ * \param dest_file new location
+ * \param src_file old location
+ * \return error iff failed to move file
+ */
+
+os_error *ro_gui_download_move(struct gui_download_window *dw,
+ const char *dest_file, const char *src_file)
+{
+ os_error *error;
+
+ /* close temporary file */
+ if (dw->file) {
+ error = xosfind_closew(dw->file);
+ dw->file = 0;
+ if (error) {
+ LOG("xosfind_closew: 0x%x: %s", error->errnum, error->errmess);
+ return error;
+ }
+ }
+
+ /* move or copy temporary file to destination file */
+ error = xosfscontrol_rename(src_file, dest_file);
+ /* Errors from a filing system have number 0x1XXnn, where XX is the FS
+ * number, and nn the error number. 0x9F is "Not same disc". */
+ if (error && (error->errnum == error_BAD_RENAME ||
+ (error->errnum & 0xFF00FFu) == 0x1009Fu)) {
+ /* rename failed: copy with delete */
+ error = xosfscontrol_copy(src_file, dest_file,
+ osfscontrol_COPY_FORCE |
+ osfscontrol_COPY_DELETE |
+ osfscontrol_COPY_LOOK,
+ 0, 0, 0, 0, 0);
+ if (error) {
+ LOG("xosfscontrol_copy: 0x%x: %s", error->errnum, error->errmess);
+ return error;
+ }
+ } else if (error) {
+ LOG("xosfscontrol_rename: 0x%x: %s", error->errnum, error->errmess);
+ return error;
+ }
+
+ if (dw->ctx) {
+ /* open new destination file if still fetching */
+ error = xosfile_write(dest_file, 0xdeaddead, 0xdeaddead,
+ fileswitch_ATTR_OWNER_READ |
+ fileswitch_ATTR_OWNER_WRITE);
+ if (error) {
+ LOG("xosfile_write: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("SaveError", error->errmess);
+ }
+
+ error = xosfind_openupw(osfind_NO_PATH | osfind_ERROR_IF_DIR,
+ dest_file, 0, &dw->file);
+ if (error) {
+ LOG("xosfind_openupw: 0x%x: %s", error->errnum, error->errmess);
+ return error;
+ }
+
+ error = xosargs_set_ptrw(dw->file, dw->received);
+ if (error) {
+ LOG("xosargs_set_ptrw: 0x%x: %s", error->errnum, error->errmess);
+ return error;
+ }
+
+ } else {
+ /* otherwise just set the file type */
+ error = xosfile_set_type(dest_file,
+ dw->file_type);
+ if (error) {
+ LOG("xosfile_set_type: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("SaveError", error->errmess);
+ }
+ }
+
+ /* success */
+ return NULL;
+}
+
+
+/**
+ * Remember the directory containing the given file,
+ * for use in further downloads.
+ *
+ * \param path pathname of downloaded file
+ * \return none
+ */
+
+void ro_gui_download_remember_dir(const char *path)
+{
+ const char *lastdot = NULL;
+ const char *p = path;
+
+ while (*p >= 0x20) {
+ if (*p == '.') {
+ /* don't remember the directory if it's a temporary file */
+ if (!lastdot && p == path + 12 &&
+ !memcmp(path, "<Wimp$Scrap>", 12)) break;
+ lastdot = p;
+ }
+ p++;
+ }
+
+ if (lastdot) {
+ /* remember the directory */
+ char *new_dir = realloc(download_dir, (lastdot+1)-path);
+ if (new_dir) {
+ download_dir_len = lastdot - path;
+ memcpy(new_dir, path, download_dir_len);
+ new_dir[download_dir_len] = '\0';
+ download_dir = new_dir;
+ }
+ }
+}
+
+/**
+ * Start of save operation, user has specified where the file should be saved.
+ *
+ * \param dw download window
+ * \param file_name pathname of destination file
+ & \param force_overwrite true iff required to overwrite without prompting
+ * \return true iff save successfully initiated
+ */
+
+bool ro_gui_download_save(struct gui_download_window *dw,
+ const char *file_name, bool force_overwrite)
+{
+ fileswitch_object_type obj_type;
+ const char *temp_name;
+ os_error *error;
+
+ if (dw->saved || dw->error)
+ return true;
+
+ temp_name = ro_gui_download_temp_name(dw);
+
+ /* does the user want to check for collisions when saving? */
+ if (!force_overwrite) {
+ /* check whether the destination file/dir already exists */
+ error = xosfile_read_stamped(file_name, &obj_type,
+ NULL, NULL, NULL, NULL, NULL);
+ if (error) {
+ LOG("xosfile_read_stamped: 0x%x:%s", error->errnum, error->errmess);
+ return false;
+ }
+
+ switch (obj_type) {
+ case osfile_NOT_FOUND:
+ break;
+
+ case osfile_IS_FILE:
+ dw->query = query_user("OverwriteFile", NULL, &overwrite_funcs, dw,
+ messages_get("Replace"), messages_get("DontReplace"));
+ dw->query_rsn = QueryRsn_Overwrite;
+ return false;
+
+ default:
+ error = xosfile_make_error(file_name, obj_type);
+ assert(error);
+ ro_warn_user("SaveError", error->errmess);
+ return false;
+ }
+ }
+
+ if (!ro_gui_download_check_space(dw, file_name, temp_name)) {
+ ro_warn_user("SaveError", messages_get("NoDiscSpace"));
+ return false;
+ }
+
+ error = ro_gui_download_move(dw, file_name, temp_name);
+ if (error) {
+ ro_warn_user("SaveError", error->errmess);
+
+ /* try to reopen at old location so that the download can continue
+ to the temporary file */
+ error = xosfind_openupw(osfind_NO_PATH | osfind_ERROR_IF_DIR,
+ temp_name, 0, &dw->file);
+ if (error) {
+ LOG("xosfind_openupw: 0x%x: %s", error->errnum, error->errmess);
+
+ } else {
+ error = xosargs_set_ptrw(dw->file, dw->received);
+ if (error) {
+ LOG("xosargs_set_ptrw: 0x%x: %s", error->errnum, error->errmess);
+ }
+ }
+
+ if (error) {
+ if (dw->ctx)
+ download_context_abort(dw->ctx);
+ gui_download_window_error(dw, error->errmess);
+ }
+ return false;
+ }
+
+ dw->saved = true;
+ strncpy(dw->path, file_name, sizeof dw->path);
+
+ if (!dw->send_dataload || dw->save_message.data.data_xfer.est_size != -1)
+ ro_gui_download_remember_dir(file_name);
+
+ /* grey out file icon */
+ error = xwimp_set_icon_state(dw->window, ICON_DOWNLOAD_ICON,
+ wimp_ICON_SHADED, wimp_ICON_SHADED);
+ if (error) {
+ LOG("xwimp_set_icon_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+
+ /* hide writeable path icon and show destination icon
+ Note: must redraw icon bounding box because the destination icon
+ has rounded edges on RISC OS Select/Adjust and doesn't
+ completely cover the writeable icon */
+
+ ro_gui_force_redraw_icon(dw->window, ICON_DOWNLOAD_PATH);
+ error = xwimp_set_icon_state(dw->window, ICON_DOWNLOAD_PATH,
+ wimp_ICON_DELETED, wimp_ICON_DELETED);
+ if (error) {
+ LOG("xwimp_set_icon_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+ error = xwimp_set_icon_state(dw->window,
+ ICON_DOWNLOAD_DESTINATION, wimp_ICON_DELETED, 0);
+ if (error) {
+ LOG("xwimp_set_icon_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+
+ ro_gui_download_window_hide_caret(dw);
+
+ return true;
+}
+
+
+/**
+ * Send DataLoad message in response to DataSaveAck, informing the
+ * target application that the transfer is complete.
+ *
+ * \param dw download window
+ */
+
+void ro_gui_download_send_dataload(struct gui_download_window *dw)
+{
+ /* Ack successful save with message_DATA_LOAD */
+ wimp_message *message = &dw->save_message;
+ os_error *error;
+
+ assert(dw->send_dataload);
+ dw->send_dataload = false;
+
+ message->action = message_DATA_LOAD;
+ message->your_ref = message->my_ref;
+ error = xwimp_send_message_to_window(wimp_USER_MESSAGE, message,
+ message->data.data_xfer.w,
+ message->data.data_xfer.i, 0);
+ /* The window we just attempted to send a message to may
+ * have been closed before the message was sent. As we've
+ * no clean way of detecting this, we'll just detect the
+ * error return from the message send attempt and judiciously
+ * ignore it.
+ *
+ * Ideally, we would have registered to receive Message_WindowClosed
+ * and then cleared dw->send_dataload flag for the appropriate
+ * window. Unfortunately, however, a long-standing bug in the
+ * Pinboard module prevents this from being a viable solution.
+ *
+ * See http://groups.google.co.uk/group/comp.sys.acorn.tech/msg/e3fbf70d8393e6cf?dmode=source&hl=en
+ * for the rather depressing details.
+ */
+ if (error && error->errnum != error_WIMP_BAD_HANDLE) {
+ LOG("xwimp_set_icon_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+
+ riscos_schedule(2000, ro_gui_download_window_destroy_wrapper, dw);
+}
+
+
+/**
+ * Handle closing of download window
+ */
+void ro_gui_download_close(wimp_w w)
+{
+ struct gui_download_window *dw;
+
+ dw = (struct gui_download_window *)ro_gui_wimp_event_get_user_data(w);
+ ro_gui_download_window_destroy(dw, false);
+}
+
+
+/**
+ * Close a download window and free any related resources.
+ *
+ * \param dw download window
+ * \param quit destroying because we're quitting the whole app
+ * \return true if window destroyed, not waiting for user confirmation
+ */
+
+bool ro_gui_download_window_destroy(struct gui_download_window *dw, bool quit)
+{
+ bool safe = dw->saved && !dw->ctx;
+ os_error *error;
+
+ if (!safe && !dw->close_confirmed)
+ {
+ query_reason rsn = quit ? QueryRsn_Quit : QueryRsn_Abort;
+
+ if (dw->query != QUERY_INVALID) {
+
+ /* can we just reuse the existing query? */
+ if (rsn == dw->query_rsn) {
+ ro_gui_query_window_bring_to_front(dw->query);
+ return false;
+ }
+
+ query_close(dw->query);
+ dw->query = QUERY_INVALID;
+ }
+
+ if (quit) {
+ /* bring all download windows to the front of the desktop as
+ a convenience if there are lots of windows open */
+
+ struct gui_download_window *d = download_window_list;
+ while (d) {
+ ro_gui_dialog_open_top(d->window, NULL, 0, 0);
+ d = d->next;
+ }
+ }
+
+ dw->query_rsn = rsn;
+ dw->query = query_user(quit ? "QuitDownload" : "AbortDownload",
+ NULL, &close_funcs, dw, NULL, NULL);
+
+ return false;
+ }
+
+ riscos_schedule(-1, ro_gui_download_update_status_wrapper, dw);
+ riscos_schedule(-1, ro_gui_download_window_destroy_wrapper, dw);
+
+ /* remove from list */
+ if (dw->prev)
+ dw->prev->next = dw->next;
+ else
+ download_window_list = dw->next;
+ if (dw->next)
+ dw->next->prev = dw->prev;
+
+ /* delete window */
+ error = xwimp_delete_window(dw->window);
+ if (error) {
+ LOG("xwimp_delete_window: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+ ro_gui_wimp_event_finalise(dw->window);
+
+ /* close download file */
+ if (dw->file) {
+ error = xosfind_closew(dw->file);
+ if (error) {
+ LOG("xosfind_closew: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("SaveError", error->errmess);
+ }
+ }
+
+ /* delete temporary file */
+ if (!dw->saved) {
+ const char *temp_name = ro_gui_download_temp_name(dw);
+
+ error = xosfile_delete(temp_name, 0, 0, 0, 0, 0);
+ if (error) {
+ LOG("xosfile_delete: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("SaveError", error->errmess);
+ }
+ }
+
+ if (dw->ctx) {
+ download_context_abort(dw->ctx);
+ download_context_destroy(dw->ctx);
+ }
+
+ free(dw);
+
+ return true;
+}
+
+
+/**
+ * Wrapper for ro_gui_download_window_destroy(), suitable for riscos_schedule().
+ */
+
+void ro_gui_download_window_destroy_wrapper(void *p)
+{
+ struct gui_download_window *dw = p;
+ if (dw->query != QUERY_INVALID)
+ query_close(dw->query);
+ dw->query = QUERY_INVALID;
+ dw->close_confirmed = true;
+ ro_gui_download_window_destroy(dw, false);
+}
+
+
+/**
+ * User has opted to cancel the close, leaving the download to continue.
+ */
+
+void ro_gui_download_close_cancelled(query_id id, enum query_response res, void *p)
+{
+ struct gui_download_window *dw = p;
+ dw->query = QUERY_INVALID;
+}
+
+
+/**
+ * Download aborted, close window and tidy up.
+ */
+
+void ro_gui_download_close_confirmed(query_id id, enum query_response res, void *p)
+{
+ struct gui_download_window *dw = p;
+ dw->query = QUERY_INVALID;
+ dw->close_confirmed = true;
+ if (dw->query_rsn == QueryRsn_Quit) {
+
+ /* destroy all our downloads */
+ while (download_window_list)
+ ro_gui_download_window_destroy_wrapper(download_window_list);
+
+ /* and restart the shutdown */
+ if (ro_gui_prequit())
+ riscos_done = true;
+ }
+ else
+ ro_gui_download_window_destroy(dw, false);
+}
+
+
+/**
+ * User has opted not to overwrite the existing file.
+ */
+
+void ro_gui_download_overwrite_cancelled(query_id id, enum query_response res, void *p)
+{
+ struct gui_download_window *dw = p;
+ dw->query = QUERY_INVALID;
+}
+
+
+/**
+ * Overwrite of existing file confirmed, proceed with the save.
+ */
+
+void ro_gui_download_overwrite_confirmed(query_id id, enum query_response res, void *p)
+{
+ struct gui_download_window *dw = p;
+ dw->query = QUERY_INVALID;
+
+ if (!ro_gui_download_save(dw, dw->save_message.data.data_xfer.file_name, true))
+ return;
+
+ if (!dw->ctx) {
+ /* Ack successful completed save with message_DATA_LOAD immediately
+ to reduce the chance of the target app getting confused by it
+ being delayed */
+
+ ro_gui_download_send_dataload(dw);
+
+ riscos_schedule(2000, ro_gui_download_window_destroy_wrapper, dw);
+ }
+}
+
+
+/**
+ * Respond to PreQuit message, displaying a prompt message if we need
+ * the user to confirm the shutdown.
+ *
+ * \return true if we can shutdown straightaway
+ */
+
+bool ro_gui_download_prequit(void)
+{
+ while (download_window_list)
+ {
+ if (!ro_gui_download_window_destroy(download_window_list, true))
+ return false; /* awaiting user confirmation */
+ }
+ return true;
+}
+
+static struct gui_download_table download_table = {
+ .create = gui_download_window_create,
+ .data = gui_download_window_data,
+ .error = gui_download_window_error,
+ .done = gui_download_window_done,
+};
+
+struct gui_download_table *riscos_download_table = &download_table;
diff --git a/frontends/riscos/filetype.c b/frontends/riscos/filetype.c
new file mode 100644
index 000000000..99a44ae30
--- /dev/null
+++ b/frontends/riscos/filetype.c
@@ -0,0 +1,352 @@
+/*
+ * Copyright 2004 James Bursa <bursa@users.sourceforge.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <unixlib/local.h>
+#include "oslib/mimemap.h"
+#include "oslib/osfile.h"
+
+#include "utils/config.h"
+#include "utils/log.h"
+#include "content/content.h"
+#include "content/fetch.h"
+#include "content/hlcache.h"
+
+#include "riscos/filetype.h"
+#include "riscos/gui.h"
+
+/* type_map must be in sorted order by file_type */
+struct type_entry {
+ bits file_type;
+ char mime_type[40];
+};
+static const struct type_entry type_map[] = {
+ {0x132, "image/ico"},
+ {0x188, "application/x-shockwave-flash"},
+ {0x695, "image/gif"},
+ {0x69c, "image/x-ms-bmp"},
+ {0xaad, "image/svg+xml"},
+ {0xaff, "image/x-drawfile"},
+ {0xb60, "image/png"},
+ {0xc85, "image/jpeg"},
+ {0xd94, "image/x-artworks"},
+ {0xf78, "image/jng"},
+ {0xf79, "text/css"},
+ {0xf81, "application/javascript"},
+ {0xf83, "image/mng"},
+ {0xfaf, "text/html"},
+ {0xff9, "image/x-riscos-sprite"},
+ {0xfff, "text/plain"},
+};
+#define TYPE_MAP_COUNT (sizeof(type_map) / sizeof(type_map[0]))
+
+#define BUF_SIZE (256)
+static char type_buf[BUF_SIZE];
+
+
+static int cmp_type(const void *x, const void *y);
+
+/* exported interface documented in riscos/filetype.h */
+const char *fetch_filetype(const char *unix_path)
+{
+ struct type_entry *t;
+ unsigned int len = strlen(unix_path) + 100;
+ char *path = calloc(len, 1);
+ char *r;
+ os_error *error;
+ bits file_type, temp;
+ int objtype;
+
+ if (!path) {
+ LOG("Insufficient memory for calloc");
+ ro_warn_user("NoMemory", 0);
+ return "application/riscos";
+ }
+
+ /* convert path to RISC OS format and read file type */
+ r = __riscosify(unix_path, 0, __RISCOSIFY_NO_SUFFIX, path, len, 0);
+ if (r == 0) {
+ LOG("__riscosify failed");
+ free(path);
+ return "application/riscos";
+ }
+
+ error = xosfile_read_stamped_no_path(path, &objtype, 0, 0, 0, 0,
+ &file_type);
+ if (error) {
+ LOG("xosfile_read_stamped_no_path failed: %s", error->errmess);
+ free(path);
+ return "application/riscos";
+ }
+
+ if (objtype == osfile_IS_DIR) {
+ sprintf(type_buf, "application/x-netsurf-directory");
+ free(path);
+ return (const char *)type_buf;
+ }
+
+ /* If filetype is text or data, and the file has an extension, try to
+ * map the extension to a filetype via the MimeMap file. */
+ if (file_type == osfile_TYPE_TEXT || file_type == osfile_TYPE_DATA) {
+ char *slash = strrchr(path, '/');
+ if (slash) {
+ error = xmimemaptranslate_extension_to_filetype(
+ slash+1, &temp);
+ if (error)
+ /* ignore error and leave file_type alone */
+ LOG("xmimemaptranslate_extension_to_filetype: ""0x%x %s", error->errnum, error->errmess);
+ else
+ file_type = temp;
+ }
+ }
+
+ /* search for MIME type in our internal table */
+ t = bsearch(&file_type, type_map, TYPE_MAP_COUNT,
+ sizeof(type_map[0]), cmp_type);
+ if (t) {
+ /* found, so return it */
+ free(path);
+ return t->mime_type;
+ }
+
+ /* not in internal table, so ask MimeMap */
+ error = xmimemaptranslate_filetype_to_mime_type(file_type, type_buf);
+ if (error) {
+ LOG("0x%x %s", error->errnum, error->errmess);
+ free(path);
+ return "application/riscos";
+ }
+ /* make sure we're NULL terminated. If we're not, the MimeMap
+ * module's probably written past the end of the buffer from
+ * SVC mode. Short of rewriting MimeMap with an incompatible API,
+ * there's nothing we can do about it.
+ */
+ type_buf[BUF_SIZE - 1] = '\0';
+
+ free(path);
+
+ LOG("mime type '%s'", type_buf);
+ return (const char *)type_buf;
+
+}
+
+/* exported interface documented in riscos/filetype.h */
+char *fetch_mimetype(const char *ro_path)
+{
+ os_error *e;
+ bits filetype = 0, load;
+ int objtype;
+ char *mime = calloc(BUF_SIZE, sizeof(char));
+ char *slash;
+ struct type_entry *t;
+
+ if (!mime) {
+ LOG("Insufficient memory for calloc");
+ ro_warn_user("NoMemory", 0);
+ return 0;
+ }
+
+ e = xosfile_read_no_path(ro_path, &objtype, &load, 0, 0, 0);
+ if (e) {
+ LOG("xosfile_read_no_path: 0x%x: %s", e->errnum, e->errmess);
+ free(mime);
+ return 0;
+ }
+
+ if (objtype == osfile_IS_DIR) {
+ free(mime);
+ return 0; /* directories are pointless */
+ }
+
+ if ((load >> 20) & 0xFFF) {
+ filetype = (load>>8) & 0x000FFF;
+ }
+ else {
+ free(mime);
+ return 0; /* no idea */
+ }
+
+ /* If filetype is text and the file has an extension, try to map the
+ * extension to a filetype via the MimeMap file. */
+ slash = strrchr(ro_path, '/');
+ if (slash && filetype == osfile_TYPE_TEXT) {
+ e = xmimemaptranslate_extension_to_filetype(slash+1, &load);
+ if (e)
+ /* if we get an error here, simply ignore it and
+ * leave filetype unchanged */
+ LOG("0x%x %s", e->errnum, e->errmess);
+ else
+ filetype = load;
+ }
+
+ /* search for MIME type in our internal table */
+ t = bsearch(&filetype, type_map, TYPE_MAP_COUNT,
+ sizeof(type_map[0]), cmp_type);
+ if (t) {
+ /* found, so return it */
+ strncpy(mime, t->mime_type, BUF_SIZE);
+ return mime;
+ }
+
+ /* not in internal table, so ask MimeMap */
+ e = xmimemaptranslate_filetype_to_mime_type(filetype, mime);
+ if (e) {
+ LOG("xmimemaptranslate_filetype_to_mime_type: 0x%x: %s", e->errnum, e->errmess);
+ free(mime);
+ return 0;
+ }
+ /* make sure we're NULL terminated. If we're not, the MimeMap
+ * module's probably written past the end of the buffer from
+ * SVC mode. Short of rewriting MimeMap with an incompatible API,
+ * there's nothing we can do about it.
+ */
+ mime[BUF_SIZE - 1] = '\0';
+
+ return mime;
+}
+
+/**
+ * Comparison function for bsearch
+ */
+int cmp_type(const void *x, const void *y)
+{
+ const bits *p = x;
+ const struct type_entry *q = y;
+ return *p < q->file_type ? -1 : (*p == q->file_type ? 0 : +1);
+}
+
+/* exported interface documented in riscos/filetype.h */
+int ro_content_filetype(hlcache_handle *c)
+{
+ lwc_string *mime_type;
+ int file_type;
+
+ file_type = ro_content_filetype_from_type(content_get_type(c));
+ if (file_type != 0)
+ return file_type;
+
+ mime_type = content_get_mime_type(c);
+
+ file_type = ro_content_filetype_from_mime_type(mime_type);
+
+ lwc_string_unref(mime_type);
+
+ return file_type;
+}
+
+
+/* exported interface documented in riscos/filetype.h */
+int ro_content_native_type(hlcache_handle *c)
+{
+ switch (ro_content_filetype(c)) {
+ case FILETYPE_JPEG: /* jpeg */
+ case FILETYPE_JNG: /* jng */
+ case FILETYPE_MNG: /* mng */
+ case FILETYPE_GIF: /* gif */
+ case FILETYPE_BMP: /* bmp */
+ case FILETYPE_ICO: /* ico */
+ case FILETYPE_PNG: /* png */
+ case 0xff9: /* sprite */
+ return osfile_TYPE_SPRITE;
+ case FILETYPE_SVG: /* svg */
+ case 0xaff: /* draw */
+ return osfile_TYPE_DRAW;
+ default:
+ break;
+ }
+
+ return osfile_TYPE_DATA;
+}
+
+
+/* exported interface documented in riscos/filetype.h */
+int ro_content_filetype_from_mime_type(lwc_string *mime_type)
+{
+ int file_type, index;
+ os_error *error;
+
+ /* Search internal type map */
+ for (index = TYPE_MAP_COUNT; index > 0; index--) {
+ const struct type_entry *e = &type_map[index - 1];
+
+ if (strlen(e->mime_type) == lwc_string_length(mime_type) &&
+ strncasecmp(e->mime_type,
+ lwc_string_data(mime_type),
+ lwc_string_length(mime_type)) == 0)
+ return e->file_type;
+ }
+
+ /* Ask MimeMap module */
+ error = xmimemaptranslate_mime_type_to_filetype(
+ lwc_string_data(mime_type), (bits *) &file_type);
+ if (error)
+ file_type = 0xffd;
+
+ return file_type;
+}
+
+
+/* exported interface documented in riscos/filetype.h */
+int ro_content_filetype_from_type(content_type type) {
+ switch (type) {
+ case CONTENT_HTML: return FILETYPE_HTML;
+ case CONTENT_TEXTPLAIN: return 0xfff;
+ case CONTENT_CSS: return 0xf79;
+ default: break;
+ }
+ return 0;
+}
+
+
+/* exported interface documented in riscos/filetype.h */
+bits ro_filetype_from_unix_path(const char *unix_path)
+{
+ unsigned int len = strlen(unix_path) + 100;
+ char *path = calloc(len, 1);
+ char *r;
+ os_error *error;
+ bits file_type;
+
+ if (!path) {
+ LOG("Insufficient memory for calloc");
+ ro_warn_user("NoMemory", 0);
+ return osfile_TYPE_DATA;
+ }
+
+ /* convert path to RISC OS format and read file type */
+ r = __riscosify(unix_path, 0, __RISCOSIFY_NO_SUFFIX, path, len, 0);
+ if (r == 0) {
+ LOG("__riscosify failed");
+ free(path);
+ return osfile_TYPE_DATA;
+ }
+
+ error = xosfile_read_stamped_no_path(path, 0, 0, 0, 0, 0,
+ &file_type);
+ if (error) {
+ LOG("xosfile_read_stamped_no_path failed: %s", error->errmess);
+ free(path);
+ return osfile_TYPE_DATA;
+ }
+
+ free(path);
+
+ return file_type;
+}
+
diff --git a/frontends/riscos/filetype.h b/frontends/riscos/filetype.h
new file mode 100644
index 000000000..3ba613033
--- /dev/null
+++ b/frontends/riscos/filetype.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2014 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file riscos/filetype.h
+ * RISC OS filetpe interface.
+ */
+
+#ifndef _NETSURF_RISCOS_FILETYPE_H_
+#define _NETSURF_RISCOS_FILETYPE_H_
+
+#include "content/content_type.h"
+
+#ifndef FILETYPE_ACORN_URI
+#define FILETYPE_ACORN_URI 0xf91
+#endif
+#ifndef FILETYPE_ANT_URL
+#define FILETYPE_ANT_URL 0xb28
+#endif
+#ifndef FILETYPE_IEURL
+#define FILETYPE_IEURL 0x1ba
+#endif
+#ifndef FILETYPE_HTML
+#define FILETYPE_HTML 0xfaf
+#endif
+#ifndef FILETYPE_JNG
+#define FILETYPE_JNG 0xf78
+#endif
+#ifndef FILETYPE_CSS
+#define FILETYPE_CSS 0xf79
+#endif
+#ifndef FILETYPE_MNG
+#define FILETYPE_MNG 0xf83
+#endif
+#ifndef FILETYPE_GIF
+#define FILETYPE_GIF 0x695
+#endif
+#ifndef FILETYPE_BMP
+#define FILETYPE_BMP 0x69c
+#endif
+#ifndef FILETYPE_ICO
+#define FILETYPE_ICO 0x132
+#endif
+#ifndef FILETYPE_PNG
+#define FILETYPE_PNG 0xb60
+#endif
+#ifndef FILETYPE_JPEG
+#define FILETYPE_JPEG 0xc85
+#endif
+#ifndef FILETYPE_ARTWORKS
+#define FILETYPE_ARTWORKS 0xd94
+#endif
+#ifndef FILETYPE_SVG
+#define FILETYPE_SVG 0xaad
+#endif
+
+/**
+ * Determine the MIME type of a local file.
+ *
+ * \param unix_path Unix style path to file on disk
+ * \return Pointer to MIME type string (should not be freed) - invalidated
+ * on next call to fetch_filetype.
+ */
+const char *fetch_filetype(const char *unix_path);
+
+/**
+ * Find a MIME type for a local file
+ *
+ * \param ro_path RISC OS style path to file on disk
+ * \return MIME type string (on heap, caller should free), or NULL
+ */
+char *fetch_mimetype(const char *ro_path);
+
+/**
+ * Determine the RISC OS filetype for a content.
+ *
+ * \param h The handle of the content to examine.
+ * \return The RISC OS filetype corresponding to the content
+ */
+int ro_content_filetype(struct hlcache_handle *h);
+
+/**
+ * Determine the native RISC OS filetype to export a content as
+ *
+ * \param c The content to examine
+ * \return Native RISC OS filetype for export
+ */
+int ro_content_native_type(struct hlcache_handle *c);
+
+/**
+ * Determine the RISC OS filetype for a MIME type
+ *
+ * \param mime_type MIME type to consider
+ * \return Corresponding RISC OS filetype
+ */
+int ro_content_filetype_from_mime_type(lwc_string *mime_type);
+
+/**
+ * Determine the RISC OS filetype from a content type.
+ *
+ * \param type The content type to examine.
+ * \return The RISC OS filetype corresponding to the content, or 0 for unknown
+ */
+int ro_content_filetype_from_type(content_type type);
+
+/**
+ * Determine the type of a local file.
+ *
+ * \param unix_path Unix style path to file on disk
+ * \return File type
+ */
+bits ro_filetype_from_unix_path(const char *unix_path);
+
+#endif
diff --git a/frontends/riscos/font.c b/frontends/riscos/font.c
new file mode 100644
index 000000000..2f2ba9a35
--- /dev/null
+++ b/frontends/riscos/font.c
@@ -0,0 +1,598 @@
+/*
+ * Copyright 2006 James Bursa <bursa@users.sourceforge.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * RISC OS implementation of Font handling.
+ *
+ * The RUfl is used to handle and render fonts.
+ */
+
+#include "utils/config.h"
+
+#include <assert.h>
+#include <string.h>
+#include <oslib/wimp.h>
+#include <oslib/wimpreadsysinfo.h>
+
+#include "utils/nsoption.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/utils.h"
+#include "desktop/gui_layout.h"
+
+#include "riscos/gui.h"
+#include "riscos/font.h"
+
+
+/** desktop font, size and style being used */
+char ro_gui_desktop_font_family[80];
+int ro_gui_desktop_font_size = 12;
+rufl_style ro_gui_desktop_font_style = rufl_WEIGHT_400;
+bool no_font_blending = false;
+
+
+/**
+ * Check that at least Homerton.Medium is available.
+ */
+static void nsfont_check_fonts(void)
+{
+ char s[252];
+ font_f font;
+ os_error *error;
+
+ error = xfont_find_font("Homerton.Medium\\ELatin1",
+ 160, 160, 0, 0, &font, 0, 0);
+ if (error) {
+ if (error->errnum == error_FILE_NOT_FOUND) {
+ xwimp_start_task("TaskWindow -wimpslot 200K -quit "
+ "<NetSurf$Dir>.FixFonts", 0);
+ die("FontBadInst");
+ } else {
+ LOG("xfont_find_font: 0x%x: %s", error->errnum, error->errmess);
+ snprintf(s, sizeof s, messages_get("FontError"),
+ error->errmess);
+ die(s);
+ }
+ }
+
+ error = xfont_lose_font(font);
+ if (error) {
+ LOG("xfont_lose_font: 0x%x: %s", error->errnum, error->errmess);
+ snprintf(s, sizeof s, messages_get("FontError"),
+ error->errmess);
+ die(s);
+ }
+}
+
+
+/**
+ * Check that a font option is valid, and fix it if not.
+ *
+ * \param option pointer to option, as used by options.[ch]
+ * \param family font family to use if option is not set, or the set
+ * family is not available
+ * \param fallback font family to use if family is not available either
+ */
+static void nsfont_check_option(char **option, const char *family,
+ const char *fallback)
+{
+ if (*option && !nsfont_exists(*option)) {
+ free(*option);
+ *option = 0;
+ }
+ if (!*option) {
+ if (nsfont_exists(family))
+ *option = strdup(family);
+ else
+ *option = strdup(fallback);
+ }
+}
+
+
+/**
+ * Initialize font handling.
+ *
+ * Exits through die() on error.
+ */
+void nsfont_init(void)
+{
+ const char *fallback;
+ rufl_code code;
+
+ nsfont_check_fonts();
+
+ LOG("Initialise RUfl");
+ code = rufl_init();
+ if (code != rufl_OK) {
+ if (code == rufl_FONT_MANAGER_ERROR)
+ LOG("rufl_init: rufl_FONT_MANAGER_ERROR: 0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess);
+ else
+ LOG("rufl_init: 0x%x", code);
+ die("The Unicode font library could not be initialized. "
+ "Please report this to the developers.");
+ }
+ LOG("RUfl initialised");
+
+ if (rufl_family_list_entries == 0)
+ die("No fonts could be found. At least one font must be "
+ "installed.");
+
+ fallback = nsfont_fallback_font();
+
+ nsfont_check_option(&nsoption_charp(font_sans), "Homerton", fallback);
+ nsfont_check_option(&nsoption_charp(font_serif), "Trinity", fallback);
+ nsfont_check_option(&nsoption_charp(font_mono), "Corpus", fallback);
+ nsfont_check_option(&nsoption_charp(font_cursive), "Churchill", fallback);
+ nsfont_check_option(&nsoption_charp(font_fantasy), "Sassoon", fallback);
+
+ if (nsoption_int(font_default) != PLOT_FONT_FAMILY_SANS_SERIF &&
+ nsoption_int(font_default) != PLOT_FONT_FAMILY_SERIF &&
+ nsoption_int(font_default) != PLOT_FONT_FAMILY_MONOSPACE &&
+ nsoption_int(font_default) != PLOT_FONT_FAMILY_CURSIVE &&
+ nsoption_int(font_default) != PLOT_FONT_FAMILY_FANTASY) {
+ nsoption_set_int(font_default, PLOT_FONT_FAMILY_SANS_SERIF);
+ }
+}
+
+
+/**
+ * Retrieve the fallback font name
+ *
+ * \return Fallback font name
+ */
+const char *nsfont_fallback_font(void)
+{
+ const char *fallback = "Homerton";
+
+ if (!nsfont_exists(fallback)) {
+ LOG("Homerton not found, dumping RUfl family list");
+ for (unsigned int i = 0; i < rufl_family_list_entries; i++) {
+ LOG("'%s'", rufl_family_list[i]);
+ }
+ fallback = rufl_family_list[0];
+ }
+
+ return fallback;
+}
+
+
+/**
+ * bsearch comparison routine
+ */
+static int nsfont_list_cmp(const void *keyval, const void *datum)
+{
+ const char *key = keyval;
+ const char * const *entry = datum;
+ return strcasecmp(key, *entry);
+}
+
+
+/**
+ * Check if a font family is available.
+ *
+ * \param font_family name of font family
+ * \return true if the family is available
+ */
+bool nsfont_exists(const char *font_family)
+{
+ if (bsearch(font_family, rufl_family_list,
+ rufl_family_list_entries, sizeof rufl_family_list[0],
+ nsfont_list_cmp))
+ return true;
+ return false;
+}
+
+
+/**
+ * Measure the width of a string.
+ *
+ * \param fstyle plot style for this text
+ * \param string UTF-8 string to measure
+ * \param length length of string
+ * \param width updated to width of string[0..length)
+ * \return true on success, false on error and error reported
+ */
+static nserror
+ro_font_width(const plot_font_style_t *fstyle,
+ const char *string, size_t length,
+ int *width)
+{
+ const char *font_family;
+ unsigned int font_size;
+ rufl_style font_style;
+ rufl_code code;
+
+ nsfont_read_style(fstyle, &font_family, &font_size, &font_style);
+ if (font_size == 0) {
+ *width = 0;
+ return NSERROR_OK;
+ }
+
+ code = rufl_width(font_family, font_style, font_size,
+ string, length,
+ width);
+ if (code != rufl_OK) {
+ if (code == rufl_FONT_MANAGER_ERROR)
+ LOG("rufl_width: rufl_FONT_MANAGER_ERROR: 0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess);
+ else
+ LOG("rufl_width: 0x%x", code);
+/* ro_warn_user("MiscError", "font error"); */
+ *width = 0;
+ return NSERROR_INVALID;
+ }
+
+ *width /= 2;
+ return NSERROR_OK;
+}
+
+
+/**
+ * Find the position in a string where an x coordinate falls.
+ *
+ * \param fstyle style for this text
+ * \param string UTF-8 string to measure
+ * \param length length of string
+ * \param x x coordinate to search for
+ * \param char_offset updated to offset in string of actual_x, [0..length]
+ * \param actual_x updated to x coordinate of character closest to x
+ * \return true on success, false on error and error reported
+ */
+static nserror
+ro_font_position(const plot_font_style_t *fstyle,
+ const char *string, size_t length,
+ int x, size_t *char_offset, int *actual_x)
+{
+ const char *font_family;
+ unsigned int font_size;
+ rufl_style font_style;
+ rufl_code code;
+
+ nsfont_read_style(fstyle, &font_family, &font_size, &font_style);
+ if (font_size == 0) {
+ *char_offset = 0;
+ *actual_x = 0;
+ return NSERROR_OK;
+ }
+
+ code = rufl_x_to_offset(font_family, font_style, font_size,
+ string, length,
+ x * 2, char_offset, actual_x);
+ if (code != rufl_OK) {
+ if (code == rufl_FONT_MANAGER_ERROR)
+ LOG("rufl_x_to_offset: rufl_FONT_MANAGER_ERROR: ""0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess);
+ else
+ LOG("rufl_x_to_offset: 0x%x", code);
+/* ro_warn_user("MiscError", "font error"); */
+ *char_offset = 0;
+ *actual_x = 0;
+ return NSERROR_INVALID;
+ }
+
+ *actual_x /= 2;
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * Find where to split a string to make it fit a width.
+ *
+ * \param fstyle style for this text
+ * \param string UTF-8 string to measure
+ * \param length length of string, in bytes
+ * \param x width available
+ * \param char_offset updated to offset in string of actual_x, [1..length]
+ * \param actual_x updated to x coordinate of character closest to x
+ * \return true on success, false on error and error reported
+ *
+ * On exit, char_offset indicates first character after split point.
+ *
+ * Note: char_offset of 0 should never be returned.
+ *
+ * Returns:
+ * char_offset giving split point closest to x, where actual_x <= x
+ * else
+ * char_offset giving split point closest to x, where actual_x > x
+ *
+ * Returning char_offset == length means no split possible
+ */
+static nserror
+ro_font_split(const plot_font_style_t *fstyle,
+ const char *string, size_t length,
+ int x, size_t *char_offset, int *actual_x)
+{
+ const char *font_family;
+ unsigned int font_size;
+ rufl_style font_style;
+ rufl_code code;
+
+ nsfont_read_style(fstyle, &font_family, &font_size, &font_style);
+ if (font_size == 0) {
+ *char_offset = 0;
+ *actual_x = 0;
+ return NSERROR_OK;
+ }
+
+ code = rufl_split(font_family, font_style, font_size,
+ string, length,
+ x * 2, char_offset, actual_x);
+ if (code != rufl_OK) {
+ if (code == rufl_FONT_MANAGER_ERROR) {
+ LOG("rufl_split: rufl_FONT_MANAGER_ERROR: ""0x%x: %s",
+ rufl_fm_error->errnum, rufl_fm_error->errmess);
+ } else {
+ LOG("rufl_split: 0x%x", code);
+ }
+/* ro_warn_user("MiscError", "font error"); */
+ *char_offset = 0;
+ *actual_x = 0;
+ return NSERROR_INVALID;
+ }
+
+ if (*char_offset != length) {
+ /* we found something to split at */
+ size_t orig = *char_offset;
+
+ /* ensure a space at <= the split point we found */
+ while (*char_offset && string[*char_offset] != ' ') {
+ (*char_offset)--;
+ }
+
+ /* nothing valid found <= split point, advance to next space */
+ if (*char_offset == 0) {
+ *char_offset = orig;
+ while ((*char_offset != length) &&
+ (string[*char_offset] != ' ')) {
+ (*char_offset)++;
+ }
+ }
+ }
+
+ code = rufl_width(font_family, font_style, font_size,
+ string, *char_offset,
+ actual_x);
+ if (code != rufl_OK) {
+ if (code == rufl_FONT_MANAGER_ERROR) {
+ LOG("rufl_width: rufl_FONT_MANAGER_ERROR: 0x%x: %s",
+ rufl_fm_error->errnum, rufl_fm_error->errmess);
+ } else {
+ LOG("rufl_width: 0x%x", code);
+ }
+/* ro_warn_user("MiscError", "font error"); */
+ *char_offset = 0;
+ *actual_x = 0;
+ return NSERROR_INVALID;
+ }
+
+ *actual_x /= 2;
+ return NSERROR_OK;
+}
+
+
+/**
+ * Paint a string.
+ *
+ * \param fstyle plot style for this text
+ * \param string UTF-8 string to measure
+ * \param length length of string
+ * \param x x coordinate
+ * \param y y coordinate
+ * \return true on success, false on error and error reported
+ */
+bool nsfont_paint(const plot_font_style_t *fstyle, const char *string,
+ size_t length, int x, int y)
+{
+ const char *font_family;
+ unsigned int font_size;
+ unsigned int flags = rufl_BLEND_FONT;
+ rufl_style font_style;
+ rufl_code code;
+
+ nsfont_read_style(fstyle, &font_family, &font_size, &font_style);
+ if (font_size == 0)
+ return true;
+
+ if (no_font_blending || print_active)
+ flags = 0;
+
+ code = rufl_paint(font_family, font_style, font_size,
+ string, length, x, y, flags);
+ if (code != rufl_OK) {
+ if (code == rufl_FONT_MANAGER_ERROR) {
+ LOG("rufl_paint: rufl_FONT_MANAGER_ERROR: 0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess);
+ } else {
+ LOG("rufl_paint: 0x%x", code);
+ }
+ }
+
+ return true;
+}
+
+
+/**
+ * Convert a font style to a font family, size and rufl_style.
+ *
+ * \param fstyle plot style for this text
+ * \param font_family updated to font family
+ * \param font_size updated to font size
+ * \param font_style updated to font style
+ */
+void nsfont_read_style(const plot_font_style_t *fstyle,
+ const char **font_family, unsigned int *font_size,
+ rufl_style *font_style)
+{
+ static const rufl_style weight_table[] = {
+ rufl_WEIGHT_100,
+ rufl_WEIGHT_200,
+ rufl_WEIGHT_300,
+ rufl_WEIGHT_400,
+ rufl_WEIGHT_500,
+ rufl_WEIGHT_600,
+ rufl_WEIGHT_700,
+ rufl_WEIGHT_800,
+ rufl_WEIGHT_900
+ };
+
+ *font_size = (fstyle->size * 16) / FONT_SIZE_SCALE;
+ if (1600 < *font_size)
+ *font_size = 1600;
+
+ switch (fstyle->family) {
+ case PLOT_FONT_FAMILY_SANS_SERIF:
+ *font_family = nsoption_charp(font_sans);
+ break;
+ case PLOT_FONT_FAMILY_SERIF:
+ *font_family = nsoption_charp(font_serif);
+ break;
+ case PLOT_FONT_FAMILY_MONOSPACE:
+ *font_family = nsoption_charp(font_mono);
+ break;
+ case PLOT_FONT_FAMILY_CURSIVE:
+ *font_family = nsoption_charp(font_cursive);
+ break;
+ case PLOT_FONT_FAMILY_FANTASY:
+ *font_family = nsoption_charp(font_fantasy);
+ break;
+ default:
+ *font_family = nsoption_charp(font_sans);
+ break;
+ }
+
+ if ((fstyle->flags & FONTF_ITALIC) || (fstyle->flags & FONTF_OBLIQUE)) {
+ *font_style = rufl_SLANTED;
+ } else {
+ *font_style = 0;
+ }
+
+ *font_style |= weight_table[(fstyle->weight / 100) - 1];
+}
+
+
+/**
+ * Looks up the current desktop font and converts that to a family name,
+ * font size and style flags suitable for passing directly to rufl
+ *
+ * \param family buffer to receive font family
+ * \param family_size buffer size
+ * \param psize receives the font size in 1/16 points
+ * \param pstyle receives the style settings to be passed to rufl
+ */
+static void
+ro_gui_wimp_desktop_font(char *family,
+ size_t family_size,
+ int *psize,
+ rufl_style *pstyle)
+{
+ rufl_style style = rufl_WEIGHT_400;
+ os_error *error;
+ int ptx, pty;
+ font_f font_handle;
+ int used;
+
+ assert(family);
+ assert(20 < family_size);
+ assert(psize);
+ assert(pstyle);
+
+ error = xwimpreadsysinfo_font(&font_handle, NULL);
+ if (error) {
+ LOG("xwimpreadsysinfo_font: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ goto failsafe;
+ }
+
+ if (font_handle == font_SYSTEM) {
+ /* Er, yeah; like that's ever gonna work with RUfl */
+ goto failsafe;
+ }
+
+ error = xfont_read_identifier(font_handle, NULL, &used);
+ if (error) {
+ LOG("xfont_read_identifier: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("MiscError", error->errmess);
+ goto failsafe;
+ }
+
+ if (family_size < (size_t) used + 1) {
+ LOG("desktop font name too long");
+ goto failsafe;
+ }
+
+ error = xfont_read_defn(font_handle, (byte *) family,
+ &ptx, &pty, NULL, NULL, NULL, NULL);
+ if (error) {
+ LOG("xfont_read_defn: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("MiscError", error->errmess);
+ goto failsafe;
+ }
+
+ for (size_t i = 0; i != (size_t) used; i++) {
+ if (family[i] < ' ') {
+ family[i] = 0;
+ break;
+ }
+ }
+
+ LOG("desktop font \"%s\"", family);
+
+ if (strcasestr(family, ".Medium"))
+ style = rufl_WEIGHT_500;
+ else if (strcasestr(family, ".Bold"))
+ style = rufl_WEIGHT_700;
+ if (strcasestr(family, ".Italic") || strcasestr(family, ".Oblique"))
+ style |= rufl_SLANTED;
+
+ char *dot = strchr(family, '.');
+ if (dot)
+ *dot = 0;
+
+ *psize = max(ptx, pty);
+ *pstyle = style;
+
+ LOG("family \"%s\", size %i, style %i", family, *psize, style);
+
+ return;
+
+failsafe:
+ strcpy(family, "Homerton");
+ *psize = 12*16;
+ *pstyle = rufl_WEIGHT_400;
+}
+
+
+/**
+ * Retrieve the current desktop font family, size and style from
+ * the WindowManager in a form suitable for passing to rufl
+ */
+void ro_gui_wimp_get_desktop_font(void)
+{
+ ro_gui_wimp_desktop_font(ro_gui_desktop_font_family,
+ sizeof(ro_gui_desktop_font_family),
+ &ro_gui_desktop_font_size,
+ &ro_gui_desktop_font_style);
+}
+
+
+static struct gui_layout_table layout_table = {
+ .width = ro_font_width,
+ .position = ro_font_position,
+ .split = ro_font_split,
+};
+
+struct gui_layout_table *riscos_layout_table = &layout_table;
diff --git a/frontends/riscos/font.h b/frontends/riscos/font.h
new file mode 100644
index 000000000..0319a7ee3
--- /dev/null
+++ b/frontends/riscos/font.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2014 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file riscos/font.h
+ * RISC OS font interface.
+ */
+
+#ifndef _NETSURF_RISCOS_FONT_H_
+#define _NETSURF_RISCOS_FONT_H_
+
+#include <rufl.h>
+
+struct gui_layout_table *riscos_layout_table;
+
+/** desktop font, size and style being used */
+extern char ro_gui_desktop_font_family[];
+extern int ro_gui_desktop_font_size;
+extern rufl_style ro_gui_desktop_font_style;
+
+void nsfont_init(void);
+bool nsfont_exists(const char *font_family);
+const char *nsfont_fallback_font(void);
+bool nsfont_paint(const plot_font_style_t *fstyle, const char *string,
+ size_t length, int x, int y);
+void nsfont_read_style(const plot_font_style_t *fstyle,
+ const char **font_family, unsigned int *font_size,
+ rufl_style *font_style);
+void ro_gui_wimp_get_desktop_font(void);
+
+#endif
diff --git a/frontends/riscos/global_history.c b/frontends/riscos/global_history.c
new file mode 100644
index 000000000..c469847e0
--- /dev/null
+++ b/frontends/riscos/global_history.c
@@ -0,0 +1,413 @@
+/*
+ * Copyright 2005 Richard Wilson <info@tinct.net>
+ * Copyright 2010 Stephen Fryatt <stevef@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Global history (implementation).
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "oslib/wimp.h"
+#include "oslib/wimpspriteop.h"
+
+#include "content/urldb.h"
+#include "utils/nsoption.h"
+#include "utils/messages.h"
+#include "utils/log.h"
+#include "desktop/global_history.h"
+#include "desktop/tree.h"
+#include "desktop/gui_window.h"
+
+#include "riscos/dialog.h"
+#include "riscos/global_history.h"
+#include "riscos/gui.h"
+#include "riscos/menus.h"
+#include "riscos/save.h"
+#include "riscos/toolbar.h"
+#include "riscos/treeview.h"
+#include "riscos/wimp.h"
+#include "riscos/wimp_event.h"
+
+static void ro_gui_global_history_toolbar_update_buttons(void);
+static void ro_gui_global_history_toolbar_save_buttons(char *config);
+static bool ro_gui_global_history_menu_prepare(wimp_w w, wimp_i i,
+ wimp_menu *menu, wimp_pointer *pointer);
+static void ro_gui_global_history_menu_warning(wimp_w w, wimp_i i,
+ wimp_menu *menu, wimp_selection *selection, menu_action action);
+static bool ro_gui_global_history_menu_select(wimp_w w, wimp_i i,
+ wimp_menu *menu, wimp_selection *selection, menu_action action);
+static void ro_gui_global_history_toolbar_click(button_bar_action action);
+
+struct ro_treeview_callbacks ro_global_history_treeview_callbacks = {
+ ro_gui_global_history_toolbar_click,
+ ro_gui_global_history_toolbar_update_buttons,
+ ro_gui_global_history_toolbar_save_buttons
+};
+
+/* The RISC OS global history window, toolbar and treeview data */
+
+static struct ro_global_history_window {
+ wimp_w window;
+ struct toolbar *toolbar;
+ ro_treeview *tv;
+ wimp_menu *menu;
+} global_history_window;
+
+/**
+ * Pre-Initialise the global history tree. This is called for things that
+ * need to be done at the gui_init() stage, such as loading templates.
+ */
+
+void ro_gui_global_history_preinitialise(void)
+{
+ /* Create our window. */
+
+ global_history_window.window = ro_gui_dialog_create("tree");
+ ro_gui_set_window_title(global_history_window.window,
+ messages_get("GlobalHistory"));
+}
+
+/**
+ * Initialise global history tree, at the gui_init2() stage.
+ */
+
+void ro_gui_global_history_postinitialise(void)
+{
+ /* Create our toolbar. */
+
+ global_history_window.toolbar = ro_toolbar_create(NULL,
+ global_history_window.window,
+ THEME_STYLE_GLOBAL_HISTORY_TOOLBAR, TOOLBAR_FLAGS_NONE,
+ ro_treeview_get_toolbar_callbacks(), NULL,
+ "HelpGHistoryToolbar");
+ if (global_history_window.toolbar != NULL) {
+ ro_toolbar_add_buttons(global_history_window.toolbar,
+ global_history_toolbar_buttons,
+ nsoption_charp(toolbar_history));
+ ro_toolbar_rebuild(global_history_window.toolbar);
+ }
+
+ /* Create the treeview with the window and toolbar. */
+
+ global_history_window.tv =
+ ro_treeview_create(global_history_window.window,
+ global_history_window.toolbar,
+ &ro_global_history_treeview_callbacks,
+ TREE_HISTORY);
+ if (global_history_window.tv == NULL) {
+ LOG("Failed to allocate treeview");
+ return;
+ }
+
+ ro_toolbar_update_client_data(global_history_window.toolbar,
+ global_history_window.tv);
+
+ /* Build the global history window menu. */
+
+ static const struct ns_menu global_history_definition = {
+ "History", {
+ { "History", NO_ACTION, 0 },
+ { "_History.Export", HISTORY_EXPORT, &dialog_saveas },
+ { "History.Expand", TREE_EXPAND_ALL, 0 },
+ { "History.Expand.All", TREE_EXPAND_ALL, 0 },
+ { "History.Expand.Folders", TREE_EXPAND_FOLDERS, 0 },
+ { "History.Expand.Links", TREE_EXPAND_LINKS, 0 },
+ { "History.Collapse", TREE_COLLAPSE_ALL, 0 },
+ { "History.Collapse.All", TREE_COLLAPSE_ALL, 0 },
+ { "History.Collapse.Folders", TREE_COLLAPSE_FOLDERS, 0 },
+ { "History.Collapse.Links", TREE_COLLAPSE_LINKS, 0 },
+ { "History.Toolbars", NO_ACTION, 0 },
+ { "_History.Toolbars.ToolButtons", TOOLBAR_BUTTONS, 0 },
+ { "History.Toolbars.EditToolbar",TOOLBAR_EDIT, 0 },
+ { "Selection", TREE_SELECTION, 0 },
+ { "Selection.Launch", TREE_SELECTION_LAUNCH, 0 },
+ { "Selection.Delete", TREE_SELECTION_DELETE, 0 },
+ { "SelectAll", TREE_SELECT_ALL, 0 },
+ { "Clear", TREE_CLEAR_SELECTION, 0 },
+ {NULL, 0, 0}
+ }
+ };
+ global_history_window.menu = ro_gui_menu_define_menu(
+ &global_history_definition);
+
+ ro_gui_wimp_event_register_menu(global_history_window.window,
+ global_history_window.menu, false, false);
+ ro_gui_wimp_event_register_menu_prepare(global_history_window.window,
+ ro_gui_global_history_menu_prepare);
+ ro_gui_wimp_event_register_menu_selection(global_history_window.window,
+ ro_gui_global_history_menu_select);
+ ro_gui_wimp_event_register_menu_warning(global_history_window.window,
+ ro_gui_global_history_menu_warning);
+}
+
+/**
+ * Destroy the global history window.
+ */
+
+void ro_gui_global_history_destroy(void)
+{
+ if (global_history_window.tv == NULL)
+ return;
+
+ ro_treeview_destroy(global_history_window.tv);
+}
+
+/**
+ * Open the global history window.
+ */
+
+void ro_gui_global_history_open(void)
+{
+ ro_gui_global_history_toolbar_update_buttons();
+
+ if (!ro_gui_dialog_open_top(global_history_window.window,
+ global_history_window.toolbar, 600, 800)) {
+ ro_treeview_set_origin(global_history_window.tv, 0,
+ -(ro_toolbar_height(
+ global_history_window.toolbar)));
+ }
+}
+
+/**
+ * Handle toolbar button clicks.
+ *
+ * \param action The action to handle
+ */
+
+void ro_gui_global_history_toolbar_click(button_bar_action action)
+{
+ switch (action) {
+ case TOOLBAR_BUTTON_DELETE:
+ global_history_keypress(NS_KEY_DELETE_LEFT);
+ break;
+
+ case TOOLBAR_BUTTON_EXPAND:
+ global_history_expand(false);
+ break;
+
+ case TOOLBAR_BUTTON_COLLAPSE:
+ global_history_contract(false);
+ break;
+
+ case TOOLBAR_BUTTON_OPEN:
+ global_history_expand(true);
+ break;
+
+ case TOOLBAR_BUTTON_CLOSE:
+ global_history_contract(true);
+ break;
+
+ case TOOLBAR_BUTTON_LAUNCH:
+ global_history_keypress(NS_KEY_CR);
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+/**
+ * Update the button state in the global history toolbar.
+ */
+
+void ro_gui_global_history_toolbar_update_buttons(void)
+{
+ ro_toolbar_set_button_shaded_state(global_history_window.toolbar,
+ TOOLBAR_BUTTON_DELETE,
+ !global_history_has_selection());
+
+ ro_toolbar_set_button_shaded_state(global_history_window.toolbar,
+ TOOLBAR_BUTTON_LAUNCH,
+ !global_history_has_selection());
+}
+
+
+/**
+ * Save a new button arrangement in the global history toolbar.
+ *
+ * \param *config The new button configuration string.
+ */
+
+void ro_gui_global_history_toolbar_save_buttons(char *config)
+{
+ nsoption_set_charp(toolbar_history, config);
+ ro_gui_save_options();
+}
+
+
+/**
+ * Prepare the global history menu for opening
+ *
+ * \param w The window owning the menu.
+ * \param i The icon owning the menu.
+ * \param *menu The menu about to be opened.
+ * \param *pointer Pointer to the relevant wimp event block, or
+ * NULL for an Adjust click.
+ * \return true if the event was handled; else false.
+ */
+
+bool ro_gui_global_history_menu_prepare(wimp_w w, wimp_i i, wimp_menu *menu,
+ wimp_pointer *pointer)
+{
+ bool selection;
+
+ if (menu != global_history_window.menu)
+ return false;
+
+ selection = global_history_has_selection();
+
+ ro_gui_menu_set_entry_shaded(global_history_window.menu,
+ TREE_SELECTION, !selection);
+ ro_gui_menu_set_entry_shaded(global_history_window.menu,
+ TREE_CLEAR_SELECTION, !selection);
+
+ ro_gui_save_prepare(GUI_SAVE_HISTORY_EXPORT_HTML,
+ NULL, NULL, NULL, NULL);
+
+ ro_gui_menu_set_entry_shaded(menu, TOOLBAR_BUTTONS,
+ ro_toolbar_menu_option_shade(
+ global_history_window.toolbar));
+ ro_gui_menu_set_entry_ticked(menu, TOOLBAR_BUTTONS,
+ ro_toolbar_menu_buttons_tick(
+ global_history_window.toolbar));
+
+ ro_gui_menu_set_entry_shaded(menu, TOOLBAR_EDIT,
+ ro_toolbar_menu_edit_shade(
+ global_history_window.toolbar));
+ ro_gui_menu_set_entry_ticked(menu, TOOLBAR_EDIT,
+ ro_toolbar_menu_edit_tick(
+ global_history_window.toolbar));
+
+ return true;
+}
+
+/**
+ * Handle submenu warnings for the global_hostory menu
+ *
+ * \param w The window owning the menu.
+ * \param i The icon owning the menu.
+ * \param *menu The menu to which the warning applies.
+ * \param *selection The wimp menu selection data.
+ * \param action The selected menu action.
+ */
+
+void ro_gui_global_history_menu_warning(wimp_w w, wimp_i i, wimp_menu *menu,
+ wimp_selection *selection, menu_action action)
+{
+ /* Do nothing */
+}
+
+/**
+ * Handle selections from the global history menu
+ *
+ * \param w The window owning the menu.
+ * \param i The icon owning the menu.
+ * \param *menu The menu from which the selection was made.
+ * \param *selection The wimp menu selection data.
+ * \param action The selected menu action.
+ * \return true if action accepted; else false.
+ */
+
+bool ro_gui_global_history_menu_select(wimp_w w, wimp_i i, wimp_menu *menu,
+ wimp_selection *selection, menu_action action)
+{
+ switch (action) {
+ case HISTORY_EXPORT:
+ ro_gui_dialog_open_persistent(w, dialog_saveas, true);
+ return true;
+ case TREE_EXPAND_ALL:
+ global_history_expand(false);
+ return true;
+ case TREE_EXPAND_FOLDERS:
+ global_history_expand(true);
+ return true;
+ case TREE_EXPAND_LINKS:
+ global_history_expand(false);
+ return true;
+ case TREE_COLLAPSE_ALL:
+ global_history_contract(true);
+ return true;
+ case TREE_COLLAPSE_FOLDERS:
+ global_history_contract(true);
+ return true;
+ case TREE_COLLAPSE_LINKS:
+ global_history_contract(false);
+ return true;
+ case TREE_SELECTION_LAUNCH:
+ global_history_keypress(NS_KEY_CR);
+ return true;
+ case TREE_SELECTION_DELETE:
+ global_history_keypress(NS_KEY_DELETE_LEFT);
+ return true;
+ case TREE_SELECT_ALL:
+ global_history_keypress(NS_KEY_SELECT_ALL);
+ return true;
+ case TREE_CLEAR_SELECTION:
+ global_history_keypress(NS_KEY_CLEAR_SELECTION);
+ return true;
+ case TOOLBAR_BUTTONS:
+ ro_toolbar_set_display_buttons(global_history_window.toolbar,
+ !ro_toolbar_get_display_buttons(
+ global_history_window.toolbar));
+ return true;
+ case TOOLBAR_EDIT:
+ ro_toolbar_toggle_edit(global_history_window.toolbar);
+ return true;
+ default:
+ return false;
+ }
+
+ return false;
+}
+
+/**
+ * Check if a particular window handle is the global history window
+ *
+ * \param window the window in question
+ * \return true if this window is the global history
+ */
+
+bool ro_gui_global_history_check_window(wimp_w window)
+{
+ if (global_history_window.window == window)
+ return true;
+ else
+ return false;
+}
+
+/**
+ * Check if a particular menu handle is the global history menu
+ *
+ * \param *menu The menu in question.
+ * \return true if this menu is the global history menu
+ */
+
+bool ro_gui_global_history_check_menu(wimp_menu *menu)
+{
+ if (global_history_window.menu == menu)
+ return true;
+ else
+ return false;
+}
+
diff --git a/frontends/riscos/global_history.h b/frontends/riscos/global_history.h
new file mode 100644
index 000000000..6f5ba11eb
--- /dev/null
+++ b/frontends/riscos/global_history.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2005 Richard Wilson <info@tinct.net>
+ * Copyright 2010 Stephen Fryatt <stevef@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Global history (interface).
+ */
+
+#ifndef _NETSURF_RISCOS_GLOBALHISTORY_H_
+#define _NETSURF_RISCOS_GLOBALHISTORY_H_
+
+#include "riscos/menus.h"
+
+void ro_gui_global_history_preinitialise(void);
+void ro_gui_global_history_postinitialise(void);
+void ro_gui_global_history_destroy(void);
+void ro_gui_global_history_open(void);
+void ro_gui_global_history_save(void);
+bool ro_gui_global_history_check_window(wimp_w window);
+bool ro_gui_global_history_check_menu(wimp_menu *menu);
+
+#endif
+
diff --git a/frontends/riscos/gui.c b/frontends/riscos/gui.c
new file mode 100644
index 000000000..309f27bdb
--- /dev/null
+++ b/frontends/riscos/gui.c
@@ -0,0 +1,2522 @@
+/*
+ * Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
+ * Copyright 2004-2008 James Bursa <bursa@users.sourceforge.net>
+ * Copyright 2003 John M Bell <jmb202@ecs.soton.ac.uk>
+ * Copyright 2005 Richard Wilson <info@tinct.net>
+ * Copyright 2004 Andrew Timmins <atimmins@blueyonder.co.uk>
+ * Copyright 2004-2009 John Tytgat <joty@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdbool.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <signal.h>
+#include <unixlib/local.h>
+#include <fpu_control.h>
+#include <oslib/help.h>
+#include <oslib/uri.h>
+#include <oslib/inetsuite.h>
+#include <oslib/pdriver.h>
+#include <oslib/osfile.h>
+#include <oslib/hourglass.h>
+#include <oslib/osgbpb.h>
+#include <oslib/osbyte.h>
+#include <oslib/osmodule.h>
+#include <oslib/osfscontrol.h>
+
+#include "utils/utils.h"
+#include "utils/nsoption.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/file.h"
+#include "utils/filename.h"
+#include "utils/url.h"
+#include "utils/corestrings.h"
+#include "desktop/gui_fetch.h"
+#include "desktop/gui_misc.h"
+#include "desktop/save_complete.h"
+#include "desktop/treeview.h"
+#include "desktop/netsurf.h"
+#include "desktop/browser.h"
+#include "content/urldb.h"
+#include "content/hlcache.h"
+#include "content/backing_store.h"
+
+#include "riscos/gui.h"
+#include "riscos/bitmap.h"
+#include "riscos/wimputils.h"
+#include "riscos/hotlist.h"
+#include "riscos/buffer.h"
+#include "riscos/textselection.h"
+#include "riscos/print.h"
+#include "riscos/save.h"
+#include "riscos/dialog.h"
+#include "riscos/wimp.h"
+#include "riscos/message.h"
+#include "riscos/help.h"
+#include "riscos/query.h"
+#include "riscos/window.h"
+#include "riscos/iconbar.h"
+#include "riscos/sslcert.h"
+#include "riscos/global_history.h"
+#include "riscos/cookies.h"
+#include "riscos/wimp_event.h"
+#include "riscos/uri.h"
+#include "riscos/url_protocol.h"
+#include "riscos/mouse.h"
+#include "riscos/ucstables.h"
+#include "riscos/filetype.h"
+#include "riscos/font.h"
+#include "riscos/toolbar.h"
+#include "riscos/content-handlers/artworks.h"
+#include "riscos/content-handlers/draw.h"
+#include "riscos/content-handlers/sprite.h"
+
+bool riscos_done = false;
+
+extern bool ro_plot_patterned_lines;
+
+int os_version = 0;
+
+const char * const __dynamic_da_name = "NetSurf"; /**< For UnixLib. */
+int __dynamic_da_max_size = 128 * 1024 * 1024; /**< For UnixLib. */
+int __feature_imagefs_is_file = 1; /**< For UnixLib. */
+/* default filename handling */
+int __riscosify_control = __RISCOSIFY_NO_SUFFIX |
+ __RISCOSIFY_NO_REVERSE_SUFFIX;
+#ifndef __ELF__
+extern int __dynamic_num;
+#endif
+
+const char * NETSURF_DIR;
+
+static const char *task_name = "NetSurf";
+#define CHOICES_PREFIX "<Choices$Write>.WWW.NetSurf."
+
+ro_gui_drag_type gui_current_drag_type;
+wimp_t task_handle; /**< RISC OS wimp task handle. */
+static clock_t gui_last_poll; /**< Time of last wimp_poll. */
+osspriteop_area *gui_sprites; /**< Sprite area containing pointer and hotlist sprites */
+
+#define DIR_SEP ('.')
+
+/**
+ * Accepted wimp user messages.
+ */
+static ns_wimp_message_list task_messages = {
+ message_HELP_REQUEST,
+ {
+ message_DATA_SAVE,
+ message_DATA_SAVE_ACK,
+ message_DATA_LOAD,
+ message_DATA_LOAD_ACK,
+ message_DATA_OPEN,
+ message_PRE_QUIT,
+ message_SAVE_DESKTOP,
+ message_MENU_WARNING,
+ message_MENUS_DELETED,
+ message_WINDOW_INFO,
+ message_CLAIM_ENTITY,
+ message_DATA_REQUEST,
+ message_DRAGGING,
+ message_DRAG_CLAIM,
+ message_MODE_CHANGE,
+ message_PALETTE_CHANGE,
+ message_FONT_CHANGED,
+ message_URI_PROCESS,
+ message_URI_RETURN_RESULT,
+ message_INET_SUITE_OPEN_URL,
+#ifdef WITH_PLUGIN
+ message_PLUG_IN_OPENING,
+ message_PLUG_IN_CLOSED,
+ message_PLUG_IN_RESHAPE_REQUEST,
+ message_PLUG_IN_FOCUS,
+ message_PLUG_IN_URL_ACCESS,
+ message_PLUG_IN_STATUS,
+ message_PLUG_IN_BUSY,
+ message_PLUG_IN_STREAM_NEW,
+ message_PLUG_IN_STREAM_WRITE,
+ message_PLUG_IN_STREAM_WRITTEN,
+ message_PLUG_IN_STREAM_DESTROY,
+ message_PLUG_IN_OPEN,
+ message_PLUG_IN_CLOSE,
+ message_PLUG_IN_RESHAPE,
+ message_PLUG_IN_STREAM_AS_FILE,
+ message_PLUG_IN_NOTIFY,
+ message_PLUG_IN_ABORT,
+ message_PLUG_IN_ACTION,
+ /* message_PLUG_IN_INFORMED, (not provided by oslib) */
+#endif
+ message_PRINT_SAVE,
+ message_PRINT_ERROR,
+ message_PRINT_TYPE_ODD,
+ message_HOTLIST_ADD_URL,
+ message_HOTLIST_CHANGED,
+ 0
+ }
+};
+
+
+static struct
+{
+ int width; /* in OS units */
+ int height;
+} screen_info;
+
+
+/**
+ * Callback to translate resource to full url for RISC OS.
+ *
+ * Transforms a resource: path into a full URL. The returned URL is
+ * used as the target for a redirect. The caller takes ownership of
+ * the returned nsurl including unrefing it when finished with it.
+ *
+ * \param path The path of the resource to locate.
+ * \return A string containing the full URL of the target object or
+ * NULL if no suitable resource can be found.
+ */
+static nsurl *gui_get_resource_url(const char *path)
+{
+ static const char base_url[] = "file:///NetSurf:/Resources/";
+ size_t path_len, length;
+ char *raw;
+ nsurl *url = NULL;
+
+ /* Map paths first */
+ if (strcmp(path, "adblock.css") == 0) {
+ path = "AdBlock";
+
+ } else if (strcmp(path, "default.css") == 0) {
+ path = "CSS";
+
+ } else if (strcmp(path, "quirks.css") == 0) {
+ path = "Quirks";
+
+ } else if (strcmp(path, "favicon.ico") == 0) {
+ path = "Icons/content.png";
+
+ } else if (strcmp(path, "user.css") == 0) {
+ /* Special case; this file comes from Choices: */
+ nsurl_create("file:///Choices:WWW/NetSurf/User", &url);
+ return url;
+ }
+
+ path_len = strlen(path);
+
+ /* Find max URL length */
+ length = SLEN(base_url) + SLEN("xx/") + path_len + 1;
+
+ raw = malloc(length);
+ if (raw != NULL) {
+ /* Insert base URL */
+ char *ptr = memcpy(raw, base_url, SLEN(base_url));
+ ptr += SLEN(base_url);
+
+ /* Add language directory to URL, for translated files */
+ /* TODO: handle non-en langauages
+ * handle non-html translated files */
+ if (path_len > SLEN(".html") &&
+ strncmp(path + path_len - SLEN(".html"),
+ ".html", SLEN(".html")) == 0) {
+ memcpy(ptr, "en/", SLEN("en/"));
+ ptr += SLEN("en/");
+ }
+
+ /* Add filename to URL */
+ memcpy(ptr, path, path_len);
+ ptr += path_len;
+
+ /* Terminate string */
+ *ptr = '\0';
+
+ nsurl_create(raw, &url);
+ free(raw);
+ }
+
+ return url;
+}
+
+
+/**
+ * Set colour option from wimp.
+ *
+ * \param opts The netsurf options.
+ * \param wimp wimp colour value
+ * \param option the netsurf option enum.
+ * \param def_colour The default colour value to use.
+ * \return NSERROR_OK on success or error code.
+ */
+static nserror
+set_colour_from_wimp(struct nsoption_s *opts,
+ wimp_colour wimp,
+ enum nsoption_e option,
+ colour def_colour)
+{
+ os_error *error;
+ os_PALETTE(20) palette;
+
+ error = xwimp_read_true_palette((os_palette *) &palette);
+ if (error != NULL) {
+ LOG("xwimp_read_palette: 0x%x: %s",
+ error->errnum, error->errmess);
+ } else {
+ /* entries are in B0G0R0LL */
+ def_colour = palette.entries[wimp] >> 8;
+ }
+
+ opts[option].value.c = def_colour;
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * Set option defaults for riscos frontend
+ *
+ * @param defaults The option table to update.
+ * @return error status.
+ *
+ * @todo The wimp_COLOUR_... values here map the colour definitions to
+ * parts of the RISC OS desktop palette. In places this is fairly
+ * arbitrary, and could probably do with re-checking.
+ */
+static nserror set_defaults(struct nsoption_s *defaults)
+{
+ /* Set defaults for absent option strings */
+ nsoption_setnull_charp(ca_bundle, strdup("NetSurf:Resources.ca-bundle"));
+ nsoption_setnull_charp(cookie_file, strdup("NetSurf:Cookies"));
+ nsoption_setnull_charp(cookie_jar, strdup(CHOICES_PREFIX "Cookies"));
+
+ if (nsoption_charp(ca_bundle) == NULL ||
+ nsoption_charp(cookie_file) == NULL ||
+ nsoption_charp(cookie_jar) == NULL) {
+ LOG("Failed initialising default options");
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ /* RISC OS platform does not generally benefit from disc cache
+ * so the default should be off.
+ */
+ nsoption_set_uint(disc_cache_size, 0);
+
+ /* set default system colours for riscos ui */
+ set_colour_from_wimp(defaults, wimp_COLOUR_BLACK, NSOPTION_sys_colour_ActiveBorder, 0x00000000);
+ set_colour_from_wimp(defaults, wimp_COLOUR_CREAM, NSOPTION_sys_colour_ActiveCaption, 0x00dddddd);
+ set_colour_from_wimp(defaults, wimp_COLOUR_VERY_LIGHT_GREY, NSOPTION_sys_colour_AppWorkspace, 0x00eeeeee);
+ set_colour_from_wimp(defaults, wimp_COLOUR_VERY_LIGHT_GREY, NSOPTION_sys_colour_Background, 0x00aa0000);/* \TODO -- Check */
+ set_colour_from_wimp(defaults, wimp_COLOUR_VERY_LIGHT_GREY, NSOPTION_sys_colour_ButtonFace, 0x00aaaaaa);
+ set_colour_from_wimp(defaults, wimp_COLOUR_DARK_GREY, NSOPTION_sys_colour_ButtonHighlight, 0x00cccccc);/* \TODO -- Check */
+ set_colour_from_wimp(defaults, wimp_COLOUR_MID_DARK_GREY, NSOPTION_sys_colour_ButtonShadow, 0x00bbbbbb);
+ set_colour_from_wimp(defaults, wimp_COLOUR_BLACK, NSOPTION_sys_colour_ButtonText, 0x00000000);
+ set_colour_from_wimp(defaults, wimp_COLOUR_BLACK, NSOPTION_sys_colour_CaptionText, 0x00000000);
+ set_colour_from_wimp(defaults, wimp_COLOUR_MID_LIGHT_GREY, NSOPTION_sys_colour_GrayText, 0x00777777);/* \TODO -- Check */
+ set_colour_from_wimp(defaults, wimp_COLOUR_BLACK, NSOPTION_sys_colour_Highlight, 0x00ee0000);
+ set_colour_from_wimp(defaults, wimp_COLOUR_WHITE, NSOPTION_sys_colour_HighlightText, 0x00000000);
+ set_colour_from_wimp(defaults, wimp_COLOUR_BLACK, NSOPTION_sys_colour_InactiveBorder, 0x00000000);
+ set_colour_from_wimp(defaults, wimp_COLOUR_LIGHT_GREY, NSOPTION_sys_colour_InactiveCaption, 0x00ffffff);
+ set_colour_from_wimp(defaults, wimp_COLOUR_BLACK, NSOPTION_sys_colour_InactiveCaptionText, 0x00cccccc);
+ set_colour_from_wimp(defaults, wimp_COLOUR_CREAM, NSOPTION_sys_colour_InfoBackground, 0x00aaaaaa);
+ set_colour_from_wimp(defaults, wimp_COLOUR_BLACK, NSOPTION_sys_colour_InfoText, 0x00000000);
+ set_colour_from_wimp(defaults, wimp_COLOUR_WHITE, NSOPTION_sys_colour_Menu, 0x00aaaaaa);
+ set_colour_from_wimp(defaults, wimp_COLOUR_BLACK, NSOPTION_sys_colour_MenuText, 0x00000000);
+ set_colour_from_wimp(defaults, wimp_COLOUR_LIGHT_GREY, NSOPTION_sys_colour_Scrollbar, 0x00aaaaaa);/* \TODO -- Check */
+ set_colour_from_wimp(defaults, wimp_COLOUR_MID_DARK_GREY, NSOPTION_sys_colour_ThreeDDarkShadow, 0x00555555);
+ set_colour_from_wimp(defaults, wimp_COLOUR_VERY_LIGHT_GREY, NSOPTION_sys_colour_ThreeDFace, 0x00dddddd);
+ set_colour_from_wimp(defaults, wimp_COLOUR_WHITE, NSOPTION_sys_colour_ThreeDHighlight, 0x00aaaaaa);
+ set_colour_from_wimp(defaults, wimp_COLOUR_WHITE, NSOPTION_sys_colour_ThreeDLightShadow, 0x00999999);
+ set_colour_from_wimp(defaults, wimp_COLOUR_MID_DARK_GREY, NSOPTION_sys_colour_ThreeDShadow, 0x00777777);
+ set_colour_from_wimp(defaults, wimp_COLOUR_VERY_LIGHT_GREY, NSOPTION_sys_colour_Window, 0x00aaaaaa);
+ set_colour_from_wimp(defaults, wimp_COLOUR_BLACK, NSOPTION_sys_colour_WindowFrame, 0x00000000);
+ set_colour_from_wimp(defaults, wimp_COLOUR_BLACK, NSOPTION_sys_colour_WindowText, 0x00000000);
+
+ return NSERROR_OK;
+}
+
+
+
+
+/**
+ * Create intermediate directories for Choices and User Data files
+ */
+static void ro_gui_create_dirs(void)
+{
+ char buf[256];
+ char *path;
+
+ /* Choices */
+ path = getenv("NetSurf$ChoicesSave");
+ if (!path)
+ die("Failed to find NetSurf Choices save path");
+
+ snprintf(buf, sizeof(buf), "%s", path);
+ netsurf_mkdir_all(buf);
+
+ /* URL */
+ snprintf(buf, sizeof(buf), "%s", nsoption_charp(url_save));
+ netsurf_mkdir_all(buf);
+
+ /* Hotlist */
+ snprintf(buf, sizeof(buf), "%s", nsoption_charp(hotlist_save));
+ netsurf_mkdir_all(buf);
+
+ /* Recent */
+ snprintf(buf, sizeof(buf), "%s", nsoption_charp(recent_save));
+ netsurf_mkdir_all(buf);
+
+ /* Theme */
+ snprintf(buf, sizeof(buf), "%s", nsoption_charp(theme_save));
+ netsurf_mkdir_all(buf);
+ /* and the final directory part (as theme_save is a directory) */
+ xosfile_create_dir(buf, 0);
+}
+
+
+/**
+ * Ensures the gui exits cleanly.
+ */
+static void ro_gui_cleanup(void)
+{
+ ro_gui_buffer_close();
+ xhourglass_off();
+ /* Uninstall NetSurf-specific fonts */
+ xos_cli("FontRemove NetSurf:Resources.Fonts.");
+}
+
+
+/**
+ * Handles a signal
+ */
+static void ro_gui_signal(int sig)
+{
+ static const os_error error = { 1, "NetSurf has detected a serious "
+ "error and must exit. Please submit a bug report, "
+ "attaching the browser log file." };
+ os_colour old_sand, old_glass;
+
+ ro_gui_cleanup();
+
+ xhourglass_on();
+ xhourglass_colours(0x0000ffff, 0x000000ff, &old_sand, &old_glass);
+ nsoption_dump(stderr, NULL);
+ /*rufl_dump_state();*/
+
+#ifndef __ELF__
+ /* save WimpSlot and DA to files if NetSurf$CoreDump exists */
+ int used;
+ xos_read_var_val_size("NetSurf$CoreDump", 0, 0, &used, 0, 0);
+ if (used) {
+ int curr_slot;
+ xwimp_slot_size(-1, -1, &curr_slot, 0, 0);
+ LOG("saving WimpSlot, size 0x%x", curr_slot);
+ xosfile_save("$.NetSurf_Slot", 0x8000, 0,
+ (byte *) 0x8000,
+ (byte *) 0x8000 + curr_slot);
+
+ if (__dynamic_num != -1) {
+ int size;
+ byte *base_address;
+ xosdynamicarea_read(__dynamic_num, &size,
+ &base_address, 0, 0, 0, 0, 0);
+ LOG("saving DA %i, base %p, size 0x%x", __dynamic_num, base_address, size);
+ xosfile_save("$.NetSurf_DA",
+ (bits) base_address, 0,
+ base_address,
+ base_address + size);
+ }
+ }
+#else
+ /* Save WimpSlot and UnixLib managed DAs when UnixEnv$coredump
+ * defines a coredump directory. */
+ const _kernel_oserror *err = __unixlib_write_coredump (NULL);
+ if (err != NULL)
+ LOG("Coredump failed: %s", err->errmess);
+#endif
+
+ xhourglass_colours(old_sand, old_glass, 0, 0);
+ xhourglass_off();
+
+ __write_backtrace(sig);
+
+ xwimp_report_error_by_category(&error,
+ wimp_ERROR_BOX_GIVEN_CATEGORY |
+ wimp_ERROR_BOX_CATEGORY_ERROR <<
+ wimp_ERROR_BOX_CATEGORY_SHIFT,
+ "NetSurf", "!netsurf",
+ (osspriteop_area *) 1, "Quit", 0);
+ xos_cli("Filer_Run <Wimp$ScrapDir>.WWW.NetSurf.Log");
+
+ _Exit(sig);
+}
+
+
+/**
+ * Read a "line" from an Acorn URI file.
+ *
+ * \param fp file pointer to read from
+ * \param b buffer for line, size 400 bytes
+ * \return true on success, false on EOF
+ */
+static bool ro_gui_uri_file_parse_line(FILE *fp, char *b)
+{
+ int c;
+ unsigned int i = 0;
+
+ c = getc(fp);
+ if (c == EOF)
+ return false;
+
+ /* skip comment lines */
+ while (c == '#') {
+ do { c = getc(fp); } while (c != EOF && 32 <= c);
+ if (c == EOF)
+ return false;
+ do { c = getc(fp); } while (c != EOF && c < 32);
+ if (c == EOF)
+ return false;
+ }
+
+ /* read "line" */
+ do {
+ if (i == 399)
+ return false;
+ b[i++] = c;
+ c = getc(fp);
+ } while (c != EOF && 32 <= c);
+
+ /* skip line ending control characters */
+ while (c != EOF && c < 32)
+ c = getc(fp);
+
+ if (c != EOF)
+ ungetc(c, fp);
+
+ b[i] = 0;
+ return true;
+}
+
+
+/**
+ * Parse an Acorn URI file.
+ *
+ * \param file_name file to read
+ * \param uri_title pointer to receive title data, or NULL for no data
+ * \return URL from file, or 0 on error and error reported
+ */
+static char *ro_gui_uri_file_parse(const char *file_name, char **uri_title)
+{
+ /* See the "Acorn URI Handler Functional Specification" for the
+ * definition of the URI file format. */
+ char line[400];
+ char *url = NULL;
+ FILE *fp;
+
+ *uri_title = NULL;
+ fp = fopen(file_name, "rb");
+ if (!fp) {
+ LOG("fopen(\"%s\", \"rb\"): %i: %s", file_name, errno, strerror(errno));
+ ro_warn_user("LoadError", strerror(errno));
+ return 0;
+ }
+
+ /* "URI" */
+ if (!ro_gui_uri_file_parse_line(fp, line) || strcmp(line, "URI") != 0)
+ goto uri_syntax_error;
+
+ /* version */
+ if (!ro_gui_uri_file_parse_line(fp, line) ||
+ strspn(line, "0123456789") != strlen(line))
+ goto uri_syntax_error;
+
+ /* URI */
+ if (!ro_gui_uri_file_parse_line(fp, line))
+ goto uri_syntax_error;
+
+ url = strdup(line);
+ if (!url) {
+ ro_warn_user("NoMemory", 0);
+ fclose(fp);
+ return 0;
+ }
+
+ /* title */
+ if (!ro_gui_uri_file_parse_line(fp, line))
+ goto uri_free;
+ if (uri_title && line[0] && ((line[0] != '*') || line[1])) {
+ *uri_title = strdup(line);
+ if (!*uri_title) /* non-fatal */
+ ro_warn_user("NoMemory", 0);
+ }
+ fclose(fp);
+
+ return url;
+
+uri_free:
+ free(url);
+
+uri_syntax_error:
+ fclose(fp);
+ ro_warn_user("URIError", 0);
+ return 0;
+}
+
+
+/**
+ * Parse an ANT URL file.
+ *
+ * \param file_name file to read
+ * \return URL from file, or 0 on error and error reported
+ */
+static char *ro_gui_url_file_parse(const char *file_name)
+{
+ char line[400];
+ char *url;
+ FILE *fp;
+
+ fp = fopen(file_name, "r");
+ if (!fp) {
+ LOG("fopen(\"%s\", \"r\"): %i: %s", file_name, errno, strerror(errno));
+ ro_warn_user("LoadError", strerror(errno));
+ return 0;
+ }
+
+ if (!fgets(line, sizeof line, fp)) {
+ if (ferror(fp)) {
+ LOG("fgets: %i: %s", errno, strerror(errno));
+ ro_warn_user("LoadError", strerror(errno));
+ } else
+ ro_warn_user("LoadError", messages_get("EmptyError"));
+ fclose(fp);
+ return 0;
+ }
+
+ fclose(fp);
+
+ if (line[strlen(line) - 1] == '\n')
+ line[strlen(line) - 1] = '\0';
+
+ url = strdup(line);
+ if (!url) {
+ ro_warn_user("NoMemory", 0);
+ return 0;
+ }
+
+ return url;
+}
+
+
+/**
+ * Parse an IEURL file.
+ *
+ * \param file_name file to read
+ * \return URL from file, or 0 on error and error reported
+ */
+static char *ro_gui_ieurl_file_parse(const char *file_name)
+{
+ char line[400];
+ char *url = 0;
+ FILE *fp;
+
+ fp = fopen(file_name, "r");
+ if (!fp) {
+ LOG("fopen(\"%s\", \"r\"): %i: %s", file_name, errno, strerror(errno));
+ ro_warn_user("LoadError", strerror(errno));
+ return 0;
+ }
+
+ while (fgets(line, sizeof line, fp)) {
+ if (strncmp(line, "URL=", 4) == 0) {
+ if (line[strlen(line) - 1] == '\n')
+ line[strlen(line) - 1] = '\0';
+ url = strdup(line + 4);
+ if (!url) {
+ fclose(fp);
+ ro_warn_user("NoMemory", 0);
+ return 0;
+ }
+ break;
+ }
+ }
+ if (ferror(fp)) {
+ LOG("fgets: %i: %s", errno, strerror(errno));
+ ro_warn_user("LoadError", strerror(errno));
+ fclose(fp);
+ return 0;
+ }
+
+ fclose(fp);
+
+ if (!url)
+ ro_warn_user("URIError", 0);
+
+ return url;
+}
+
+
+/**
+ * Handle Message_DataOpen (double-click on file in the Filer).
+ *
+ * \param message The wimp message to open.
+ */
+static void ro_msg_dataopen(wimp_message *message)
+{
+ int file_type = message->data.data_xfer.file_type;
+ char *url = 0;
+ os_error *oserror;
+ nsurl *urlns;
+ nserror error;
+ size_t len;
+
+ switch (file_type) {
+ case 0xb28: /* ANT URL file */
+ url = ro_gui_url_file_parse(message->data.data_xfer.file_name);
+ error = nsurl_create(url, &urlns);
+ free(url);
+ break;
+
+ case 0xfaf: /* HTML file */
+ error = netsurf_path_to_nsurl(message->data.data_xfer.file_name,
+ &urlns);
+ break;
+
+ case 0x1ba: /* IEURL file */
+ url = ro_gui_ieurl_file_parse(message->
+ data.data_xfer.file_name);
+ error = nsurl_create(url, &urlns);
+ free(url);
+ break;
+
+ case 0x2000: /* application */
+ len = strlen(message->data.data_xfer.file_name);
+ if (len < 9 || strcmp(".!NetSurf",
+ message->data.data_xfer.file_name + len - 9))
+ return;
+
+ if (nsoption_charp(homepage_url) &&
+ nsoption_charp(homepage_url)[0]) {
+ error = nsurl_create(nsoption_charp(homepage_url),
+ &urlns);
+ } else {
+ error = nsurl_create(NETSURF_HOMEPAGE, &urlns);
+ }
+ break;
+
+ default:
+ return;
+ }
+
+ /* send DataLoadAck */
+ message->action = message_DATA_LOAD_ACK;
+ message->your_ref = message->my_ref;
+ oserror = xwimp_send_message(wimp_USER_MESSAGE, message, message->sender);
+ if (oserror) {
+ LOG("xwimp_send_message: 0x%x: %s", oserror->errnum, oserror->errmess);
+ ro_warn_user("WimpError", oserror->errmess);
+ return;
+ }
+
+ if (error != NSERROR_OK) {
+ ro_warn_user(messages_get_errorcode(error), 0);
+ return;
+ }
+
+ /* create a new window with the file */
+ error = browser_window_create(BW_CREATE_HISTORY,
+ urlns,
+ NULL,
+ NULL,
+ NULL);
+ nsurl_unref(urlns);
+ if (error != NSERROR_OK) {
+ ro_warn_user(messages_get_errorcode(error), 0);
+ }
+}
+
+
+/**
+ * Handle Message_DataLoad (file dragged in).
+ */
+static void ro_msg_dataload(wimp_message *message)
+{
+ int file_type = message->data.data_xfer.file_type;
+ char *urltxt = NULL;
+ char *title = NULL;
+ struct gui_window *g;
+ os_error *oserror;
+ nsurl *url;
+ nserror error;
+
+ g = ro_gui_window_lookup(message->data.data_xfer.w);
+ if (g) {
+ if (ro_gui_window_dataload(g, message))
+ return;
+ }
+ else {
+ g = ro_gui_toolbar_lookup(message->data.data_xfer.w);
+ if (g && ro_gui_toolbar_dataload(g, message))
+ return;
+ }
+
+ switch (file_type) {
+ case FILETYPE_ACORN_URI:
+ urltxt = ro_gui_uri_file_parse(message->data.data_xfer.file_name,
+ &title);
+ error = nsurl_create(urltxt, &url);
+ free(urltxt);
+ break;
+
+ case FILETYPE_ANT_URL:
+ urltxt = ro_gui_url_file_parse(message->data.data_xfer.file_name);
+ error = nsurl_create(urltxt, &url);
+ free(urltxt);
+ break;
+
+ case FILETYPE_IEURL:
+ urltxt = ro_gui_ieurl_file_parse(message->data.data_xfer.file_name);
+ error = nsurl_create(urltxt, &url);
+ free(urltxt);
+ break;
+
+ case FILETYPE_HTML:
+ case FILETYPE_JNG:
+ case FILETYPE_CSS:
+ case FILETYPE_MNG:
+ case FILETYPE_GIF:
+ case FILETYPE_BMP:
+ case FILETYPE_ICO:
+ case osfile_TYPE_DRAW:
+ case FILETYPE_PNG:
+ case FILETYPE_JPEG:
+ case osfile_TYPE_SPRITE:
+ case osfile_TYPE_TEXT:
+ case FILETYPE_ARTWORKS:
+ case FILETYPE_SVG:
+ /* display the actual file */
+ error = netsurf_path_to_nsurl(message->data.data_xfer.file_name, &url);
+ break;
+
+ default:
+ return;
+ }
+
+ /* report error to user */
+ if (error != NSERROR_OK) {
+ ro_warn_user(messages_get_errorcode(error), 0);
+ return;
+ }
+
+
+ if (g) {
+ error = browser_window_navigate(g->bw,
+ url,
+ NULL,
+ BW_NAVIGATE_HISTORY,
+ NULL,
+ NULL,
+ NULL);
+ } else {
+ error = browser_window_create(BW_CREATE_HISTORY,
+ url,
+ NULL,
+ NULL,
+ NULL);
+ }
+ nsurl_unref(url);
+ if (error != NSERROR_OK) {
+ ro_warn_user(messages_get_errorcode(error), 0);
+ }
+
+
+ /* send DataLoadAck */
+ message->action = message_DATA_LOAD_ACK;
+ message->your_ref = message->my_ref;
+ oserror = xwimp_send_message(wimp_USER_MESSAGE, message,
+ message->sender);
+ if (oserror) {
+ LOG("xwimp_send_message: 0x%x: %s", oserror->errnum, oserror->errmess);
+ ro_warn_user("WimpError", oserror->errmess);
+ return;
+ }
+
+}
+
+
+/**
+ * Ensure that the filename in a data transfer message is NULL terminated
+ * (some applications, especially BASIC programs use CR)
+ *
+ * \param message message to be corrected
+ */
+static void ro_msg_terminate_filename(wimp_full_message_data_xfer *message)
+{
+ const char *ep = (char*)message + message->size;
+ char *p = message->file_name;
+
+ if ((size_t)message->size >= sizeof(*message))
+ ep = (char*)message + sizeof(*message) - 1;
+
+ while (p < ep && *p >= ' ') p++;
+ *p = '\0';
+}
+
+
+/**
+ * Handle Message_DataSave
+ */
+static void ro_msg_datasave(wimp_message *message)
+{
+ wimp_full_message_data_xfer *dataxfer = (wimp_full_message_data_xfer*)message;
+
+ /* remove ghost caret if drag-and-drop protocol was used */
+// ro_gui_selection_drag_reset();
+
+ ro_msg_terminate_filename(dataxfer);
+
+ if (ro_gui_selection_prepare_paste_datasave(dataxfer))
+ return;
+
+ switch (dataxfer->file_type) {
+ case FILETYPE_ACORN_URI:
+ case FILETYPE_ANT_URL:
+ case FILETYPE_IEURL:
+ case FILETYPE_HTML:
+ case FILETYPE_JNG:
+ case FILETYPE_CSS:
+ case FILETYPE_MNG:
+ case FILETYPE_GIF:
+ case FILETYPE_BMP:
+ case FILETYPE_ICO:
+ case osfile_TYPE_DRAW:
+ case FILETYPE_PNG:
+ case FILETYPE_JPEG:
+ case osfile_TYPE_SPRITE:
+ case osfile_TYPE_TEXT:
+ case FILETYPE_ARTWORKS:
+ case FILETYPE_SVG: {
+ os_error *error;
+
+ dataxfer->your_ref = dataxfer->my_ref;
+ dataxfer->size = offsetof(wimp_full_message_data_xfer, file_name) + 16;
+ dataxfer->action = message_DATA_SAVE_ACK;
+ dataxfer->est_size = -1;
+ memcpy(dataxfer->file_name, "<Wimp$Scrap>", 13);
+
+ error = xwimp_send_message(wimp_USER_MESSAGE, (wimp_message*)dataxfer, message->sender);
+ if (error) {
+ LOG("xwimp_send_message: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+ }
+ break;
+ }
+}
+
+
+/**
+ * Handle Message_DataSaveAck.
+ */
+static void ro_msg_datasave_ack(wimp_message *message)
+{
+ ro_msg_terminate_filename((wimp_full_message_data_xfer*)message);
+
+ if (ro_print_ack(message))
+ return;
+
+ switch (gui_current_drag_type) {
+ case GUI_DRAG_DOWNLOAD_SAVE:
+ ro_gui_download_datasave_ack(message);
+ break;
+
+ case GUI_DRAG_SAVE:
+ ro_gui_save_datasave_ack(message);
+ gui_current_drag_type = GUI_DRAG_NONE;
+ break;
+
+ default:
+ break;
+ }
+
+ gui_current_drag_type = GUI_DRAG_NONE;
+}
+
+
+/**
+ * Handle PreQuit message
+ *
+ * \param message PreQuit message from Wimp
+ */
+static void ro_msg_prequit(wimp_message *message)
+{
+ if (!ro_gui_prequit()) {
+ os_error *error;
+
+ /* we're objecting to the close down */
+ message->your_ref = message->my_ref;
+ error = xwimp_send_message(wimp_USER_MESSAGE_ACKNOWLEDGE,
+ message, message->sender);
+ if (error) {
+ LOG("xwimp_send_message: 0x%x:%s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+ }
+}
+
+
+/**
+ * Handle SaveDesktop message.
+ *
+ * \param message SaveDesktop message from Wimp.
+ */
+static void ro_msg_save_desktop(wimp_message *message)
+{
+ os_error *error;
+
+ error = xosgbpb_writew(message->data.save_desktopw.file,
+ (const byte*)"Run ", 4, NULL);
+ if (!error) {
+ error = xosgbpb_writew(message->data.save_desktopw.file,
+ (const byte*)NETSURF_DIR, strlen(NETSURF_DIR), NULL);
+ if (!error)
+ error = xos_bputw('\n', message->data.save_desktopw.file);
+ }
+
+ if (error) {
+ LOG("xosgbpb_writew/xos_bputw: 0x%x:%s", error->errnum, error->errmess);
+ ro_warn_user("SaveError", error->errmess);
+
+ /* we must cancel the save by acknowledging the message */
+ message->your_ref = message->my_ref;
+ error = xwimp_send_message(wimp_USER_MESSAGE_ACKNOWLEDGE,
+ message, message->sender);
+ if (error) {
+ LOG("xwimp_send_message: 0x%x:%s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+ }
+}
+
+
+/**
+ * Handle WindowInfo message (part of the iconising protocol)
+ *
+ * \param message WindowInfo message from the Iconiser
+ */
+static void ro_msg_window_info(wimp_message *message)
+{
+ wimp_full_message_window_info *wi;
+ struct gui_window *g;
+
+ /* allow the user to turn off thumbnail icons */
+ if (!nsoption_bool(thumbnail_iconise))
+ return;
+
+ wi = (wimp_full_message_window_info*)message;
+ g = ro_gui_window_lookup(wi->w);
+
+ /* ic_<task name> will suffice for our other windows */
+ if (g) {
+ ro_gui_window_iconise(g, wi);
+ ro_gui_dialog_close_persistent(wi->w);
+ }
+}
+
+
+/**
+ * Get screen properties following a mode change.
+ */
+static void ro_gui_get_screen_properties(void)
+{
+ static const ns_os_vdu_var_list vars = {
+ os_MODEVAR_XWIND_LIMIT,
+ {
+ os_MODEVAR_YWIND_LIMIT,
+ os_MODEVAR_XEIG_FACTOR,
+ os_MODEVAR_YEIG_FACTOR,
+ os_VDUVAR_END_LIST
+ }
+ };
+ os_error *error;
+ int vals[4];
+
+ error = xos_read_vdu_variables(PTR_OS_VDU_VAR_LIST(&vars), vals);
+ if (error) {
+ LOG("xos_read_vdu_variables: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("MiscError", error->errmess);
+ return;
+ }
+ screen_info.width = (vals[0] + 1) << vals[2];
+ screen_info.height = (vals[1] + 1) << vals[3];
+}
+
+
+/**
+ * Warn the user if Inet$Resolvers is not set.
+ */
+static void ro_gui_check_resolvers(void)
+{
+ char *resolvers;
+ resolvers = getenv("Inet$Resolvers");
+ if (resolvers && resolvers[0]) {
+ LOG("Inet$Resolvers '%s'", resolvers);
+ } else {
+ LOG("Inet$Resolvers not set or empty");
+ ro_warn_user("Resolvers", 0);
+ }
+}
+
+
+/**
+ * Initialise the RISC OS specific GUI.
+ *
+ * \param argc The number of command line arguments.
+ * \param argv The string vector of command line arguments.
+ */
+static nserror gui_init(int argc, char** argv)
+{
+ struct {
+ void (*sigabrt)(int);
+ void (*sigfpe)(int);
+ void (*sigill)(int);
+ void (*sigint)(int);
+ void (*sigsegv)(int);
+ void (*sigterm)(int);
+ void (*sigoserror)(int);
+ } prev_sigs;
+ char path[40];
+ os_error *error;
+ int length;
+ char *nsdir_temp;
+ byte *base;
+ nsurl *url;
+ nserror ret;
+ bool open_window;
+
+ /* re-enable all FPU exceptions/traps except inexact operations,
+ * which we're not interested in, and underflow which is incorrectly
+ * raised when converting an exact value of 0 from double-precision
+ * to single-precision on FPEmulator v4.09-4.11 (MVFD F0,#0:MVFS F0,F0)
+ * - UnixLib disables all FP exceptions by default */
+
+ _FPU_SETCW(_FPU_IEEE & ~(_FPU_MASK_PM | _FPU_MASK_UM));
+
+ xhourglass_start(1);
+
+ /* read OS version for code that adapts to conform to the OS
+ * (remember that it's preferable to check for specific features
+ * being present) */
+ xos_byte(osbyte_IN_KEY, 0, 0xff, &os_version, NULL);
+
+ /* the first release version of the A9home OS is incapable of
+ plotting patterned lines (presumably a fault in the hw acceleration) */
+ if (!xosmodule_lookup("VideoHWSMI", NULL, NULL, &base, NULL, NULL)) {
+#if 0 // this fault still hasn't been fixed, so disable patterned lines for all versions until it has
+ const char *help = (char*)base + ((int*)base)[5];
+ while (*help > 9) help++;
+ while (*help == 9) help++;
+ if (!memcmp(help, "0.55", 4))
+#endif
+ ro_plot_patterned_lines = false;
+ }
+
+ /* Create our choices directories */
+ ro_gui_create_dirs();
+
+ /* Register exit and signal handlers */
+ atexit(ro_gui_cleanup);
+ prev_sigs.sigabrt = signal(SIGABRT, ro_gui_signal);
+ prev_sigs.sigfpe = signal(SIGFPE, ro_gui_signal);
+ prev_sigs.sigill = signal(SIGILL, ro_gui_signal);
+ prev_sigs.sigint = signal(SIGINT, ro_gui_signal);
+ prev_sigs.sigsegv = signal(SIGSEGV, ro_gui_signal);
+ prev_sigs.sigterm = signal(SIGTERM, ro_gui_signal);
+ prev_sigs.sigoserror = signal(SIGOSERROR, ro_gui_signal);
+
+ if (prev_sigs.sigabrt == SIG_ERR || prev_sigs.sigfpe == SIG_ERR ||
+ prev_sigs.sigill == SIG_ERR ||
+ prev_sigs.sigint == SIG_ERR ||
+ prev_sigs.sigsegv == SIG_ERR ||
+ prev_sigs.sigterm == SIG_ERR ||
+ prev_sigs.sigoserror == SIG_ERR)
+ die("Failed registering signal handlers");
+
+ /* Load in UI sprites */
+ gui_sprites = ro_gui_load_sprite_file("NetSurf:Resources.Sprites");
+ if (!gui_sprites)
+ die("Unable to load Sprites.");
+
+ /* Find NetSurf directory */
+ nsdir_temp = getenv("NetSurf$Dir");
+ if (!nsdir_temp)
+ die("Failed to locate NetSurf directory");
+ NETSURF_DIR = strdup(nsdir_temp);
+ if (!NETSURF_DIR)
+ die("Failed duplicating NetSurf directory string");
+
+ /* Initialise filename allocator */
+ filename_initialise();
+
+ /* Initialise save complete functionality */
+ save_complete_init();
+
+ /* Load in visited URLs and Cookies */
+ urldb_load(nsoption_charp(url_path));
+ urldb_load_cookies(nsoption_charp(cookie_file));
+
+ /* Initialise with the wimp */
+ error = xwimp_initialise(wimp_VERSION_RO38, task_name,
+ PTR_WIMP_MESSAGE_LIST(&task_messages), 0,
+ &task_handle);
+ if (error) {
+ LOG("xwimp_initialise: 0x%x: %s", error->errnum, error->errmess);
+ die(error->errmess);
+ }
+ /* Register message handlers */
+ ro_message_register_route(message_HELP_REQUEST,
+ ro_gui_interactive_help_request);
+ ro_message_register_route(message_DATA_OPEN,
+ ro_msg_dataopen);
+ ro_message_register_route(message_DATA_SAVE,
+ ro_msg_datasave);
+ ro_message_register_route(message_DATA_SAVE_ACK,
+ ro_msg_datasave_ack);
+ ro_message_register_route(message_PRE_QUIT,
+ ro_msg_prequit);
+ ro_message_register_route(message_SAVE_DESKTOP,
+ ro_msg_save_desktop);
+ ro_message_register_route(message_DRAGGING,
+ ro_gui_selection_dragging);
+ ro_message_register_route(message_DRAG_CLAIM,
+ ro_gui_selection_drag_claim);
+ ro_message_register_route(message_WINDOW_INFO,
+ ro_msg_window_info);
+
+ /* Initialise the font subsystem */
+ nsfont_init();
+
+ /* Initialise global information */
+ ro_gui_get_screen_properties();
+ ro_gui_wimp_get_desktop_font();
+
+ /* Issue a *Desktop to poke AcornURI into life */
+ if (getenv("NetSurf$Start_URI_Handler"))
+ xwimp_start_task("Desktop", 0);
+
+ /* Open the templates */
+ if ((length = snprintf(path, sizeof(path),
+ "NetSurf:Resources.%s.Templates",
+ nsoption_charp(language))) < 0 || length >= (int)sizeof(path))
+ die("Failed to locate Templates resource.");
+ error = xwimp_open_template(path);
+ if (error) {
+ LOG("xwimp_open_template failed: 0x%x: %s", error->errnum, error->errmess);
+ die(error->errmess);
+ }
+
+ ret = treeview_init(12);
+ if (ret != NSERROR_OK) {
+ die("Failed to initialise treeview");
+ }
+
+ /* Initialise themes before dialogs */
+ ro_gui_theme_initialise();
+
+ /* Initialise dialog windows (must be after UI sprites are loaded) */
+ ro_gui_dialog_init();
+
+ /* Initialise download window */
+ ro_gui_download_init();
+
+ /* Initialise menus */
+ ro_gui_menu_init();
+
+ /* Initialise query windows */
+ ro_gui_query_init();
+
+ /* Initialise the history subsystem */
+ ro_gui_history_init();
+
+ /* Initialise toolbars */
+ ro_toolbar_init();
+
+ /* Initialise url bar module */
+ ro_gui_url_bar_init();
+
+ /* Initialise browser windows */
+ ro_gui_window_initialise();
+
+ /* Done with the templates file */
+ wimp_close_template();
+
+ /* Create Iconbar icon and menus */
+ ro_gui_iconbar_initialise();
+
+ /* Finally, check Inet$Resolvers for sanity */
+ ro_gui_check_resolvers();
+
+ /* certificate verification window */
+ ro_gui_cert_postinitialise();
+
+ /* hotlist window */
+ ro_gui_hotlist_postinitialise();
+
+ /* global history window */
+ ro_gui_global_history_postinitialise();
+
+ /* cookies window */
+ ro_gui_cookies_postinitialise();
+
+ open_window = nsoption_bool(open_browser_at_startup);
+
+ /* parse command-line arguments */
+ if (argc == 2) {
+ LOG("parameters: '%s'", argv[1]);
+ /* this is needed for launching URI files */
+ if (strcasecmp(argv[1], "-nowin") == 0) {
+ return NSERROR_OK;
+ }
+ ret = nsurl_create(NETSURF_HOMEPAGE, &url);
+ }
+ else if (argc == 3) {
+ LOG("parameters: '%s' '%s'", argv[1], argv[2]);
+ open_window = true;
+
+ /* HTML files */
+ if (strcasecmp(argv[1], "-html") == 0) {
+ ret = netsurf_path_to_nsurl(argv[2], &url);
+ }
+ /* URL files */
+ else if (strcasecmp(argv[1], "-urlf") == 0) {
+ char *urlf = ro_gui_url_file_parse(argv[2]);
+ if (!urlf) {
+ LOG("allocation failed");
+ die("Insufficient memory for URL");
+ }
+ ret = nsurl_create(urlf, &url);
+ free(urlf);
+ }
+ /* ANT URL Load */
+ else if (strcasecmp(argv[1], "-url") == 0) {
+ ret = nsurl_create(argv[2], &url);
+ }
+ /* Unknown => exit here. */
+ else {
+ LOG("Unknown parameters: '%s' '%s'", argv[1], argv[2]);
+ return NSERROR_BAD_PARAMETER;
+ }
+ }
+ /* get user's homepage (if configured) */
+ else if (nsoption_charp(homepage_url) &&
+ nsoption_charp(homepage_url)[0]) {
+ ret = nsurl_create(nsoption_charp(homepage_url), &url);
+ }
+ /* default homepage */
+ else {
+ ret = nsurl_create(NETSURF_HOMEPAGE, &url);
+ }
+
+ /* check for url creation error */
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+
+ if (open_window) {
+ ret = browser_window_create(BW_CREATE_HISTORY,
+ url,
+ NULL,
+ NULL,
+ NULL);
+ }
+ nsurl_unref(url);
+
+ return ret;
+}
+
+
+/**
+ * Determine the default language to use.
+ *
+ * RISC OS has no standard way of determining which language the user prefers.
+ * We have to guess from the 'Country' setting.
+ */
+const char *ro_gui_default_language(void)
+{
+ char path[40];
+ const char *lang;
+ int country;
+ os_error *error;
+
+ /* choose a language from the configured country number */
+ error = xosbyte_read(osbyte_VAR_COUNTRY_NUMBER, &country);
+ if (error) {
+ LOG("xosbyte_read failed: 0x%x: %s", error->errnum, error->errmess);
+ country = 1;
+ }
+ switch (country) {
+ case 7: /* Germany */
+ case 30: /* Austria */
+ case 35: /* Switzerland (70% German-speaking) */
+ lang = "de";
+ break;
+ case 6: /* France */
+ case 18: /* Canada2 (French Canada?) */
+ lang = "fr";
+ break;
+ case 34: /* Netherlands */
+ lang = "nl";
+ break;
+ default:
+ lang = "en";
+ break;
+ }
+ sprintf(path, "NetSurf:Resources.%s", lang);
+ if (is_dir(path))
+ return lang;
+ return "en";
+}
+
+
+/**
+ * Create a nsurl from a RISC OS pathname.
+ *
+ * Perform the necessary operations on a path to generate a nsurl.
+ *
+ * @param[in] path The RISC OS pathname to convert.
+ * @param[out] url_out pointer to recive the nsurl, The returned url must be
+ * unreferenced by the caller.
+ * @return NSERROR_OK and the url is placed in \a url or error code on faliure.
+ */
+static nserror ro_path_to_nsurl(const char *path, struct nsurl **url_out)
+{
+ int spare;
+ char *canonical_path; /* canonicalised RISC OS path */
+ char *unix_path; /* unix path */
+ char *escurl;
+ os_error *error;
+ nserror ret;
+ int urllen;
+ char *url; /* resulting url */
+
+ /* calculate the canonical risc os path */
+ error = xosfscontrol_canonicalise_path(path, 0, 0, 0, 0, &spare);
+ if (error) {
+ LOG("xosfscontrol_canonicalise_path failed: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("PathToURL", error->errmess);
+ return NSERROR_NOT_FOUND;
+ }
+
+ canonical_path = malloc(1 - spare);
+ if (canonical_path == NULL) {
+ free(canonical_path);
+ return NSERROR_NOMEM;
+ }
+
+ error = xosfscontrol_canonicalise_path(path, canonical_path, 0, 0, 1 - spare, 0);
+ if (error) {
+ LOG("xosfscontrol_canonicalise_path failed: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("PathToURL", error->errmess);
+ free(canonical_path);
+ return NSERROR_NOT_FOUND;
+ }
+
+ /* create a unix path from the cananocal risc os one */
+ unix_path = __unixify(canonical_path, __RISCOSIFY_NO_REVERSE_SUFFIX, NULL, 0, 0);
+
+ if (unix_path == NULL) {
+ LOG("__unixify failed: %s", canonical_path);
+ free(canonical_path);
+ return NSERROR_BAD_PARAMETER;
+ }
+ free(canonical_path);
+
+ /* convert the unix path into a url */
+ urllen = strlen(unix_path) + FILE_SCHEME_PREFIX_LEN + 1;
+ url = malloc(urllen);
+ if (url == NULL) {
+ LOG("Unable to allocate url");
+ free(unix_path);
+ return NSERROR_NOMEM;
+ }
+
+ if (*unix_path == '/') {
+ snprintf(url, urllen, "%s%s", FILE_SCHEME_PREFIX, unix_path + 1);
+ } else {
+ snprintf(url, urllen, "%s%s", FILE_SCHEME_PREFIX, unix_path);
+ }
+ free(unix_path);
+
+ /* We don't want '/' to be escaped. */
+ ret = url_escape(url, FILE_SCHEME_PREFIX_LEN, false, "/", &escurl);
+ free(url);
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+
+ ret = nsurl_create(escurl, url_out);
+ free(escurl);
+
+ return ret;
+}
+
+
+/**
+ * Create a path from a nsurl using posix file handling.
+ *
+ * @param[in] url The url to encode.
+ * @param[out] path_out A string containing the result path which should
+ * be freed by the caller.
+ * @return NSERROR_OK and the path is written to \a path or error code
+ * on faliure.
+ */
+static nserror ro_nsurl_to_path(struct nsurl *url, char **path_out)
+{
+ lwc_string *urlpath;
+ char *unpath;
+ char *path;
+ bool match;
+ lwc_string *scheme;
+ nserror res;
+ char *r;
+
+ if ((url == NULL) || (path_out == NULL)) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ scheme = nsurl_get_component(url, NSURL_SCHEME);
+
+ if (lwc_string_caseless_isequal(scheme, corestring_lwc_file,
+ &match) != lwc_error_ok)
+ {
+ return NSERROR_BAD_PARAMETER;
+ }
+ lwc_string_unref(scheme);
+ if (match == false) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ urlpath = nsurl_get_component(url, NSURL_PATH);
+ if (urlpath == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ res = url_unescape(lwc_string_data(urlpath), &unpath);
+ lwc_string_unref(urlpath);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ /* RISC OS path should not be more than 100 characters longer */
+ path = malloc(strlen(unpath) + 100);
+ if (path == NULL) {
+ free(unpath);
+ return NSERROR_NOMEM;
+ }
+
+ r = __riscosify(unpath, 0, __RISCOSIFY_NO_SUFFIX,
+ path, strlen(unpath) + 100, 0);
+ free(unpath);
+ if (r == NULL) {
+ free(path);
+ return NSERROR_NOMEM;
+ }
+
+ *path_out = path;
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * Ensures output logging stream is correctly configured.
+ */
+static bool nslog_stream_configure(FILE *fptr)
+{
+ /* set log stream to be non-buffering */
+ setbuf(fptr, NULL);
+
+ return true;
+}
+
+
+/**
+ * Close down the gui (RISC OS).
+ */
+static void gui_quit(void)
+{
+ urldb_save_cookies(nsoption_charp(cookie_jar));
+ urldb_save(nsoption_charp(url_save));
+ ro_gui_window_quit();
+ ro_gui_global_history_destroy();
+ ro_gui_hotlist_destroy();
+ ro_gui_cookies_destroy();
+ ro_gui_saveas_quit();
+ ro_gui_url_bar_fini();
+ rufl_quit();
+ free(gui_sprites);
+ xwimp_close_down(task_handle);
+ xhourglass_off();
+}
+
+
+/**
+ * Handle Close_Window_Request events.
+ */
+static void ro_gui_close_window_request(wimp_close *close)
+{
+ if (ro_gui_alt_pressed())
+ ro_gui_window_close_all();
+ else {
+ if (ro_gui_wimp_event_close_window(close->w))
+ return;
+ ro_gui_dialog_close(close->w);
+ }
+}
+
+
+/**
+ * Handle key press paste callback.
+ */
+static void ro_gui_keypress_cb(void *pw)
+{
+ wimp_key *key = (wimp_key *) pw;
+
+ if (ro_gui_wimp_event_keypress(key) == false) {
+ os_error *error = xwimp_process_key(key->c);
+ if (error) {
+ LOG("xwimp_process_key: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+ }
+
+ free(key);
+}
+
+
+/**
+ * Handle gui keypress.
+ */
+static void ro_gui_keypress(wimp_key *key)
+{
+ if (key->c == wimp_KEY_ESCAPE &&
+ (gui_current_drag_type == GUI_DRAG_SAVE ||
+ gui_current_drag_type == GUI_DRAG_DOWNLOAD_SAVE)) {
+
+ /* Allow Escape key to be used for cancelling a drag
+ * save (easier than finding somewhere safe to abort
+ * the drag)
+ */
+ ro_gui_drag_box_cancel();
+ gui_current_drag_type = GUI_DRAG_NONE;
+ } else if (key->c == 22 /* Ctrl-V */) {
+ wimp_key *copy;
+
+ /* Must copy the keypress as it's on the stack */
+ copy = malloc(sizeof(wimp_key));
+ if (copy == NULL)
+ return;
+ memcpy(copy, key, sizeof(wimp_key));
+
+ ro_gui_selection_prepare_paste(key->w, ro_gui_keypress_cb, copy);
+ } else if (ro_gui_wimp_event_keypress(key) == false) {
+ os_error *error = xwimp_process_key(key->c);
+ if (error) {
+ LOG("xwimp_process_key: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+ }
+}
+
+
+/**
+ * Handle the three User_Message events.
+ */
+static void ro_gui_user_message(wimp_event_no event, wimp_message *message)
+{
+ /* attempt automatic routing */
+ if (ro_message_handle_message(event, message))
+ return;
+
+ switch (message->action) {
+ case message_DATA_LOAD:
+ ro_msg_terminate_filename((wimp_full_message_data_xfer*)message);
+
+ if (event == wimp_USER_MESSAGE_ACKNOWLEDGE) {
+ if (ro_print_current_window)
+ ro_print_dataload_bounce(message);
+ } else if (ro_gui_selection_prepare_paste_dataload(
+ (wimp_full_message_data_xfer *) message) == false) {
+ ro_msg_dataload(message);
+ }
+ break;
+
+ case message_DATA_LOAD_ACK:
+ if (ro_print_current_window)
+ ro_print_cleanup();
+ break;
+
+ case message_MENU_WARNING:
+ ro_gui_menu_warning((wimp_message_menu_warning *)
+ &message->data);
+ break;
+
+ case message_MENUS_DELETED:
+ ro_gui_menu_message_deleted((wimp_message_menus_deleted *)
+ &message->data);
+ break;
+
+ case message_CLAIM_ENTITY:
+ ro_gui_selection_claim_entity((wimp_full_message_claim_entity*)message);
+ break;
+
+ case message_DATA_REQUEST:
+ ro_gui_selection_data_request((wimp_full_message_data_request*)message);
+ break;
+
+ case message_MODE_CHANGE:
+ ro_gui_get_screen_properties();
+ rufl_invalidate_cache();
+ break;
+
+ case message_PALETTE_CHANGE:
+ break;
+
+ case message_FONT_CHANGED:
+ ro_gui_wimp_get_desktop_font();
+ break;
+
+ case message_URI_PROCESS:
+ if (event != wimp_USER_MESSAGE_ACKNOWLEDGE)
+ ro_uri_message_received(message);
+ break;
+ case message_URI_RETURN_RESULT:
+ ro_uri_bounce(message);
+ break;
+ case message_INET_SUITE_OPEN_URL:
+ if (event == wimp_USER_MESSAGE_ACKNOWLEDGE) {
+ ro_url_bounce(message);
+ }
+ else {
+ ro_url_message_received(message);
+ }
+ break;
+#ifdef WITH_PLUGIN
+ case message_PLUG_IN_OPENING:
+ plugin_opening(message);
+ break;
+ case message_PLUG_IN_CLOSED:
+ plugin_closed(message);
+ break;
+ case message_PLUG_IN_RESHAPE_REQUEST:
+ plugin_reshape_request(message);
+ break;
+ case message_PLUG_IN_FOCUS:
+ break;
+ case message_PLUG_IN_URL_ACCESS:
+ plugin_url_access(message);
+ break;
+ case message_PLUG_IN_STATUS:
+ plugin_status(message);
+ break;
+ case message_PLUG_IN_BUSY:
+ break;
+ case message_PLUG_IN_STREAM_NEW:
+ plugin_stream_new(message);
+ break;
+ case message_PLUG_IN_STREAM_WRITE:
+ break;
+ case message_PLUG_IN_STREAM_WRITTEN:
+ plugin_stream_written(message);
+ break;
+ case message_PLUG_IN_STREAM_DESTROY:
+ break;
+ case message_PLUG_IN_OPEN:
+ if (event == wimp_USER_MESSAGE_ACKNOWLEDGE)
+ plugin_open_msg(message);
+ break;
+ case message_PLUG_IN_CLOSE:
+ if (event == wimp_USER_MESSAGE_ACKNOWLEDGE)
+ plugin_close_msg(message);
+ break;
+ case message_PLUG_IN_RESHAPE:
+ case message_PLUG_IN_STREAM_AS_FILE:
+ case message_PLUG_IN_NOTIFY:
+ case message_PLUG_IN_ABORT:
+ case message_PLUG_IN_ACTION:
+ break;
+#endif
+ case message_PRINT_SAVE:
+ if (event == wimp_USER_MESSAGE_ACKNOWLEDGE)
+ ro_print_save_bounce(message);
+ break;
+ case message_PRINT_ERROR:
+ ro_print_error(message);
+ break;
+ case message_PRINT_TYPE_ODD:
+ ro_print_type_odd(message);
+ break;
+ case message_HOTLIST_CHANGED:
+ ro_gui_hotlist_add_cleanup();
+ break;
+ case message_QUIT:
+ riscos_done = true;
+ break;
+ }
+}
+
+
+/**
+ * Process a Wimp_Poll event.
+ *
+ * \param event wimp event number
+ * \param block parameter block
+ */
+static void ro_gui_handle_event(wimp_event_no event, wimp_block *block)
+{
+ switch (event) {
+ case wimp_NULL_REASON_CODE:
+ ro_gui_throb();
+ ro_mouse_poll();
+ break;
+
+ case wimp_REDRAW_WINDOW_REQUEST:
+ ro_gui_wimp_event_redraw_window(&block->redraw);
+ break;
+
+ case wimp_OPEN_WINDOW_REQUEST:
+ ro_gui_open_window_request(&block->open);
+ break;
+
+ case wimp_CLOSE_WINDOW_REQUEST:
+ ro_gui_close_window_request(&block->close);
+ break;
+
+ case wimp_POINTER_LEAVING_WINDOW:
+ ro_mouse_pointer_leaving_window(&block->leaving);
+ break;
+
+ case wimp_POINTER_ENTERING_WINDOW:
+ ro_gui_wimp_event_pointer_entering_window(&block->entering);
+ break;
+
+ case wimp_MOUSE_CLICK:
+ ro_gui_wimp_event_mouse_click(&block->pointer);
+ break;
+
+ case wimp_USER_DRAG_BOX:
+ ro_mouse_drag_end(&block->dragged);
+ break;
+
+ case wimp_KEY_PRESSED:
+ ro_gui_keypress(&(block->key));
+ break;
+
+ case wimp_MENU_SELECTION:
+ ro_gui_menu_selection(&(block->selection));
+ break;
+
+ /* Scroll requests fall back to a generic handler because we
+ * might get these events for any window from a scroll-wheel.
+ */
+
+ case wimp_SCROLL_REQUEST:
+ if (!ro_gui_wimp_event_scroll_window(&(block->scroll)))
+ ro_gui_scroll(&(block->scroll));
+ break;
+
+ case wimp_USER_MESSAGE:
+ case wimp_USER_MESSAGE_RECORDED:
+ case wimp_USER_MESSAGE_ACKNOWLEDGE:
+ ro_gui_user_message(event, &(block->message));
+ break;
+ }
+}
+
+
+/**
+ * Poll the RISC OS wimp for events.
+ */
+static void riscos_poll(void)
+{
+ wimp_event_no event;
+ wimp_block block;
+ const wimp_poll_flags mask = wimp_MASK_LOSE | wimp_MASK_GAIN | wimp_SAVE_FP;
+ os_t track_poll_offset;
+
+ /* Poll wimp. */
+ xhourglass_off();
+ track_poll_offset = ro_mouse_poll_interval();
+ if (sched_active || (track_poll_offset > 0)) {
+ os_t t = os_read_monotonic_time();
+
+ if (track_poll_offset > 0) {
+ t += track_poll_offset;
+ } else {
+ t += 10;
+ }
+
+ if (sched_active && (sched_time - t) < 0) {
+ t = sched_time;
+ }
+
+ event = wimp_poll_idle(mask, &block, t, 0);
+ } else {
+ event = wimp_poll(wimp_MASK_NULL | mask, &block, 0);
+ }
+
+ xhourglass_on();
+ gui_last_poll = clock();
+ ro_gui_handle_event(event, &block);
+
+ /* Only run scheduled callbacks on a null poll
+ * We cannot do this in the null event handler, as that may be called
+ * from gui_multitask(). Scheduled callbacks must only be run from the
+ * top-level.
+ */
+ if (event == wimp_NULL_REASON_CODE) {
+ schedule_run();
+ }
+
+ ro_gui_window_update_boxes();
+}
+
+
+/**
+ * Handle Open_Window_Request events.
+ */
+void ro_gui_open_window_request(wimp_open *open)
+{
+ os_error *error;
+
+ if (ro_gui_wimp_event_open_window(open))
+ return;
+
+ error = xwimp_open_window(open);
+ if (error) {
+ LOG("xwimp_open_window: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+}
+
+
+/**
+ * source bounce callback.
+ */
+static void ro_gui_view_source_bounce(wimp_message *message)
+{
+ char *filename;
+ os_error *error;
+ char command[256];
+
+ /* run the file as text */
+ filename = ((wimp_full_message_data_xfer *)message)->file_name;
+ sprintf(command, "@RunType_FFF %s", filename);
+ error = xwimp_start_task(command, 0);
+ if (error) {
+ LOG("xwimp_start_task failed: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+}
+
+
+/**
+ * Send the source of a content to a text editor.
+ */
+void ro_gui_view_source(hlcache_handle *c)
+{
+ os_error *error;
+ char *temp_name;
+ wimp_full_message_data_xfer message;
+ int objtype;
+ bool done = false;
+
+ const char *source_data;
+ unsigned long source_size;
+
+ if (!c) {
+ ro_warn_user("MiscError", "No document source");
+ return;
+ }
+
+ source_data = content_get_source_data(c, &source_size);
+
+ if (!source_data) {
+ ro_warn_user("MiscError", "No document source");
+ return;
+ }
+
+ /* try to load local files directly. */
+ if (netsurf_nsurl_to_path(hlcache_handle_get_url(c), &temp_name) == NSERROR_OK) {
+ error = xosfile_read_no_path(temp_name, &objtype, 0, 0, 0, 0);
+ if ((!error) && (objtype == osfile_IS_FILE)) {
+ snprintf(message.file_name, 212, "%s", temp_name);
+ message.file_name[211] = '\0';
+ done = true;
+ }
+ free(temp_name);
+ }
+ if (!done) {
+ /* We cannot release the requested filename until after it
+ * has finished being used. As we can't easily find out when
+ * this is, we simply don't bother releasing it and simply
+ * allow it to be re-used next time NetSurf is started. The
+ * memory overhead from doing this is under 1 byte per
+ * filename. */
+ char *r;
+ char full_name[256];
+ const char *filename = filename_request();
+ if (!filename) {
+ ro_warn_user("NoMemory", 0);
+ return;
+ }
+
+ snprintf(full_name, 256, "%s/%s", TEMP_FILENAME_PREFIX,
+ filename);
+ full_name[255] = '\0';
+ r = __riscosify(full_name, 0, __RISCOSIFY_NO_SUFFIX,
+ message.file_name, 212, 0);
+ if (r == 0) {
+ LOG("__riscosify failed");
+ return;
+ }
+ message.file_name[211] = '\0';
+
+ error = xosfile_save_stamped(message.file_name,
+ ro_content_filetype(c),
+ (byte *) source_data,
+ (byte *) source_data + source_size);
+ if (error) {
+ LOG("xosfile_save_stamped failed: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("MiscError", error->errmess);
+ return;
+ }
+ }
+
+ /* begin the DataOpen protocol */
+ message.your_ref = 0;
+ message.size = 44 + ((strlen(message.file_name) + 4) & (~3u));
+ message.action = message_DATA_OPEN;
+ message.w = 0;
+ message.i = 0;
+ message.pos.x = 0;
+ message.pos.y = 0;
+ message.est_size = 0;
+ message.file_type = 0xfff;
+ ro_message_send_message(wimp_USER_MESSAGE_RECORDED,
+ (wimp_message*)&message, 0,
+ ro_gui_view_source_bounce);
+}
+
+
+/**
+ * Broadcast an URL that we can't handle.
+ */
+static nserror gui_launch_url(struct nsurl *url)
+{
+ /* Try ant broadcast */
+ ro_url_broadcast(nsurl_access(url));
+ return NSERROR_OK;
+}
+
+
+/**
+ * Choose the language to use.
+ */
+static void ro_gui_choose_language(void)
+{
+ /* if option_language exists and is valid, use that */
+ if (nsoption_charp(language)) {
+ char path[40];
+ if (2 < strlen(nsoption_charp(language)))
+ nsoption_charp(language)[2] = 0;
+ sprintf(path, "NetSurf:Resources.%s", nsoption_charp(language));
+
+ if (is_dir(path)) {
+ nsoption_setnull_charp(accept_language,
+ strdup(nsoption_charp(language)));
+ return;
+ }
+ nsoption_set_charp(language, NULL);
+ }
+
+ nsoption_set_charp(language, strdup(ro_gui_default_language()));
+ if (nsoption_charp(language) == NULL)
+ die("Out of memory");
+ nsoption_set_charp(accept_language, strdup(nsoption_charp(language)));
+ if (nsoption_charp(accept_language) == NULL)
+ die("Out of memory");
+}
+
+
+/**
+ * Display a warning for a serious problem (eg memory exhaustion).
+ *
+ * \param warning message key for warning message
+ * \param detail additional message, or 0
+ */
+nserror ro_warn_user(const char *warning, const char *detail)
+{
+ LOG("%s %s", warning, detail);
+
+ if (dialog_warning) {
+ char warn_buffer[300];
+ snprintf(warn_buffer, sizeof warn_buffer, "%s %s",
+ messages_get(warning),
+ detail ? detail : "");
+ warn_buffer[sizeof warn_buffer - 1] = 0;
+ ro_gui_set_icon_string(dialog_warning, ICON_WARNING_MESSAGE,
+ warn_buffer, true);
+ xwimp_set_icon_state(dialog_warning, ICON_WARNING_HELP,
+ wimp_ICON_DELETED, wimp_ICON_DELETED);
+ ro_gui_dialog_open(dialog_warning);
+ xos_bell();
+ } else {
+ /* probably haven't initialised (properly), use a
+ non-multitasking error box */
+ os_error error;
+ snprintf(error.errmess, sizeof error.errmess, "%s %s",
+ messages_get(warning),
+ detail ? detail : "");
+ error.errmess[sizeof error.errmess - 1] = 0;
+ xwimp_report_error_by_category(&error,
+ wimp_ERROR_BOX_OK_ICON |
+ wimp_ERROR_BOX_GIVEN_CATEGORY |
+ wimp_ERROR_BOX_CATEGORY_ERROR <<
+ wimp_ERROR_BOX_CATEGORY_SHIFT,
+ "NetSurf", "!netsurf",
+ (osspriteop_area *) 1, 0, 0);
+ }
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * Display an error and exit.
+ *
+ * Should only be used during initialisation.
+ */
+void die(const char * const error)
+{
+ os_error warn_error;
+
+ LOG("%s", error);
+
+ warn_error.errnum = 1; /* \todo: reasonable ? */
+ strncpy(warn_error.errmess, messages_get(error),
+ sizeof(warn_error.errmess)-1);
+ warn_error.errmess[sizeof(warn_error.errmess)-1] = '\0';
+ xwimp_report_error_by_category(&warn_error,
+ wimp_ERROR_BOX_OK_ICON |
+ wimp_ERROR_BOX_GIVEN_CATEGORY |
+ wimp_ERROR_BOX_CATEGORY_ERROR <<
+ wimp_ERROR_BOX_CATEGORY_SHIFT,
+ "NetSurf", "!netsurf",
+ (osspriteop_area *) 1, 0, 0);
+ exit(EXIT_FAILURE);
+}
+
+
+/**
+ * Test whether it's okay to shutdown, prompting the user if not.
+ *
+ * \return true iff it's okay to shutdown immediately
+ */
+bool ro_gui_prequit(void)
+{
+ return ro_gui_download_prequit();
+}
+
+
+/**
+ * Generate a riscos path from one or more component elemnts.
+ *
+ * Constructs a complete path element from passed components. The
+ * second (and subsequent) components have a slash substituted for all
+ * riscos directory separators.
+ *
+ * If a string is allocated it must be freed by the caller.
+ *
+ * @param[in,out] str pointer to string pointer if this is NULL enough
+ * storage will be allocated for the complete path.
+ * @param[in,out] size The size of the space available if \a str not
+ * NULL on input and if not NULL set to the total
+ * output length on output.
+ * @param[in] nelm The number of elements.
+ * @param[in] ap The elements of the path as string pointers.
+ * @return NSERROR_OK and the complete path is written to str
+ * or error code on faliure.
+ */
+static nserror riscos_mkpath(char **str, size_t *size, size_t nelm, va_list ap)
+{
+ const char *elm[16];
+ size_t elm_len[16];
+ size_t elm_idx;
+ char *fname;
+ size_t fname_len = 0;
+ char *curp;
+ size_t idx;
+
+ /* check the parameters are all sensible */
+ if ((nelm == 0) || (nelm > 16)) {
+ return NSERROR_BAD_PARAMETER;
+ }
+ if ((*str != NULL) && (size == NULL)) {
+ /* if the caller is providing the buffer they must say
+ * how much space is available.
+ */
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ /* calculate how much storage we need for the complete path
+ * with all the elements.
+ */
+ for (elm_idx = 0; elm_idx < nelm; elm_idx++) {
+ elm[elm_idx] = va_arg(ap, const char *);
+ /* check the argument is not NULL */
+ if (elm[elm_idx] == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+ elm_len[elm_idx] = strlen(elm[elm_idx]);
+ fname_len += elm_len[elm_idx];
+ }
+ fname_len += nelm; /* allow for separators and terminator */
+
+ /* ensure there is enough space */
+ fname = *str;
+ if (fname != NULL) {
+ if (fname_len > *size) {
+ return NSERROR_NOSPACE;
+ }
+ } else {
+ fname = malloc(fname_len);
+ if (fname == NULL) {
+ return NSERROR_NOMEM;
+ }
+ }
+
+ /* copy the elements in with directory separator */
+ curp = fname;
+
+ /* first element is not altered */
+ memmove(curp, elm[0], elm_len[0]);
+ curp += elm_len[0];
+ /* ensure there is a delimiter */
+ if (curp[-1] != DIR_SEP) {
+ *curp = DIR_SEP;
+ curp++;
+ }
+
+ /* subsequent elemnts have slashes substituted with directory
+ * separators.
+ */
+ for (elm_idx = 1; elm_idx < nelm; elm_idx++) {
+ for (idx = 0; idx < elm_len[elm_idx]; idx++) {
+ if (elm[elm_idx][idx] == DIR_SEP) {
+ *curp = '/';
+ } else {
+ *curp = elm[elm_idx][idx];
+ }
+ curp++;
+ }
+ *curp = DIR_SEP;
+ curp++;
+ }
+ curp[-1] = 0; /* NULL terminate */
+
+ assert((curp - fname) <= (int)fname_len);
+
+ *str = fname;
+ if (size != NULL) {
+ *size = fname_len;
+ }
+
+ return NSERROR_OK;
+
+}
+
+
+/**
+ * Get the basename of a file using posix path handling.
+ *
+ * This gets the last element of a path and returns it. The returned
+ * element has all forward slashes translated into riscos directory
+ * separators.
+ *
+ * @param[in] path The path to extract the name from.
+ * @param[in,out] str Pointer to string pointer if this is NULL enough
+ * storage will be allocated for the path element.
+ * @param[in,out] size The size of the space available if \a
+ * str not NULL on input and set to the total
+ * output length on output.
+ * @return NSERROR_OK and the complete path is written to str
+ * or error code on faliure.
+ */
+static nserror riscos_basename(const char *path, char **str, size_t *size)
+{
+ const char *leafname;
+ char *fname;
+ char *temp;
+
+ if (path == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ leafname = strrchr(path, DIR_SEP);
+ if (!leafname) {
+ leafname = path;
+ } else {
+ leafname += 1;
+ }
+
+ fname = strdup(leafname);
+ if (fname == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ /** @todo check this leafname translation is actually required */
+ /* and s/\//\./g */
+ for (temp = fname; *temp != 0; temp++) {
+ if (*temp == '/') {
+ *temp = DIR_SEP;
+ }
+ }
+
+ *str = fname;
+ if (size != NULL) {
+ *size = strlen(fname);
+ }
+ return NSERROR_OK;
+}
+
+
+/**
+ * Ensure that all directory elements needed to store a filename exist.
+ *
+ * Given a path of x.y.z directories x and x.y will be created.
+ *
+ * @param fname The filename to ensure the path to exists.
+ * @return NSERROR_OK on success or error code on failure.
+ */
+static nserror riscos_mkdir_all(const char *fname)
+{
+ char *dname;
+ char *cur;
+
+ dname = strdup(fname);
+
+ cur = dname;
+ while ((cur = strchr(cur, '.'))) {
+ *cur = '\0';
+ xosfile_create_dir(dname, 0);
+ *cur++ = '.';
+ }
+
+ free(dname);
+
+ return NSERROR_OK;
+}
+
+/**
+ * Find screen size in OS units.
+ */
+void ro_gui_screen_size(int *width, int *height)
+{
+ *width = screen_info.width;
+ *height = screen_info.height;
+}
+
+
+/**
+ * Send the debug dump of a content to a text editor.
+ */
+void ro_gui_dump_browser_window(struct browser_window *bw)
+{
+ os_error *error;
+
+ /* open file for dump */
+ FILE *stream = fopen("<Wimp$ScrapDir>.WWW.NetSurf.dump", "w");
+ if (!stream) {
+ LOG("fopen: errno %i", errno);
+ ro_warn_user("SaveError", strerror(errno));
+ return;
+ }
+
+ browser_window_debug_dump(bw, stream, CONTENT_DEBUG_RENDER);
+
+ fclose(stream);
+
+ /* launch file in editor */
+ error = xwimp_start_task("Filer_Run <Wimp$ScrapDir>.WWW.NetSurf.dump",
+ 0);
+ if (error) {
+ LOG("xwimp_start_task failed: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+}
+
+
+static struct gui_file_table riscos_file_table = {
+ .mkpath = riscos_mkpath,
+ .basename = riscos_basename,
+ .nsurl_to_path = ro_nsurl_to_path,
+ .path_to_nsurl = ro_path_to_nsurl,
+ .mkdir_all = riscos_mkdir_all,
+};
+
+static struct gui_fetch_table riscos_fetch_table = {
+ .filetype = fetch_filetype,
+
+ .get_resource_url = gui_get_resource_url,
+ .mimetype = fetch_mimetype,
+};
+
+static struct gui_misc_table riscos_misc_table = {
+ .schedule = riscos_schedule,
+ .warning = ro_warn_user,
+
+ .quit = gui_quit,
+ .launch_url = gui_launch_url,
+ .cert_verify = gui_cert_verify,
+ .login = gui_401login_open,
+};
+
+
+static char *get_cachepath(void)
+{
+ char *cachedir;
+ char *cachepath = NULL;
+ nserror ret;
+
+ cachedir = getenv("Cache$Dir");
+ if ((cachedir == NULL) || (cachedir[0] == 0)) {
+ LOG("cachedir was null");
+ return NULL;
+ }
+ ret = netsurf_mkpath(&cachepath, NULL, 2, cachedir, "NetSurf");
+ if (ret != NSERROR_OK) {
+ return NULL;
+ }
+ return cachepath;
+}
+
+/**
+ * Normal entry point from RISC OS.
+ */
+int main(int argc, char** argv)
+{
+ char *cachepath;
+ char path[40];
+ int length;
+ os_var_type type;
+ int used = -1; /* slightly better with older OSLib versions */
+ os_error *error;
+ nserror ret;
+ struct netsurf_table riscos_table = {
+ .misc = &riscos_misc_table,
+ .window = riscos_window_table,
+ .clipboard = riscos_clipboard_table,
+ .download = riscos_download_table,
+ .fetch = &riscos_fetch_table,
+ .file = &riscos_file_table,
+ .utf8 = riscos_utf8_table,
+ .search = riscos_search_table,
+ .llcache = filesystem_llcache_table,
+ .bitmap = riscos_bitmap_table,
+ .layout = riscos_layout_table,
+ };
+
+ ret = netsurf_register(&riscos_table);
+ if (ret != NSERROR_OK) {
+ die("NetSurf operation table failed registration");
+ }
+
+ /* Consult NetSurf$Logging environment variable to decide if logging
+ * is required. */
+ error = xos_read_var_val_size("NetSurf$Logging", 0, os_VARTYPE_STRING,
+ &used, NULL, &type);
+ if (error != NULL || type != os_VARTYPE_STRING || used != -2) {
+ verbose_log = true;
+ } else {
+ char logging_env[2];
+ error = xos_read_var_val("NetSurf$Logging", logging_env,
+ sizeof(logging_env), 0, os_VARTYPE_STRING,
+ &used, NULL, &type);
+ if (error != NULL || logging_env[0] != '0') {
+ verbose_log = true;
+ } else {
+ verbose_log = false;
+ }
+ }
+
+ /* initialise logging. Not fatal if it fails but not much we
+ * can do about it either.
+ */
+ nslog_init(nslog_stream_configure, &argc, argv);
+
+ /* user options setup */
+ ret = nsoption_init(set_defaults, &nsoptions, &nsoptions_default);
+ if (ret != NSERROR_OK) {
+ die("Options failed to initialise");
+ }
+ nsoption_read("NetSurf:Choices", NULL);
+ nsoption_commandline(&argc, argv, NULL);
+
+ /* Choose the interface language to use */
+ ro_gui_choose_language();
+
+ /* select language-specific Messages */
+ if (((length = snprintf(path,
+ sizeof(path),
+ "NetSurf:Resources.%s.Messages",
+ nsoption_charp(language))) < 0) ||
+ (length >= (int)sizeof(path))) {
+ die("Failed to locate Messages resource.");
+ }
+
+ /* initialise messages */
+ messages_add_from_file(path);
+
+ /* obtain cache path */
+ cachepath = get_cachepath();
+
+ /* common initialisation */
+ ret = netsurf_init(cachepath);
+ free(cachepath);
+ if (ret != NSERROR_OK) {
+ die("NetSurf failed to initialise core");
+ }
+
+ artworks_init();
+ draw_init();
+ sprite_init();
+
+ /* Load some extra RISC OS specific Messages */
+ messages_add_from_file("NetSurf:Resources.LangNames");
+
+ ret = gui_init(argc, argv);
+ if (ret != NSERROR_OK) {
+ ro_warn_user(messages_get_errorcode(ret), 0);
+ }
+
+ while (!riscos_done) {
+ riscos_poll();
+ }
+
+ netsurf_exit();
+
+ return 0;
+}
diff --git a/frontends/riscos/gui.h b/frontends/riscos/gui.h
new file mode 100644
index 000000000..624f9e2fb
--- /dev/null
+++ b/frontends/riscos/gui.h
@@ -0,0 +1,271 @@
+/*
+ * Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
+ * Copyright 2004 James Bursa <bursa@users.sourceforge.net>
+ * Copyright 2004 Andrew Timmins <atimmins@blueyonder.co.uk>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _NETSURF_RISCOS_GUI_H_
+#define _NETSURF_RISCOS_GUI_H_
+
+#include <oslib/wimp.h>
+
+#define RISCOS5 0xAA
+
+#define THUMBNAIL_WIDTH 100
+#define THUMBNAIL_HEIGHT 86
+
+/* The maximum size for user-editable URLs in the RISC OS GUI. */
+
+#define RO_GUI_MAX_URL_SIZE 2048
+
+extern int os_version;
+
+extern const char * NETSURF_DIR;
+
+struct toolbar;
+struct status_bar;
+struct plotter_table;
+struct gui_window;
+struct tree;
+struct node;
+struct history;
+struct css_style;
+struct ssl_cert_info;
+struct nsurl;
+struct hlcache_handle;
+
+enum gui_pointer_shape;
+
+extern wimp_t task_handle; /**< RISC OS wimp task handle. */
+
+extern wimp_w dialog_info, dialog_saveas, dialog_zoom, dialog_pageinfo,
+ dialog_objinfo, dialog_tooltip, dialog_warning, dialog_openurl,
+ dialog_folder, dialog_entry, dialog_url_complete,
+ dialog_search, dialog_print, dialog_theme_install;
+extern wimp_w current_menu_window;
+extern bool current_menu_open;
+extern wimp_menu *recent_search_menu; /* search.c */
+extern wimp_w history_window;
+extern bool gui_redraw_debug;
+extern osspriteop_area *gui_sprites;
+extern bool dialog_folder_add, dialog_entry_add, hotlist_insert;
+extern bool print_active, print_text_black;
+extern bool no_font_blending;
+
+typedef enum { GUI_DRAG_NONE, GUI_DRAG_DOWNLOAD_SAVE, GUI_DRAG_SAVE }
+ ro_gui_drag_type;
+
+extern ro_gui_drag_type gui_current_drag_type;
+
+extern bool riscos_done;
+
+/** RISC OS data for a browser window. */
+struct gui_window {
+ /** Associated platform-independent browser window data. */
+ struct browser_window *bw;
+
+ struct toolbar *toolbar; /**< Toolbar, or 0 if not present. */
+ struct status_bar *status_bar; /**< Status bar, or 0 if not present. */
+
+ wimp_w window; /**< RISC OS window handle. */
+
+ int old_width; /**< Width when last opened / os units. */
+ int old_height; /**< Height when last opened / os units. */
+ bool update_extent; /**< Update the extent on next opening */
+ bool active; /**< Whether the throbber should be active */
+
+ char title[256]; /**< Buffer for window title. */
+
+ int iconise_icon; /**< ID number of icon when window is iconised */
+
+ char validation[12]; /**< Validation string for colours */
+
+ float scale; /**< Browser window scale */
+
+ /** Options. */
+ struct {
+ bool buffer_animations; /**< Use screen buffering for animations. */
+ bool buffer_everything; /**< Use screen buffering for everything. */
+ } option;
+
+ struct gui_window *prev; /**< Previous in linked list. */
+ struct gui_window *next; /**< Next in linked list. */
+};
+
+
+extern struct gui_window *ro_gui_current_redraw_gui;
+
+
+/* in gui.c */
+void ro_gui_open_window_request(wimp_open *open);
+void ro_gui_screen_size(int *width, int *height);
+void ro_gui_view_source(struct hlcache_handle *c);
+void ro_gui_dump_browser_window(struct browser_window *bw);
+void ro_gui_drag_box_start(wimp_pointer *pointer);
+bool ro_gui_prequit(void);
+const char *ro_gui_default_language(void);
+nserror ro_warn_user(const char *warning, const char *detail);
+
+/**
+ * Cause an abnormal program termination.
+ *
+ * \note This never returns and is intended to terminate without any cleanup.
+ *
+ * \param error The message to display to the user.
+ */
+void die(const char * const error) __attribute__ ((noreturn));
+
+/* in download.c */
+void ro_gui_download_init(void);
+void ro_gui_download_datasave_ack(wimp_message *message);
+bool ro_gui_download_prequit(void);
+extern struct gui_download_table *riscos_download_table;
+
+/* in 401login.c */
+void ro_gui_401login_init(void);
+void gui_401login_open(struct nsurl *url, const char *realm,
+ nserror (*cb)(bool proceed, void *pw), void *cbpw);
+
+/* in window.c */
+void ro_gui_window_set_scale(struct gui_window *g, float scale);
+bool ro_gui_window_dataload(struct gui_window *g, wimp_message *message);
+void ro_gui_window_mouse_at(wimp_pointer *pointer, void *data);
+void ro_gui_window_iconise(struct gui_window *g,
+ wimp_full_message_window_info *wi);
+bool ro_gui_toolbar_dataload(struct gui_window *g, wimp_message *message);
+void ro_gui_window_redraw_all(void);
+void ro_gui_window_update_boxes(void);
+void ro_gui_window_quit(void);
+/* void ro_gui_window_close_all(void); */
+#define ro_gui_window_close_all ro_gui_window_quit /* no need for a separate fn */
+void ro_gui_throb(void);
+void ro_gui_window_default_options(struct gui_window *gui);
+struct gui_window *ro_gui_window_lookup(wimp_w window);
+struct gui_window *ro_gui_toolbar_lookup(wimp_w window);
+bool ro_gui_window_to_window_pos(struct gui_window *g, int x, int y,
+ os_coord *pos);
+bool ro_gui_window_to_screen_pos(struct gui_window *g, int x, int y,
+ os_coord *pos);
+enum browser_mouse_state ro_gui_mouse_click_state(wimp_mouse_state buttons,
+ wimp_icon_flags type);
+enum browser_mouse_state ro_gui_mouse_drag_state(wimp_mouse_state buttons,
+ wimp_icon_flags type);
+bool ro_gui_shift_pressed(void);
+bool ro_gui_ctrl_pressed(void);
+bool ro_gui_alt_pressed(void);
+void gui_window_set_pointer(struct gui_window *g, enum gui_pointer_shape shape);
+
+/* in history.c */
+void ro_gui_history_init(void);
+void ro_gui_history_open(struct gui_window *g, bool pointer);
+
+/* in schedule.c */
+extern bool sched_active;
+extern os_t sched_time;
+
+/**
+ * Process events up to current time.
+ */
+bool schedule_run(void);
+
+/**
+ * Schedule a callback.
+ *
+ * \param t interval before the callback should be made in ms
+ * \param callback callback function
+ * \param p user parameter, passed to callback function
+ *
+ * The callback function will be called as soon as possible after t ms have
+ * passed.
+ */
+nserror riscos_schedule(int t, void (*callback)(void *p), void *p);
+
+/* in search.c */
+void ro_gui_search_init(void);
+void ro_gui_search_prepare(struct browser_window *g);
+struct gui_search_table *riscos_search_table;
+
+/* in print.c */
+void ro_gui_print_init(void);
+void ro_gui_print_prepare(struct gui_window *g);
+
+/* in plotters.c */
+extern const struct plotter_table ro_plotters;
+extern int ro_plot_origin_x;
+extern int ro_plot_origin_y;
+
+/* in theme_install.c */
+bool ro_gui_theme_install_apply(wimp_w w);
+
+/* in sslcert.c */
+void gui_cert_verify(struct nsurl *url,
+ const struct ssl_cert_info *certs, unsigned long num,
+ nserror (*cb)(bool proceed, void *pw), void *cbpw);
+
+/* icon numbers */
+#define ICON_STATUS_RESIZE 0
+#define ICON_STATUS_TEXT 1
+
+#define ICON_SAVE_ICON 0
+#define ICON_SAVE_PATH 1
+#define ICON_SAVE_OK 2
+#define ICON_SAVE_CANCEL 3
+
+#define ICON_PAGEINFO_TITLE 0
+#define ICON_PAGEINFO_URL 1
+#define ICON_PAGEINFO_ENC 2
+#define ICON_PAGEINFO_TYPE 3
+#define ICON_PAGEINFO_ICON 4
+
+#define ICON_OBJINFO_URL 0
+#define ICON_OBJINFO_TARGET 1
+#define ICON_OBJINFO_TYPE 2
+#define ICON_OBJINFO_ICON 3
+
+#define ICON_WARNING_MESSAGE 0
+#define ICON_WARNING_CONTINUE 1
+#define ICON_WARNING_HELP 2
+
+#define ICON_SEARCH_TEXT 0
+#define ICON_SEARCH_CASE_SENSITIVE 1
+#define ICON_SEARCH_FIND_NEXT 2
+#define ICON_SEARCH_FIND_PREV 3
+#define ICON_SEARCH_CANCEL 4
+#define ICON_SEARCH_STATUS 5
+#define ICON_SEARCH_MENU 8
+#define ICON_SEARCH_SHOW_ALL 9
+
+#define ICON_THEME_INSTALL_MESSAGE 0
+#define ICON_THEME_INSTALL_INSTALL 1
+#define ICON_THEME_INSTALL_CANCEL 2
+
+#define ICON_OPENURL_URL 1
+#define ICON_OPENURL_CANCEL 2
+#define ICON_OPENURL_OPEN 3
+#define ICON_OPENURL_MENU 4
+
+#define ICON_ENTRY_NAME 1
+#define ICON_ENTRY_URL 3
+#define ICON_ENTRY_CANCEL 4
+#define ICON_ENTRY_OK 5
+#define ICON_ENTRY_RECENT 6
+
+#define ICON_FOLDER_NAME 1
+#define ICON_FOLDER_CANCEL 2
+#define ICON_FOLDER_OK 3
+
+#endif
diff --git a/frontends/riscos/gui/button_bar.c b/frontends/riscos/gui/button_bar.c
new file mode 100644
index 000000000..6ecd7cffa
--- /dev/null
+++ b/frontends/riscos/gui/button_bar.c
@@ -0,0 +1,1229 @@
+/*
+ * Copyright 2004, 2005 Richard Wilson <info@tinct.net>
+ * Copyright 2011 Stephen Fryatt <stevef@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Button bars (implementation).
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <oslib/dragasprite.h>
+#include <oslib/os.h>
+#include <oslib/osspriteop.h>
+#include <oslib/wimp.h>
+#include <oslib/wimpspriteop.h>
+
+#include "utils/log.h"
+
+#include "riscos/gui/button_bar.h"
+#include "riscos/gui.h"
+#include "riscos/mouse.h"
+#include "riscos/theme.h"
+#include "riscos/wimp.h"
+
+#define BUTTONBAR_SPRITE_NAME_LENGTH 12
+#define BUTTONBAR_VALIDATION_LENGTH 40
+
+struct button_bar_button {
+ wimp_i icon;
+ bool shaded;
+ bool separator;
+
+ button_bar_action select_action;
+ button_bar_action adjust_action;
+
+ int x_pos, y_pos;
+ int x_size, y_size;
+
+ char sprite[BUTTONBAR_SPRITE_NAME_LENGTH];
+ char validation[BUTTONBAR_VALIDATION_LENGTH];
+ char opt_key;
+ const char *help_suffix;
+
+ struct button_bar_button *bar_next;
+ struct button_bar_button *next;
+};
+
+
+struct button_bar {
+ /** The applied theme (or NULL to use the default) */
+ struct theme_descriptor *theme;
+
+ /** The widget dimensions. */
+ int x_min, y_min;
+ int separator_width;
+ int vertical_offset;
+
+ bool separators;
+
+ /** The window details and bar position. */
+ wimp_w window;
+ os_box extent;
+ osspriteop_area *sprites;
+ int background;
+
+ bool hidden;
+
+ bool edit;
+ struct button_bar *edit_target;
+ struct button_bar *edit_source;
+ void (*edit_refresh)(void *);
+ void *edit_client_data;
+
+ /** The list of all the defined buttons. */
+
+ struct button_bar_button *buttons;
+
+ /** The list of the buttons in the current bar. */
+
+ struct button_bar_button *bar;
+};
+
+static char null_text_string[] = "";
+static char separator_name[] = "separator";
+
+static struct button_bar *drag_start = NULL;
+static char drag_opt = '\0';
+static bool drag_separator = false;
+
+/*
+ * Private function prototypes.
+ */
+
+static bool ro_gui_button_bar_place_buttons(struct button_bar *button_bar);
+static bool ro_gui_button_bar_icon_update(struct button_bar *button_bar);
+static bool ro_gui_button_bar_icon_resize(struct button_bar *button_bar);
+static void ro_gui_button_bar_drag_end(wimp_dragged *drag, void *data);
+static void ro_gui_button_bar_sync_editors(struct button_bar *target,
+ struct button_bar *source);
+static struct button_bar_button *ro_gui_button_bar_find_icon(
+ struct button_bar *button_bar, wimp_i icon);
+static struct button_bar_button *ro_gui_button_bar_find_opt_key(
+ struct button_bar *button_bar, char opt_key);
+static struct button_bar_button *ro_gui_button_bar_find_action(
+ struct button_bar *button_bar, button_bar_action action);
+static struct button_bar_button *ro_gui_button_bar_find_coords(
+ struct button_bar *button_bar, os_coord pos,
+ bool *separator, bool *right);
+
+/* This is an exported interface documented in button_bar.h */
+
+struct button_bar *ro_gui_button_bar_create(struct theme_descriptor *theme,
+ const struct button_bar_buttons buttons[])
+{
+ struct button_bar *button_bar;
+ struct button_bar_button *icon, *new_icon;
+ int def;
+
+ /* Allocate memory. */
+
+ button_bar = malloc(sizeof(struct button_bar));
+ if (button_bar == NULL) {
+ LOG("No memory for malloc()");
+ return NULL;
+ }
+
+ /* Set up default parameters. */
+
+ button_bar->theme = theme;
+ button_bar->sprites = ro_gui_theme_get_sprites(theme);
+ button_bar->background = wimp_COLOUR_VERY_LIGHT_GREY;
+
+ button_bar->x_min = -1;
+ button_bar->y_min = -1;
+ button_bar->separator_width = 0;
+ button_bar->vertical_offset = 0;
+
+ button_bar->separators = false;
+
+ button_bar->window = NULL;
+
+ button_bar->hidden = false;
+
+ button_bar->edit = false;
+ button_bar->edit_target = NULL;
+ button_bar->edit_source = NULL;
+ button_bar->edit_refresh = NULL;
+ button_bar->edit_client_data = NULL;
+
+ button_bar->buttons = NULL;
+
+ /* Process the button icon definitions */
+
+ icon = NULL;
+
+ for (def = 0; buttons[def].icon != NULL; def++) {
+ new_icon = malloc(sizeof(struct button_bar_button));
+ if (new_icon == NULL) {
+ break;
+ }
+
+ if (icon == NULL) {
+ button_bar->buttons = new_icon;
+ button_bar->bar = new_icon;
+ } else {
+ icon->next = new_icon;
+ icon->bar_next = new_icon;
+ }
+ icon = new_icon;
+ icon->next = NULL;
+ icon->bar_next = NULL;
+
+ strncpy(icon->sprite, buttons[def].icon,
+ BUTTONBAR_SPRITE_NAME_LENGTH);
+ snprintf(icon->validation, BUTTONBAR_VALIDATION_LENGTH,
+ "R5;S%s,p%s", icon->sprite, icon->sprite);
+
+ icon->icon = -1;
+ icon->shaded = false;
+ icon->separator = false;
+
+ icon->select_action = buttons[def].select;
+ icon->adjust_action = buttons[def].adjust;
+ icon->opt_key = buttons[def].opt_key;
+ icon->help_suffix = buttons[def].help;
+ }
+
+ /* Add a separator after the last entry. This will be lost if the
+ * buttons are subsequently set, but is used for the edit source bar.
+ */
+
+ if (icon != NULL)
+ icon->separator = true;
+
+ return button_bar;
+}
+
+
+/* This is an exported interface documented in button_bar.h */
+
+bool ro_gui_button_bar_link_editor(struct button_bar *target,
+ struct button_bar *source, void (* refresh)(void *),
+ void *client_data)
+{
+ if (target == NULL || source == NULL ||
+ target->edit_target != NULL ||
+ target->edit_source != NULL ||
+ source->edit_target != NULL ||
+ source->edit_source != NULL)
+ return false;
+
+ target->edit_source = source;
+ source->edit_target = target;
+
+ /* Store the callback data in the editor bar. */
+
+ source->edit_refresh = refresh;
+ source->edit_client_data = client_data;
+
+ return true;
+}
+
+
+/* This is an exported interface documented in button_bar.h */
+
+bool ro_gui_button_bar_rebuild(struct button_bar *button_bar,
+ struct theme_descriptor *theme, theme_style style,
+ wimp_w window, bool edit)
+{
+ struct button_bar_button *button;
+ int height;
+
+
+ if (button_bar == NULL)
+ return false;
+
+ button_bar->theme = theme;
+ button_bar->window = window;
+ button_bar->sprites = ro_gui_theme_get_sprites(theme);
+ button_bar->background = ro_gui_theme_get_style_element(theme, style,
+ THEME_ELEMENT_BACKGROUND);
+
+ button_bar->edit = edit;
+
+ height = 0;
+ button_bar->separator_width = 16;
+ ro_gui_wimp_get_sprite_dimensions(button_bar->sprites, separator_name,
+ &button_bar->separator_width, &height);
+
+ /* If the separator height is 0, then either the sprite really is
+ * zero pixels high or the default was used as no sprite was found.
+ * Either way, we don't have a separator.
+ */
+
+ button_bar->separators = (height == 0) ? false : true;
+
+ button = button_bar->buttons;
+
+ while (button != NULL) {
+ button->x_size = 0;
+ button->y_size = 0;
+ button->icon = -1;
+
+ ro_gui_wimp_get_sprite_dimensions(button_bar->sprites,
+ button->sprite,
+ &button->x_size, &button->y_size);
+
+ button = button->next;
+ }
+
+ if (!ro_gui_button_bar_place_buttons(button_bar))
+ return false;
+
+ if (button_bar->edit && button_bar->edit_target != NULL)
+ ro_gui_button_bar_sync_editors(button_bar->edit_target,
+ button_bar);
+
+ return ro_gui_button_bar_icon_update(button_bar);
+}
+
+
+/* This is an exported interface documented in button_bar.h */
+
+bool ro_gui_button_bar_arrange_buttons(struct button_bar *button_bar,
+ char order[])
+{
+ struct button_bar_button *button, *new;
+ int i;
+
+ if (button_bar == NULL || order == NULL)
+ return false;
+
+ /* Delete any existing button arrangement. */
+
+ button_bar->bar = NULL;
+
+ for (button = button_bar->buttons; button != NULL;
+ button = button->next) {
+ button->bar_next = NULL;
+ button->separator = false;
+ }
+
+ /* Parse the config string and link up the new buttons. */
+
+ button = NULL;
+
+ for (i = 0; order[i] != '\0'; i++) {
+ if (order[i] != '|') {
+ new = ro_gui_button_bar_find_opt_key(button_bar,
+ order[i]);
+
+ if (new != NULL) {
+ if (button == NULL)
+ button_bar->bar = new;
+ else
+ button->bar_next = new;
+
+ button = new;
+ }
+ } else {
+ if (button != NULL)
+ button->separator = true;
+ }
+ }
+
+ if (!ro_gui_button_bar_place_buttons(button_bar))
+ return false;
+
+ return ro_gui_button_bar_place_buttons(button_bar);
+}
+
+/**
+ * Place the buttons on a button bar, taking into account the button arrangement
+ * and the current theme, and update the bar extent details.
+ *
+ * \param *button_bar The button bar to update.
+ * \return true if successful; else false.
+ */
+
+bool ro_gui_button_bar_place_buttons(struct button_bar *button_bar)
+{
+ struct button_bar_button *button;
+ int x_pos, y_pos, height;
+
+ if (button_bar == NULL)
+ return false;
+
+ button = button_bar->bar;
+ x_pos = 0;
+ y_pos = 0;
+ height = 0;
+
+ while (button != NULL) {
+ button->x_pos = x_pos;
+ button->y_pos = y_pos;
+
+ x_pos += button->x_size;
+ if (button->separator)
+ x_pos += button_bar->separator_width;
+
+ if (button->y_size > height)
+ height = button->y_size;
+
+ button = button->bar_next;
+ }
+
+ button_bar->x_min = x_pos;
+ button_bar->y_min = height;
+
+ return true;
+}
+
+
+/* This is an exported interface documented in button_bar.h */
+
+void ro_gui_button_bar_destroy(struct button_bar *button_bar)
+{
+ struct button_bar_button *button;
+
+ if (button_bar == NULL)
+ return;
+
+ /* Free the button definitions. */
+
+ while (button_bar->buttons != NULL) {
+ button = button_bar->buttons;
+ button_bar->buttons = button->next;
+ free(button);
+ }
+
+ free(button_bar);
+}
+
+
+/* This is an exported interface documented in button_bar.h */
+
+bool ro_gui_button_bar_get_dims(struct button_bar *button_bar,
+ int *width, int *height)
+{
+ if (button_bar == NULL)
+ return false;
+
+ if (button_bar->x_min != -1 && button_bar->y_min != -1) {
+ if (width != NULL)
+ *width = button_bar->x_min;
+ if (height != NULL)
+ *height = button_bar->y_min;
+
+ return true;
+ }
+
+ return false;
+}
+
+
+/* This is an exported interface documented in button_bar.h */
+
+bool ro_gui_button_bar_set_extent(struct button_bar *button_bar,
+ int x0, int y0, int x1, int y1)
+{
+ if (button_bar == NULL)
+ return false;
+
+ if ((x1 - x0) < button_bar->x_min || (y1 - y0) < button_bar->y_min)
+ return false;
+
+ if (button_bar->extent.x0 == x0 && button_bar->extent.y0 == y0 &&
+ button_bar->extent.x1 == x1 &&
+ button_bar->extent.y1 == y1)
+ return true;
+
+ /* Redraw the relevant bits of the toolbar. We can't optimise for
+ * stretching the X-extent, as this probably means the button
+ * arrangement has changed which necessitates a full redraw anyway.
+ */
+
+ if (button_bar->window != NULL) {
+ xwimp_force_redraw(button_bar->window,
+ button_bar->extent.x0, button_bar->extent.y0,
+ button_bar->extent.x1, button_bar->extent.y1);
+ xwimp_force_redraw(button_bar->window, x0, y0, x1, y1);
+ }
+
+ button_bar->extent.x0 = x0;
+ button_bar->extent.y0 = y0;
+ button_bar->extent.x1 = x1;
+ button_bar->extent.y1 = y1;
+
+ if ((y1 - y0) > button_bar->y_min)
+ button_bar->vertical_offset =
+ ((y1 - y0) - button_bar->y_min) / 2;
+ else
+ button_bar->vertical_offset = 0;
+
+ return ro_gui_button_bar_icon_resize(button_bar);
+}
+
+
+/**
+ * Update the icons on a button bar, creating or deleting them from the window
+ * as necessary.
+ */
+
+bool ro_gui_button_bar_icon_update(struct button_bar *button_bar)
+{
+ wimp_icon_create icon;
+ struct button_bar_button *button, *b;
+ os_error *error;
+
+
+ if (button_bar == NULL || button_bar->window == NULL)
+ return (button_bar == NULL) ? false : true;
+
+ button = button_bar->buttons;
+
+ while (button != NULL) {
+ bool on_bar = false;
+
+ /* Check if the icon is currently on the bar. */
+
+ for (b = button_bar->bar; b != NULL; b = b->bar_next) {
+ if (b == button) {
+ on_bar = true;
+ break;
+ }
+ }
+
+ if (on_bar && !button_bar->hidden && button->icon == -1) {
+ icon.w = button_bar->window;
+ icon.icon.extent.x0 = 0;
+ icon.icon.extent.y0 = 0;
+ icon.icon.extent.x1 = 0;
+ icon.icon.extent.y1 = 0;
+ icon.icon.flags = wimp_ICON_TEXT | wimp_ICON_SPRITE |
+ wimp_ICON_INDIRECTED |
+ wimp_ICON_HCENTRED |
+ wimp_ICON_VCENTRED |
+ (button_bar->background
+ << wimp_ICON_BG_COLOUR_SHIFT);
+ icon.icon.data.indirected_text.size = 1;
+
+ /* We don't actually shade buttons unless there's no
+ * editor active or this is the source bar.
+ */
+
+ if (button->shaded && (!button_bar->edit ||
+ button_bar->edit_target != NULL))
+ icon.icon.flags |= wimp_ICON_SHADED;
+
+ if (button_bar->edit)
+ icon.icon.flags |= (wimp_BUTTON_CLICK_DRAG <<
+ wimp_ICON_BUTTON_TYPE_SHIFT);
+ else
+ icon.icon.flags |= (wimp_BUTTON_CLICK <<
+ wimp_ICON_BUTTON_TYPE_SHIFT);
+
+ icon.icon.data.indirected_text.text = null_text_string;
+ icon.icon.data.indirected_text.validation =
+ button->validation;
+
+ error = xwimp_create_icon(&icon, &button->icon);
+ if (error) {
+ LOG("xwimp_create_icon: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ button->icon = -1;
+ return false;
+ }
+ } else if ((!on_bar || button_bar->hidden)
+ && button->icon != -1) {
+ error = xwimp_delete_icon(button_bar->window,
+ button->icon);
+ if (error != NULL) {
+ LOG("xwimp_delete_icon: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return false;
+ }
+
+ button->icon = -1;
+ }
+
+ button = button->next;
+ }
+
+ return ro_gui_button_bar_icon_resize(button_bar);
+}
+
+
+/**
+ * Position the icons in the button bar to take account of the currently
+ * configured extent.
+ *
+ * \param *button_bar The button bar to update.
+ * \return true if successful; else false.
+ */
+
+bool ro_gui_button_bar_icon_resize(struct button_bar *button_bar)
+{
+ os_error *error;
+ struct button_bar_button *button;
+
+ if (button_bar == NULL || button_bar->hidden)
+ return (button_bar == NULL) ? false : true;
+
+ /* Reposition all the icons. */
+
+ button = button_bar->bar;
+
+ while (button != NULL) {
+ if(button->icon != -1) {
+ error = xwimp_resize_icon(button_bar->window,
+ button->icon,
+ button_bar->extent.x0 + button->x_pos,
+ button_bar->extent.y0 +
+ button_bar->vertical_offset +
+ button->y_pos,
+ button_bar->extent.x0 + button->x_pos +
+ button->x_size,
+ button_bar->extent.y0 +
+ button_bar->vertical_offset +
+ button->y_pos +
+ button->y_size);
+ if (error != NULL) {
+ LOG("xwimp_resize_icon: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ button->icon = -1;
+ return false;
+ }
+ }
+
+ button = button->bar_next;
+ }
+
+ return true;
+}
+
+
+/* This is an exported interface documented in button_bar.h */
+
+bool ro_gui_button_bar_hide(struct button_bar *button_bar, bool hide)
+{
+ if (button_bar == NULL || button_bar->hidden == hide)
+ return (button_bar == NULL) ? false : true;
+
+ button_bar->hidden = hide;
+
+ return ro_gui_button_bar_icon_update(button_bar);
+}
+
+
+/* This is an exported interface documented in button_bar.h */
+
+bool ro_gui_button_bar_shade_button(struct button_bar *button_bar,
+ button_bar_action action, bool shaded)
+{
+ struct button_bar_button *button;
+
+ if (button_bar == NULL)
+ return false;
+
+ button = ro_gui_button_bar_find_action(button_bar, action);
+ if (button == NULL)
+ return false;
+
+ if (button->shaded == shaded)
+ return true;
+
+ button->shaded = shaded;
+
+ /* We don't actually shade buttons unless there's no editor active
+ * or this is the source bar.
+ */
+
+ if (button->icon != -1 &&
+ (!button_bar->edit || button_bar->edit_target != NULL))
+ ro_gui_set_icon_shaded_state(button_bar->window, button->icon,
+ shaded);
+
+ return true;
+}
+
+
+/* This is an exported interface documented in button_bar.h */
+
+void ro_gui_button_bar_redraw(struct button_bar *button_bar,
+ wimp_draw *redraw)
+{
+ wimp_icon icon;
+ struct button_bar_button *button;
+
+ /* Test for a valid button bar, and then check that the redraw box
+ * coincides with the bar's extent.
+ */
+
+ if (button_bar == NULL || button_bar->hidden ||
+ (redraw->clip.x0 - (redraw->box.x0 - redraw->xscroll))
+ > button_bar->extent.x1 ||
+ (redraw->clip.y0 - (redraw->box.y1 - redraw->yscroll))
+ > button_bar->extent.y1 ||
+ (redraw->clip.x1 - (redraw->box.x0 - redraw->xscroll))
+ < button_bar->extent.x0 ||
+ (redraw->clip.y1 - (redraw->box.y1 - redraw->yscroll))
+ < button_bar->extent.y0 ||
+ (!button_bar->edit && !button_bar->separators))
+ return;
+
+ icon.flags = wimp_ICON_SPRITE | wimp_ICON_INDIRECTED |
+ wimp_ICON_HCENTRED | wimp_ICON_VCENTRED;
+ if (button_bar->edit)
+ icon.flags |= wimp_ICON_BORDER | wimp_COLOUR_DARK_GREY <<
+ wimp_ICON_FG_COLOUR_SHIFT;
+ if (!button_bar->separators)
+ icon.flags |= wimp_ICON_FILLED | wimp_COLOUR_LIGHT_GREY <<
+ wimp_ICON_BG_COLOUR_SHIFT;
+ icon.data.indirected_sprite.id = (osspriteop_id) separator_name;
+ icon.data.indirected_sprite.area = button_bar->sprites;
+ icon.data.indirected_sprite.size = 12;
+ icon.extent.y0 = button_bar->extent.y0 + button_bar->vertical_offset;
+ icon.extent.y1 = icon.extent.y0 + button_bar->y_min;
+
+ for (button = button_bar->bar; button != NULL;
+ button = button->bar_next) {
+ if (button->separator) {
+ icon.extent.x0 = button_bar->extent.x0 +
+ button->x_pos + button->x_size;
+ icon.extent.x1 = icon.extent.x0 +
+ button_bar->separator_width;
+ xwimp_plot_icon(&icon);
+ }
+ }
+}
+
+
+/* This is an exported interface documented in button_bar.h */
+
+bool ro_gui_button_bar_click(struct button_bar *button_bar,
+ wimp_pointer *pointer, wimp_window_state *state,
+ button_bar_action *action)
+{
+ struct button_bar_button *button;
+ os_coord pos;
+ os_box box;
+
+ if (button_bar == NULL || button_bar->hidden)
+ return false;
+
+ /* Check that the click was within our part of the window. */
+
+ pos.x = pointer->pos.x - state->visible.x0 + state->xscroll;
+ pos.y = pointer->pos.y - state->visible.y1 + state->yscroll;
+
+ if (pos.x < button_bar->extent.x0 || pos.x > button_bar->extent.x1 ||
+ pos.y < button_bar->extent.y0 ||
+ pos.y > button_bar->extent.y1)
+ return false;
+
+ if (button_bar->edit && pointer->buttons == wimp_DRAG_SELECT) {
+ /* This is an editor click, so we need to check for drags on
+ * icons (buttons) and work area (separators).
+ */
+
+ button = ro_gui_button_bar_find_coords(button_bar, pos,
+ &drag_separator, NULL);
+
+ if (button != NULL && (!button->shaded || drag_separator ||
+ button_bar->edit_source != NULL)) {
+ char *sprite;
+ os_error *error;
+
+ drag_start = button_bar;
+ drag_opt = button->opt_key;
+
+ if (drag_separator) {
+ box.x0 = pointer->pos.x -
+ button_bar->separator_width / 2;
+ box.x1 = box.x0 + button_bar->separator_width;
+ sprite = separator_name;
+ } else {
+ box.x0 = pointer->pos.x - button->x_size / 2;
+ box.x1 = box.x0 + button->x_size;
+ sprite = button->sprite;
+ }
+
+ box.y0 = pointer->pos.y - button->y_size / 2;
+ box.y1 = box.y0 + button->y_size;
+
+ error = xdragasprite_start(dragasprite_HPOS_CENTRE |
+ dragasprite_VPOS_CENTRE |
+ dragasprite_BOUND_SPRITE |
+ dragasprite_BOUND_TO_WINDOW |
+ dragasprite_DROP_SHADOW,
+ button_bar->sprites,
+ sprite, &box, NULL);
+ if (error)
+ LOG("xdragasprite_start: 0x%x: %s", error->errnum, error->errmess);
+
+ ro_mouse_drag_start(ro_gui_button_bar_drag_end,
+ NULL, NULL, NULL);
+
+
+ return true;
+ }
+
+ } else if (!button_bar->edit && pointer->i != -1 &&
+ (pointer->buttons == wimp_CLICK_SELECT ||
+ pointer->buttons == wimp_CLICK_ADJUST)) {
+ /* This isn't an editor click, so we're only interested in
+ * Select or Adjust clicks that occur on physical icons.
+ */
+
+ button = ro_gui_button_bar_find_icon(button_bar, pointer->i);
+
+ if (button != NULL) {
+ if (action != NULL) {
+ switch (pointer->buttons) {
+ case wimp_CLICK_SELECT:
+ *action = button->select_action;
+ break;
+ case wimp_CLICK_ADJUST:
+ *action = button->adjust_action;
+ break;
+ default:
+ break;
+ }
+ }
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+/* This is an exported interface documented in button_bar.h */
+
+bool ro_gui_button_bar_help_suffix(struct button_bar *button_bar, wimp_i i,
+ os_coord *mouse, wimp_window_state *state,
+ wimp_mouse_state buttons, const char **suffix)
+{
+ os_coord pos;
+ struct button_bar_button *button;
+
+ if (button_bar == NULL || button_bar->hidden)
+ return false;
+
+ /* Check that the click was within our part of the window. */
+
+ pos.x = mouse->x - state->visible.x0 + state->xscroll;
+ pos.y = mouse->y - state->visible.y1 + state->yscroll;
+
+ if (pos.x < button_bar->extent.x0 || pos.x > button_bar->extent.x1 ||
+ pos.y < button_bar->extent.y0 ||
+ pos.y > button_bar->extent.y1)
+ return false;
+
+ /* Look up and return the help suffix assocuated with the button. */
+
+ button = ro_gui_button_bar_find_icon(button_bar, i);
+
+ if (button != NULL)
+ *suffix = button->help_suffix;
+ else
+ *suffix = "";
+
+ return true;
+}
+
+
+/**
+ * Terminate a drag event that was initiated by a button bar.
+ *
+ * \param *drag The drag event data.
+ * \param *data NULL data to satisfy callback syntax.
+ */
+
+void ro_gui_button_bar_drag_end(wimp_dragged *drag, void *data)
+{
+ struct button_bar *drag_end = NULL;
+ struct button_bar *source = NULL, *target = NULL;
+ struct button_bar_button *button, *drop, *previous;
+ bool right, separator;
+ wimp_window_state state;
+ wimp_pointer pointer;
+ os_coord pos;
+ os_error *error;
+
+ xdragasprite_stop();
+
+ if (drag_start == NULL)
+ return;
+
+ /* Sort out the window coordinates of the drag end. */
+
+ error = xwimp_get_pointer_info(&pointer);
+ if (error) {
+ LOG("xwimp_get_pointer_info: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ assert(pointer.w = drag_start->window);
+
+ state.w = drag_start->window;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ pos.x = pointer.pos.x - state.visible.x0 + state.xscroll;
+ pos.y = pointer.pos.y - state.visible.y1 + state.yscroll;
+
+ /* Work out the destination bar, and establish source and target. */
+
+ if (drag_start->edit_target != NULL) {
+ source = drag_start;
+ target = drag_start->edit_target;
+ if (pos.x >= target->extent.x0 && pos.x <= target->extent.x1 &&
+ pos.y >= target->extent.y0 &&
+ pos.y <= target->extent.y1)
+ drag_end = target;
+ } else if (drag_start->edit_source != NULL) {
+ source = drag_start->edit_source;
+ target = drag_start;
+ if (pos.x >= target->extent.x0 && pos.x <= target->extent.x1 &&
+ pos.y >= target->extent.y0 &&
+ pos.y <= target->extent.y1)
+ drag_end = target;
+ /* drag_end == source and drag_end == NULL are both equivalent
+ * as far as the following code are concerned, and we don't need
+ * to identify either case. */
+ }
+
+ button = ro_gui_button_bar_find_opt_key(target, drag_opt);
+ assert(button != NULL);
+
+ /* The drag finished in the target bar, so find out where. */
+
+ if (drag_end == target) {
+ drop = ro_gui_button_bar_find_coords(target, pos,
+ &separator, &right);
+ } else {
+ drop = NULL;
+ }
+
+ /* If the button is dropped on itself, there's no change and it's
+ * less messy to get out now.
+ */
+
+ if (drag_start == target && drag_end == target && button == drop) {
+ drag_start = NULL;
+ return;
+ }
+
+ /* The drag started in the target bar, so remove the dragged button. */
+
+ if (drag_start == target) {
+ if (drag_separator) {
+ button->separator = false;
+ } else if (target->bar == button) {
+ target->bar = button->bar_next;
+ } else {
+ for (previous = target->bar; previous != NULL &&
+ previous->bar_next != button;
+ previous = previous->bar_next);
+ assert(previous != NULL);
+ previous->bar_next = button->bar_next;
+ if (button->separator) // ??
+ previous->separator = true; // ??
+ }
+ }
+
+ /* The drag ended in the target bar, so add the dragged button in. */
+
+ if (drop != NULL) {
+ if (right) {
+ if (drag_separator) {
+ drop->separator = true;
+ } else {
+ button->bar_next = drop->bar_next;
+ drop->bar_next = button;
+ if (drop->separator && !separator) {
+ drop->separator = false;
+ button->separator = true;
+ } else {
+ button->separator = false;
+ }
+ }
+ } else if (target->bar == drop && !drag_separator) {
+ button->separator = false;
+ button->bar_next = target->bar;
+ target->bar = button;
+ } else if (target->bar != drop) {
+ for (previous = target->bar; previous != NULL &&
+ previous->bar_next != drop;
+ previous = previous->bar_next);
+ assert(previous != NULL);
+
+ if (drag_separator) {
+ previous->separator = true;
+ } else {
+ if (separator) {
+ previous->separator = false;
+ button->separator = true;
+ } else {
+ button->separator = false;
+ }
+ button->bar_next = previous->bar_next;
+ previous->bar_next = button;
+ }
+ }
+ }
+
+ /* Reposition the buttons and force our client to update. */
+
+ ro_gui_button_bar_place_buttons(target);
+ ro_gui_button_bar_icon_update(target);
+ ro_gui_button_bar_sync_editors(target, source);
+
+ xwimp_force_redraw(target->window,
+ target->extent.x0, target->extent.y0,
+ target->extent.x1, target->extent.y1);
+
+ if (source->edit_refresh != NULL)
+ source->edit_refresh(source->edit_client_data);
+
+ drag_start = NULL;
+}
+
+
+/**
+ * Synchronise the shading of a button bar editor source bar with the currently
+ * defined buttons in its target bar.
+ *
+ * \param *target The editor target bar.
+ * \param *source The editor source bar.
+ */
+
+void ro_gui_button_bar_sync_editors(struct button_bar *target,
+ struct button_bar *source)
+{
+ struct button_bar_button *sb, *tb;
+
+ if (source == NULL || target == NULL)
+ return;
+
+ /* Unshade all of the buttons in the source bar. */
+
+ for (sb = source->bar; sb != NULL; sb = sb->bar_next)
+ sb->shaded = false;
+
+ /* Step through the target bar and shade each corresponding
+ * button in the source.
+ */
+
+ for (tb = target->bar; tb != NULL; tb = tb->bar_next) {
+ sb = ro_gui_button_bar_find_opt_key(source, tb->opt_key);
+
+ if (sb != NULL)
+ sb->shaded = true;
+ }
+
+ /* Phyically shade the necessary buttons in the toolbar. */
+
+ for (sb = source->bar; sb != NULL; sb = sb->bar_next)
+ if (sb->icon != -1)
+ ro_gui_set_icon_shaded_state(source->window, sb->icon,
+ sb->shaded);
+}
+
+
+/* This is an exported interface documented in button_bar.h */
+
+char *ro_gui_button_bar_get_config(struct button_bar *button_bar)
+{
+ struct button_bar_button *button;
+ size_t size;
+ char *config;
+ int i;
+
+ if (button_bar == NULL)
+ return NULL;
+
+ for (size = 1, button = button_bar->bar; button != NULL;
+ button = button->bar_next) {
+ size++;
+ if (button->separator)
+ size++;
+ }
+
+ config = malloc(size);
+ if (config == NULL) {
+ LOG("No memory for malloc()");
+ ro_warn_user("NoMemory", 0);
+ return NULL;
+ }
+
+ for (i = 0, button = button_bar->bar; button != NULL;
+ button = button->bar_next) {
+ config[i++] = button->opt_key;
+ if (button->separator)
+ config[i++] = '|';
+ }
+
+ config[i] = '\0';
+
+ return config;
+}
+
+
+/**
+ * Find a button bar icon definition from an icon handle.
+ *
+ * \param *button_bar The button bar to use.
+ * \param icon The icon handle.
+ * \return Pointer to the button bar icon, or NULL.
+ */
+
+struct button_bar_button *ro_gui_button_bar_find_icon(
+ struct button_bar *button_bar, wimp_i icon)
+{
+ struct button_bar_button *button;
+
+ if (button_bar == NULL || icon == -1)
+ return NULL;
+
+ button = button_bar->buttons;
+
+ while (button != NULL && button->icon != icon)
+ button = button->next;
+
+ return button;
+}
+
+
+/**
+ * Find a button bar icon definition from an options key code.
+ *
+ * \param *button_bar The button bar to use.
+ * \param opt_key The option key character code.
+ * \return Pointer to the button bar icon, or NULL.
+ */
+
+struct button_bar_button *ro_gui_button_bar_find_opt_key(
+ struct button_bar *button_bar, char opt_key)
+{
+ struct button_bar_button *button;
+
+ if (button_bar == NULL)
+ return NULL;
+
+ button = button_bar->buttons;
+
+ while (button != NULL && button->opt_key != opt_key)
+ button = button->next;
+
+ return button;
+}
+
+
+/**
+ * Find a button bar icon definition from an action code.
+ *
+ * \param *button_bar The button bar to use.
+ * \param action The button action to find.
+ * \return Pointer to the button bar icon, or NULL.
+ */
+
+struct button_bar_button *ro_gui_button_bar_find_action(
+ struct button_bar *button_bar, button_bar_action action)
+{
+ struct button_bar_button *button;
+
+ if (button_bar == NULL)
+ return NULL;
+
+ button = button_bar->buttons;
+
+ while (button != NULL &&
+ button->select_action != action &&
+ button->adjust_action != action)
+ button = button->next;
+
+ return button;
+}
+
+
+/**
+ * Find a button bar icon definition from coordinates.
+ *
+ * \param *button_bar The button bar to use.
+ * \param pos The coordinates to find, work area relative.
+ * \param *separator Returns true if the associated separator was
+ * matched; else false.
+ * \param *right Returns true if the coordinates were in the
+ * right hand side of the target; else false.
+ * \return Pointer to the button bar icon, or NULL.
+ */
+
+struct button_bar_button *ro_gui_button_bar_find_coords(
+ struct button_bar *button_bar, os_coord pos,
+ bool *separator, bool *right)
+{
+ struct button_bar_button *button;
+
+ if (button_bar == NULL)
+ return NULL;
+
+ button = button_bar->bar;
+
+ while (button != NULL) {
+ /* Match button extents. */
+ int x0, y0, x1, y1;
+
+ x0 = button_bar->extent.x0 + button->x_pos;
+ y0 = button_bar->extent.y0 + button->y_pos;
+ x1 = x0 + button->x_size;
+ y1 = y0 + button->y_size;
+
+ if (pos.x > x0 && pos.y > y0 && pos.x < x1 && pos.y < y1) {
+ if (separator != NULL)
+ *separator = false;
+
+ if (right != NULL)
+ *right = (pos.x > x0 + button->x_size/2) ?
+ true : false;
+ return button;
+ }
+
+ x0 = x1;
+ x1 = x0 + button_bar->separator_width;
+
+ /* Match separator extents. */
+
+ if (pos.x > x0 && pos.y > y0 && pos.x < x1 && pos.y < y1 &&
+ button->separator) {
+ if (separator != NULL)
+ *separator = true;
+
+ if (right != NULL)
+ *right = (x0 + button_bar->separator_width/2) ?
+ true : false;
+ return button;
+ }
+
+ button = button->bar_next;
+ }
+
+ return NULL;
+}
+
diff --git a/frontends/riscos/gui/button_bar.h b/frontends/riscos/gui/button_bar.h
new file mode 100644
index 000000000..a1f7e8b9f
--- /dev/null
+++ b/frontends/riscos/gui/button_bar.h
@@ -0,0 +1,309 @@
+/*
+ * Copyright 2005 Richard Wilson <info@tinct.net>
+ * Copyright 2011 Stephen Fryatt <stevef@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Button bars (interface).
+ */
+
+#ifndef _NETSURF_RISCOS_BUTTONBAR_H_
+#define _NETSURF_RISCOS_BUTTONBAR_H_
+
+#include <stdbool.h>
+#include "riscos/theme.h"
+
+/* A list of possible toolbar actions. */
+
+typedef enum {
+ TOOLBAR_BUTTON_NONE = 0, /* Special case: no action */
+ TOOLBAR_BUTTON_BACK,
+ TOOLBAR_BUTTON_BACK_NEW,
+ TOOLBAR_BUTTON_UP,
+ TOOLBAR_BUTTON_UP_NEW,
+ TOOLBAR_BUTTON_FORWARD,
+ TOOLBAR_BUTTON_FORWARD_NEW,
+ TOOLBAR_BUTTON_STOP,
+ TOOLBAR_BUTTON_RELOAD,
+ TOOLBAR_BUTTON_RELOAD_ALL,
+ TOOLBAR_BUTTON_HOME,
+ TOOLBAR_BUTTON_HISTORY_LOCAL,
+ TOOLBAR_BUTTON_HISTORY_GLOBAL,
+ TOOLBAR_BUTTON_SAVE_SOURCE,
+ TOOLBAR_BUTTON_SAVE_COMPLETE,
+ TOOLBAR_BUTTON_PRINT,
+ TOOLBAR_BUTTON_BOOKMARK_OPEN,
+ TOOLBAR_BUTTON_BOOKMARK_ADD,
+ TOOLBAR_BUTTON_SCALE,
+ TOOLBAR_BUTTON_SEARCH,
+ TOOLBAR_BUTTON_DELETE,
+ TOOLBAR_BUTTON_EXPAND,
+ TOOLBAR_BUTTON_COLLAPSE,
+ TOOLBAR_BUTTON_OPEN,
+ TOOLBAR_BUTTON_CLOSE,
+ TOOLBAR_BUTTON_LAUNCH,
+ TOOLBAR_BUTTON_CREATE
+} button_bar_action;
+
+/* Button bar button source definitions.
+ *
+ * Help tokens are added to the help prefix for the given toolbar by the
+ * help system, and correspond to the hard-coded icon numbers that were
+ * assigned to the different buttons in the original toolbar implementation.
+ * If the Messages file can be updated, these can change to something more
+ * meaningful.
+ */
+
+struct button_bar_buttons {
+ const char *icon; /**< The sprite used for the icon. */
+ button_bar_action select; /**< The action for select clicks. */
+ button_bar_action adjust; /**< The action for Adjust clicks. */
+ const char opt_key; /**< The char used in option strings. */
+ const char *help; /**< The interactive help token. */
+};
+
+/* \TODO -- Move these to the correct modules.
+ */
+
+static const struct button_bar_buttons brower_toolbar_buttons[] = {
+ {"back", TOOLBAR_BUTTON_BACK, TOOLBAR_BUTTON_BACK_NEW, '0', "0"},
+ {"up", TOOLBAR_BUTTON_UP, TOOLBAR_BUTTON_UP_NEW, 'b', "11"},
+ {"forward", TOOLBAR_BUTTON_FORWARD, TOOLBAR_BUTTON_FORWARD_NEW, '1', "1"},
+ {"stop", TOOLBAR_BUTTON_STOP, TOOLBAR_BUTTON_NONE, '2', "2"},
+ {"reload", TOOLBAR_BUTTON_RELOAD, TOOLBAR_BUTTON_RELOAD_ALL, '3', "3"},
+ {"home", TOOLBAR_BUTTON_HOME, TOOLBAR_BUTTON_NONE, '4', "4"},
+ {"history", TOOLBAR_BUTTON_HISTORY_LOCAL, TOOLBAR_BUTTON_HISTORY_GLOBAL, '5', "5"},
+ {"save", TOOLBAR_BUTTON_SAVE_SOURCE, TOOLBAR_BUTTON_SAVE_COMPLETE, '6', "6"},
+ {"print", TOOLBAR_BUTTON_PRINT, TOOLBAR_BUTTON_NONE, '7', "7"},
+ {"hotlist", TOOLBAR_BUTTON_BOOKMARK_OPEN, TOOLBAR_BUTTON_BOOKMARK_ADD, '8', "8"},
+ {"scale", TOOLBAR_BUTTON_SCALE, TOOLBAR_BUTTON_NONE, '9', "9"},
+ {"search", TOOLBAR_BUTTON_SEARCH, TOOLBAR_BUTTON_NONE, 'a', "10"},
+ {NULL, TOOLBAR_BUTTON_NONE, TOOLBAR_BUTTON_NONE, '\0', ""}
+};
+
+static const struct button_bar_buttons cookies_toolbar_buttons[] = {
+ {"delete", TOOLBAR_BUTTON_DELETE, TOOLBAR_BUTTON_NONE, '0', "0"},
+ {"expand", TOOLBAR_BUTTON_EXPAND, TOOLBAR_BUTTON_COLLAPSE, '1', "1"},
+ {"open", TOOLBAR_BUTTON_OPEN, TOOLBAR_BUTTON_CLOSE, '2', "2"},
+ {NULL, TOOLBAR_BUTTON_NONE, TOOLBAR_BUTTON_NONE, '\0', ""}
+};
+
+static const struct button_bar_buttons global_history_toolbar_buttons[] = {
+ {"delete", TOOLBAR_BUTTON_DELETE, TOOLBAR_BUTTON_NONE, '0', "0"},
+ {"expand", TOOLBAR_BUTTON_EXPAND, TOOLBAR_BUTTON_COLLAPSE, '1', "1"},
+ {"open", TOOLBAR_BUTTON_OPEN, TOOLBAR_BUTTON_CLOSE, '2', "2"},
+ {"launch", TOOLBAR_BUTTON_LAUNCH, TOOLBAR_BUTTON_NONE, '3', "3"},
+ {NULL, TOOLBAR_BUTTON_NONE, TOOLBAR_BUTTON_NONE, '\0', ""}
+};
+
+static const struct button_bar_buttons hotlist_toolbar_buttons[] = {
+ {"delete", TOOLBAR_BUTTON_DELETE, TOOLBAR_BUTTON_NONE, '0', "0"},
+ {"expand", TOOLBAR_BUTTON_EXPAND, TOOLBAR_BUTTON_COLLAPSE, '1', "1"},
+ {"open", TOOLBAR_BUTTON_OPEN, TOOLBAR_BUTTON_CLOSE, '2', "2"},
+ {"launch", TOOLBAR_BUTTON_LAUNCH, TOOLBAR_BUTTON_NONE, '3', "3"},
+ {"create", TOOLBAR_BUTTON_CREATE, TOOLBAR_BUTTON_NONE, '4', "4"},
+ {NULL, TOOLBAR_BUTTON_NONE, TOOLBAR_BUTTON_NONE, '\0', ""}
+};
+
+struct button_bar;
+
+
+/**
+ * Create a new button bar widget.
+ *
+ * \param *theme The theme to apply (or NULL for the default).
+ * \param buttons[] An array of button definitions for the bar.
+ * \return A button bar handle, or NULL on failure.
+ */
+
+struct button_bar *ro_gui_button_bar_create(struct theme_descriptor *theme,
+ const struct button_bar_buttons buttons[]);
+
+
+/**
+ * Link two button bars together
+ *
+ * Join two button bars the target being the active bar, and the
+ * source being the editing bar used to supply valid buttons. The bars are
+ * checked to ensure that they are not already part of an edit pair, but are
+ * not checked for button-compatibility.
+ *
+ * \param target The target button bar.
+ * \param source The source button bar.
+ * \param refresh The refresh callback.
+ * \param client_data context passed to the refresh callback
+ * \return true if successful; else false.
+ */
+
+bool ro_gui_button_bar_link_editor(struct button_bar *target,
+ struct button_bar *source, void (* refresh)(void *),
+ void *client_data);
+
+/**
+ * Place a button bar into a toolbar window and initialise any theme-specific
+ * settings. Any previous incarnation of the bar will be forgotten: this
+ * is for use when a new toolbar is being created, or when a toolbar has been
+ * deleted and rebuilt following a theme change.
+ *
+ * \param *button_bar The button bar to rebuild.
+ * \param *theme The theme to apply (or NULL for current).
+ * \param style The theme style to apply.
+ * \param window The window that the bar is in.
+ * \param edit The edit mode of the button bar.
+ * \return true on success; else false.
+ */
+
+bool ro_gui_button_bar_rebuild(struct button_bar *button_bar,
+ struct theme_descriptor *theme, theme_style style,
+ wimp_w window, bool edit);
+
+
+/**
+ * Arrange buttons on a button bar, using an order string to specify the
+ * required button and separator layout.
+ *
+ * \param *button_bar The button bar to update.
+ * \param order[] The button order configuration string.
+ * \return true if successful; else false.
+ */
+
+bool ro_gui_button_bar_arrange_buttons(struct button_bar *button_bar,
+ char order[]);
+
+
+/**
+ * Destroy a button bar widget.
+ *
+ * \param *button_bar The button bar to destroy.
+ */
+
+void ro_gui_button_bar_destroy(struct button_bar *button_bar);
+
+
+/**
+ * Return the MINIMUM dimensions required by the button bar, in RO units,
+ * allowing for the current theme.
+ *
+ * \param *button_bar The button bar of interest.
+ * \param *width Return the required width.
+ * \param *height Return the required height.
+ * \return true if values are returned; else false.
+ */
+
+bool ro_gui_button_bar_get_dims(struct button_bar *button_bar,
+ int *width, int *height);
+
+
+/**
+ * Set or update the dimensions to be used by the button bar, in RO units.
+ * If these are greater than the minimum required, the button bar will fill
+ * the extended space; if less, the call will fail.
+ *
+ * \param *button_bar The button bar to update.
+ * \param x0 The minimum X window position.
+ * \param y0 The minimum Y window position.
+ * \param x1 The maximum X window position.
+ * \param y1 The maximum Y window position.
+ * \return true if size updated; else false.
+ */
+
+bool ro_gui_button_bar_set_extent(struct button_bar *button_bar,
+ int x0, int y0, int x1, int y1);
+
+
+/**
+ * Show or hide a button bar.
+ *
+ * \param *button_bar The button bar to hide.
+ * \param hide true to hide the bar; false to show it.
+ * \return true if successful; else false.
+ */
+
+bool ro_gui_button_bar_hide(struct button_bar *button_bar, bool hide);
+
+
+/**
+ * Shade or unshade a button in a bar corresponding to the given action.
+ *
+ * \param *button_bar The button bar to update.
+ * \param action The action to update.
+ * \param shaded true to shade the button; false to unshade.
+ * \return true if successful; else false.
+ */
+
+bool ro_gui_button_bar_shade_button(struct button_bar *button_bar,
+ button_bar_action action, bool shaded);
+
+
+/**
+ * Handle redraw event rectangles in a button bar.
+ *
+ * \param *button_bar The button bar to use.
+ * \param *redraw The Wimp redraw rectangle to process.
+ */
+
+void ro_gui_button_bar_redraw(struct button_bar *button_bar,
+ wimp_draw *redraw);
+
+
+/**
+ * Handle mouse clicks in a button bar.
+ *
+ * \param *button_bar The button bar to use.
+ * \param *pointer The Wimp mouse click event data.
+ * \param *state The toolbar window state.
+ * \param *action Returns the selected action, or
+ * TOOLBAR_BUTTON_NONE.
+ * \return true if the event was handled exclusively;
+ * else false.
+ */
+
+bool ro_gui_button_bar_click(struct button_bar *button_bar,
+ wimp_pointer *pointer, wimp_window_state *state,
+ button_bar_action *action);
+
+
+/**
+ * Translate mouse data into an interactive help message for a button bar.
+ *
+ * \param *button_bar The button bar to process.
+ * \param i The wimp icon under the pointer.
+ * \param *mouse The mouse position.
+ * \param *state The toolbar window state.
+ * \param buttons The mouse button state.
+ * \param **suffix Return a help token suffix, or "" for none.
+ * \return true if handled exclusively; else false.
+ */
+
+bool ro_gui_button_bar_help_suffix(struct button_bar *button_bar, wimp_i i,
+ os_coord *mouse, wimp_window_state *state,
+ wimp_mouse_state buttons, const char **suffix);
+
+
+/**
+ * Return a config string reflecting the configured order of buttons
+ * and spacers. The string is allocated with malloc(), and should be
+ * free()d after use.
+ *
+ * \param *button_bar The button bar of interest.
+ * \return Pointer to a config string, or NULL on failure.
+ */
+
+char *ro_gui_button_bar_get_config(struct button_bar *button_bar);
+
+#endif
+
diff --git a/frontends/riscos/gui/progress_bar.c b/frontends/riscos/gui/progress_bar.c
new file mode 100644
index 000000000..3ec6b3aa8
--- /dev/null
+++ b/frontends/riscos/gui/progress_bar.c
@@ -0,0 +1,535 @@
+/*
+ * Copyright 2006 Richard Wilson <info@tinct.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Progress bar (implementation).
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <string.h>
+#include "swis.h"
+#include "oslib/colourtrans.h"
+#include "oslib/os.h"
+#include "oslib/osspriteop.h"
+#include "oslib/wimp.h"
+#include "oslib/wimpspriteop.h"
+
+#include "desktop/plotters.h"
+#include "utils/log.h"
+#include "utils/utils.h"
+
+#include "riscos/gui.h"
+#include "riscos/tinct.h"
+#include "riscos/wimp_event.h"
+#include "riscos/gui/progress_bar.h"
+
+#define MARGIN 6
+
+struct progress_bar {
+ wimp_w w; /**< progress bar window handle */
+ unsigned int range; /**< progress bar range */
+ unsigned int value; /**< progress bar value */
+ char icon[13]; /**< current icon */
+ int offset; /**< progress bar rotation */
+ os_box visible; /**< progress bar position */
+ int icon_x0; /**< icon x0 */
+ int icon_y0; /**< icon y0 */
+ osspriteop_header *icon_img; /**< icon image */
+ bool animating; /**< progress bar is animating */
+ bool recalculate; /**< recalculation required */
+ int cur_width; /**< current calculated width */
+ int cur_height; /**< current calculated height */
+ bool icon_obscured; /**< icon is partially obscured */
+};
+
+static char progress_animation_sprite[] = "progress";
+static osspriteop_header *progress_icon;
+static unsigned int progress_width;
+static unsigned int progress_height;
+
+struct wimp_window_base progress_bar_definition = {
+ {0, 0, 1, 1},
+ 0,
+ 0,
+ wimp_TOP,
+ wimp_WINDOW_NEW_FORMAT | wimp_WINDOW_MOVEABLE | wimp_WINDOW_NO_BOUNDS,
+ 0xff,
+ wimp_COLOUR_LIGHT_GREY,
+ wimp_COLOUR_LIGHT_GREY,
+ wimp_COLOUR_VERY_LIGHT_GREY,
+ wimp_COLOUR_DARK_GREY,
+ wimp_COLOUR_MID_LIGHT_GREY,
+ wimp_COLOUR_CREAM,
+ wimp_WINDOW_NEVER3D | 0x16u /* RISC OS 5.03+ */,
+ {0, 0, 65535, 65535},
+ 0,
+ 0,
+ wimpspriteop_AREA,
+ 1,
+ 1,
+ {""},
+ 0
+};
+
+
+static void ro_gui_progress_bar_calculate(struct progress_bar *pb, int width,
+ int height);
+static void ro_gui_progress_bar_redraw(wimp_draw *redraw);
+static void ro_gui_progress_bar_redraw_window(wimp_draw *redraw,
+ struct progress_bar *pb);
+static void ro_gui_progress_bar_animate(void *p);
+
+
+/**
+ * Initialise the progress bar
+ *
+ * \param icons the sprite area to use for icons
+ */
+void ro_gui_progress_bar_init(osspriteop_area *icons)
+{
+ const char *name = progress_animation_sprite;
+ os_error *error;
+
+ progress_bar_definition.sprite_area = icons;
+
+ progress_icon = NULL;
+ error = xosspriteop_select_sprite(osspriteop_USER_AREA,
+ progress_bar_definition.sprite_area,
+ (osspriteop_id) name, &progress_icon);
+ if (!error) {
+ xosspriteop_read_sprite_info(osspriteop_USER_AREA,
+ progress_bar_definition.sprite_area,
+ (osspriteop_id) name,
+ (int *) &progress_width, (int *) &progress_height,
+ 0, 0);
+ }
+}
+
+
+/**
+ * Create a new progress bar
+ */
+struct progress_bar *ro_gui_progress_bar_create(void)
+{
+ struct progress_bar *pb;
+ os_error *error;
+
+ pb = calloc(1, sizeof(*pb));
+ if (!pb)
+ return NULL;
+
+ error = xwimp_create_window((wimp_window *)&progress_bar_definition,
+ &pb->w);
+ if (error) {
+ LOG("xwimp_create_window: 0x%x: %s", error->errnum, error->errmess);
+ free(pb);
+ return NULL;
+ }
+
+ ro_gui_wimp_event_register_redraw_window(pb->w,
+ ro_gui_progress_bar_redraw);
+ ro_gui_wimp_event_set_user_data(pb->w, pb);
+ return pb;
+}
+
+
+/**
+ * Destroy a progress bar and free all associated resources
+ *
+ * \param pb the progress bar to destroy
+ */
+void ro_gui_progress_bar_destroy(struct progress_bar *pb)
+{
+ os_error *error;
+ assert(pb);
+
+ if (pb->animating) {
+ riscos_schedule(-1, ro_gui_progress_bar_animate, pb);
+ }
+ ro_gui_wimp_event_finalise(pb->w);
+ error = xwimp_delete_window(pb->w);
+ if (error) {
+ LOG("xwimp_delete_window: 0x%x:%s", error->errnum, error->errmess);
+ }
+
+ free(pb);
+}
+
+
+/**
+ * Get the handle of the window that represents a progress bar
+ *
+ * \param pb the progress bar to get the window handle of
+ * \return the progress bar's window handle
+ */
+wimp_w ro_gui_progress_bar_get_window(struct progress_bar *pb)
+{
+ assert(pb);
+
+ return pb->w;
+}
+
+
+/**
+ * Set the icon for a progress bar
+ *
+ * \param pb the progress bar to set the icon for
+ * \param icon the icon to use, or NULL for no icon
+ */
+void ro_gui_progress_bar_set_icon(struct progress_bar *pb, const char *icon)
+{
+ assert(pb);
+
+ if (!strcmp(icon, pb->icon))
+ return;
+ if (!icon)
+ pb->icon[0] = '\0';
+ else {
+ strncpy(pb->icon, icon, 12);
+ pb->icon[12] = '\0';
+ }
+ pb->recalculate = true;
+ xwimp_force_redraw(pb->w, 0, 0, 32, 32);
+ ro_gui_progress_bar_update(pb, pb->cur_width, pb->cur_height);
+}
+
+
+/**
+ * Set the value of a progress bar
+ *
+ * \param pb the progress bar to set the value for
+ * \param value the value to use
+ */
+void ro_gui_progress_bar_set_value(struct progress_bar *pb, unsigned int value)
+{
+ assert(pb);
+
+ pb->value = value;
+ if (pb->value > pb->range)
+ pb->range = pb->value;
+ ro_gui_progress_bar_update(pb, pb->cur_width, pb->cur_height);
+}
+
+
+/**
+ * Get the value of a progress bar
+ *
+ * \param pb the progress bar to get the value of
+ * \return the current value
+ */
+unsigned int ro_gui_progress_bar_get_value(struct progress_bar *pb)
+{
+ assert(pb);
+
+ return pb->value;
+}
+
+
+/**
+ * Set the range of a progress bar
+ *
+ * \param pb the progress bar to set the range for
+ * \param range the range to use
+ */
+void ro_gui_progress_bar_set_range(struct progress_bar *pb, unsigned int range)
+{
+ assert(pb);
+
+ pb->range = range;
+ if (pb->value > pb->range)
+ pb->value = pb->range;
+ ro_gui_progress_bar_update(pb, pb->cur_width, pb->cur_height);
+}
+
+
+/**
+ * Get the range of a progress bar
+ *
+ * \param pb the progress bar to get the range of
+ * \return the current range
+ */
+unsigned int ro_gui_progress_bar_get_range(struct progress_bar *pb)
+{
+ assert(pb);
+
+ return pb->range;
+}
+
+
+/**
+ * Update the progress bar to a new dimension.
+ *
+ * \param pb the progress bar to update
+ * \param width the new progress bar width
+ * \param height the new progress bar height
+ */
+void ro_gui_progress_bar_update(struct progress_bar *pb, int width, int height)
+{
+ wimp_draw redraw;
+ os_error *error;
+ osbool more;
+ os_box cur;
+
+ /* don't allow negative dimensions */
+ width = max(width, 0);
+ height = max(height, 0);
+
+ /* update the animation state */
+ if ((pb->value == 0) || (pb->value == pb->range)) {
+ if (pb->animating) {
+ riscos_schedule(-1, ro_gui_progress_bar_animate, pb);
+ }
+ pb->animating = false;
+ } else {
+ if (!pb->animating) {
+ riscos_schedule(200, ro_gui_progress_bar_animate, pb);
+ }
+ pb->animating = true;
+ }
+
+ /* get old and new positions */
+ cur = pb->visible;
+ pb->recalculate = true;
+ ro_gui_progress_bar_calculate(pb, width, height);
+
+ /* see if the progress bar hasn't moved. we don't need to consider
+ * the left edge moving as this is handled by the icon setting
+ * function */
+ if (cur.x1 == pb->visible.x1)
+ return;
+
+ /* if size has decreased then we must force a redraw */
+ if (cur.x1 > pb->visible.x1) {
+ xwimp_force_redraw(pb->w, pb->visible.x1, pb->visible.y0,
+ cur.x1, pb->visible.y1);
+ return;
+ }
+
+ /* perform a minimal redraw update */
+ redraw.w = pb->w;
+ redraw.box = pb->visible;
+ redraw.box.x0 = cur.x1;
+ error = xwimp_update_window(&redraw, &more);
+ if (error) {
+ LOG("Error getting update window: 0x%x: %s", error->errnum, error->errmess);
+ return;
+ }
+ if (more)
+ ro_gui_progress_bar_redraw_window(&redraw, pb);
+}
+
+
+/**
+ * Process a WIMP redraw request
+ *
+ * \param redraw the redraw request to process
+ */
+void ro_gui_progress_bar_redraw(wimp_draw *redraw)
+{
+ struct progress_bar *pb;
+ os_error *error;
+ osbool more;
+
+ pb = (struct progress_bar *)ro_gui_wimp_event_get_user_data(redraw->w);
+ assert(pb);
+
+ error = xwimp_redraw_window(redraw, &more);
+ if (error) {
+ LOG("xwimp_redraw_window: 0x%x: %s", error->errnum, error->errmess);
+ return;
+ }
+ if (more)
+ ro_gui_progress_bar_redraw_window(redraw, pb);
+}
+
+
+/**
+ * Animate the progress bar
+ *
+ * \param p the progress bar to animate
+ */
+void ro_gui_progress_bar_animate(void *p)
+{
+ wimp_draw redraw;
+ os_error *error;
+ osbool more;
+ struct progress_bar *pb = p;
+
+ if (!progress_icon)
+ return;
+ pb->offset -= 6;
+ if (pb->offset < 0)
+ pb->offset += progress_width * 2;
+
+ if (pb->animating) {
+ riscos_schedule(200, ro_gui_progress_bar_animate, pb);
+ }
+
+ redraw.w = pb->w;
+ redraw.box = pb->visible;
+ error = xwimp_update_window(&redraw, &more);
+ if (error != NULL) {
+ LOG("Error getting update window: '%s'", error->errmess);
+ return;
+ }
+ if (more)
+ ro_gui_progress_bar_redraw_window(&redraw, pb);
+}
+
+
+/**
+ * Calculate the position of the progress bar
+ *
+ * \param pb the progress bar to recalculate
+ * \param width the width of the progress bar
+ * \param height the height of the progress bar
+ * \return the address of the associated icon, or NULL
+ */
+void ro_gui_progress_bar_calculate(struct progress_bar *pb, int width,
+ int height)
+{
+ int icon_width, icon_height;
+ int icon_x0 = 0, icon_y0 = 0, progress_x0, progress_x1;
+ osspriteop_header *icon = NULL;
+ bool icon_redraw = false;
+
+ /* try to use cached values */
+ if ((!pb->recalculate) && (pb->cur_width == width) &&
+ (pb->cur_height == height))
+ return;
+
+ /* update cache status */
+ pb->recalculate = false;
+ pb->cur_width = width;
+ pb->cur_height = height;
+
+ /* get the window dimensions */
+ width -= MARGIN * 2;
+ icon_width = icon_height = 0;
+ progress_x0 = MARGIN;
+
+ /* get the icon information */
+ if (progress_bar_definition.sprite_area != wimpspriteop_AREA) {
+ int progress_ymid = height / 2;
+ os_error *error;
+ error = xosspriteop_read_sprite_info(osspriteop_USER_AREA,
+ progress_bar_definition.sprite_area,
+ (osspriteop_id)pb->icon,
+ &icon_width, &icon_height, 0, 0);
+ if (!error) {
+ error = xosspriteop_select_sprite(osspriteop_USER_AREA,
+ progress_bar_definition.sprite_area,
+ (osspriteop_id)pb->icon, &icon);
+ }
+ if (!error) {
+ progress_x0 += 32 + MARGIN;
+ width -= 32 + MARGIN;
+ icon_x0 = MARGIN + 16 - icon_width;
+ icon_y0 = progress_ymid - icon_height;
+ if (width < -MARGIN) {
+ icon_x0 += width + MARGIN;
+ icon_redraw = true;
+ }
+ }
+ }
+
+ /* update the icon */
+ if ((pb->icon_obscured) || (icon_redraw)) {
+ if (icon_x0 != pb->icon_x0)
+ xwimp_force_redraw(pb->w, 0, 0, 32 + MARGIN, 65536);
+ }
+ pb->icon_obscured = icon_redraw;
+
+ progress_x1 = progress_x0;
+ if ((pb->range > 0) && (width > 0))
+ progress_x1 += (width * pb->value) / pb->range;
+
+ pb->visible.x0 = progress_x0;
+ pb->visible.y0 = MARGIN;
+ pb->visible.x1 = progress_x1;
+ pb->visible.y1 = height - MARGIN;
+ pb->icon_x0 = icon_x0;
+ pb->icon_y0 = icon_y0;
+ pb->icon_img = icon;
+}
+
+
+/**
+ * Redraw a section of a progress bar window
+ *
+ * \param redraw the section of the window to redraw
+ * \param pb the progress bar to redraw
+ */
+void ro_gui_progress_bar_redraw_window(wimp_draw *redraw,
+ struct progress_bar *pb)
+{
+ osbool more = true;
+ struct rect clip;
+ int progress_ymid;
+
+ /* initialise the plotters */
+ ro_plot_origin_x = 0;
+ ro_plot_origin_y = 0;
+
+ /* recalculate the progress bar */
+ ro_gui_progress_bar_calculate(pb, redraw->box.x1 - redraw->box.x0,
+ redraw->box.y1 - redraw->box.y0);
+ progress_ymid = redraw->box.y0 + pb->visible.y0 +
+ ((pb->visible.y1 - pb->visible.y0) >> 1);
+
+ /* redraw the window */
+ while (more) {
+ os_error *error;
+ if (pb->icon)
+ _swix(Tinct_PlotAlpha, _IN(2) | _IN(3) | _IN(4) | _IN(7),
+ pb->icon_img,
+ redraw->box.x0 + pb->icon_x0,
+ redraw->box.y0 + pb->icon_y0,
+ tinct_ERROR_DIFFUSE);
+ if (!pb->icon_obscured) {
+ clip.x0 = max(redraw->clip.x0,
+ redraw->box.x0 + pb->visible.x0) >> 1;
+ clip.y0 = -min(redraw->clip.y1,
+ redraw->box.y0 + pb->visible.y1) >> 1;
+ clip.x1 = min(redraw->clip.x1,
+ redraw->box.x0 + pb->visible.x1) >> 1;
+ clip.y1 = -max(redraw->clip.y0,
+ redraw->box.y0 + pb->visible.y0) >> 1;
+ if ((clip.x0 < clip.x1) && (clip.y0 < clip.y1)) {
+ if (progress_icon) {
+ ro_plotters.clip(&clip);
+ _swix(Tinct_Plot, _IN(2) | _IN(3) | _IN(4) | _IN(7),
+ progress_icon,
+ redraw->box.x0 - pb->offset,
+ progress_ymid - progress_height,
+ tinct_FILL_HORIZONTALLY);
+ } else {
+ ro_plotters.rectangle(clip.x0, clip.y0,
+ clip.x1, clip.y1,
+ plot_style_fill_red);
+ }
+ }
+ }
+ error = xwimp_get_rectangle(redraw, &more);
+ if (error) {
+ LOG("xwimp_get_rectangle: 0x%x: %s", error->errnum, error->errmess);
+ return;
+ }
+ }
+}
diff --git a/frontends/riscos/gui/progress_bar.h b/frontends/riscos/gui/progress_bar.h
new file mode 100644
index 000000000..e4cec1369
--- /dev/null
+++ b/frontends/riscos/gui/progress_bar.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2006 Richard Wilson <info@tinct.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Progress bar (interface).
+ */
+
+#ifndef _NETSURF_RISCOS_PROGRESS_BAR_H_
+#define _NETSURF_RISCOS_PROGRESS_BAR_H_
+
+#include <stdbool.h>
+#include "oslib/osspriteop.h"
+#include "oslib/wimp.h"
+
+struct progress_bar;
+
+void ro_gui_progress_bar_init(osspriteop_area *icons);
+
+struct progress_bar *ro_gui_progress_bar_create(void);
+void ro_gui_progress_bar_destroy(struct progress_bar *pb);
+void ro_gui_progress_bar_update(struct progress_bar *pb, int width, int height);
+
+wimp_w ro_gui_progress_bar_get_window(struct progress_bar *pb);
+void ro_gui_progress_bar_set_icon(struct progress_bar *pb, const char *icon);
+void ro_gui_progress_bar_set_value(struct progress_bar *pb, unsigned int value);
+unsigned int ro_gui_progress_bar_get_value(struct progress_bar *pb);
+void ro_gui_progress_bar_set_range(struct progress_bar *pb, unsigned int range);
+unsigned int ro_gui_progress_bar_get_range(struct progress_bar *pb);
+#endif
diff --git a/frontends/riscos/gui/status_bar.c b/frontends/riscos/gui/status_bar.c
new file mode 100644
index 000000000..cbc404658
--- /dev/null
+++ b/frontends/riscos/gui/status_bar.c
@@ -0,0 +1,625 @@
+/*
+ * Copyright 2006 Richard Wilson <info@tinct.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * UTF8 status bar (implementation).
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <string.h>
+#include "swis.h"
+#include "oslib/colourtrans.h"
+#include "oslib/os.h"
+#include "oslib/wimp.h"
+#include "oslib/wimpspriteop.h"
+#include "desktop/plotters.h"
+#include "utils/log.h"
+#include "utils/utils.h"
+
+#include "riscos/gui.h"
+#include "riscos/wimp.h"
+#include "riscos/wimp_event.h"
+#include "riscos/wimputils.h"
+#include "riscos/font.h"
+#include "riscos/gui/progress_bar.h"
+#include "riscos/gui/status_bar.h"
+
+#define ICON_WIDGET 0
+#define WIDGET_WIDTH 12
+#define PROGRESS_WIDTH 160
+
+struct status_bar {
+ wimp_w w; /**< status bar window handle */
+ wimp_w parent; /**< parent window handle */
+ const char *text; /**< status bar text */
+ struct progress_bar *pb; /**< progress bar */
+ unsigned int scale; /**< current status bar scale */
+ int width; /**< current status bar width */
+ bool visible; /**< status bar is visible? */
+};
+
+static char status_widget_text[] = "";
+static char status_widget_validation[] = "R5;Pptr_lr,8,6";
+
+wimp_WINDOW(1) status_bar_definition = {
+ {0, 0, 1, 1},
+ 0,
+ 0,
+ wimp_TOP,
+ wimp_WINDOW_NEW_FORMAT | wimp_WINDOW_MOVEABLE |
+ wimp_WINDOW_FURNITURE_WINDOW |
+ wimp_WINDOW_IGNORE_XEXTENT,
+ wimp_COLOUR_BLACK,
+ wimp_COLOUR_LIGHT_GREY,
+ wimp_COLOUR_LIGHT_GREY,
+ wimp_COLOUR_VERY_LIGHT_GREY,
+ wimp_COLOUR_DARK_GREY,
+ wimp_COLOUR_MID_LIGHT_GREY,
+ wimp_COLOUR_CREAM,
+ wimp_WINDOW_NEVER3D | 0x16u /* RISC OS 5.03+ */,
+ {0, 0, 65535, 65535},
+ 0,
+ 0,
+ wimpspriteop_AREA,
+ 1,
+ 1,
+ {""},
+ 1,
+ {
+ {
+ {0, 0, 1, 1},
+ wimp_ICON_TEXT | wimp_ICON_INDIRECTED |
+ wimp_ICON_BORDER | wimp_ICON_FILLED |
+ (wimp_COLOUR_LIGHT_GREY <<
+ wimp_ICON_BG_COLOUR_SHIFT) |
+ (wimp_BUTTON_CLICK_DRAG <<
+ wimp_ICON_BUTTON_TYPE_SHIFT),
+ {
+ .indirected_text = {
+ status_widget_text,
+ status_widget_validation,
+ 1
+ }
+ }
+ }
+ }
+};
+
+static void ro_gui_status_bar_open(wimp_open *open);
+static bool ro_gui_status_bar_click(wimp_pointer *pointer);
+static void ro_gui_status_bar_redraw(wimp_draw *redraw);
+static void ro_gui_status_bar_redraw_callback(void *handle);
+static void ro_gui_status_position_progress_bar(struct status_bar *sb);
+
+
+/**
+ * Create a new status bar
+ *
+ * \param parent the window to contain the status bar
+ * \param width the proportional width to use (0...10,000)
+ */
+struct status_bar *ro_gui_status_bar_create(wimp_w parent, unsigned int width)
+{
+ struct status_bar *sb;
+ os_error *error;
+
+ sb = calloc(1, sizeof(*sb));
+ if (!sb)
+ return NULL;
+
+ sb->pb = ro_gui_progress_bar_create();
+ if (!sb->pb)
+ return NULL;
+
+ error = xwimp_create_window((wimp_window *)&status_bar_definition,
+ &sb->w);
+ if (error) {
+ LOG("xwimp_create_window: 0x%x: %s", error->errnum, error->errmess);
+ free(sb);
+ return NULL;
+ }
+ sb->parent = parent;
+ sb->scale = width;
+ sb->visible = true;
+
+ ro_gui_wimp_event_set_user_data(sb->w, sb);
+ ro_gui_wimp_event_register_open_window(sb->w,
+ ro_gui_status_bar_open);
+ ro_gui_wimp_event_register_mouse_click(sb->w,
+ ro_gui_status_bar_click);
+ ro_gui_wimp_event_register_redraw_window(sb->w,
+ ro_gui_status_bar_redraw);
+ ro_gui_wimp_event_set_help_prefix(sb->w, "HelpStatus");
+ ro_gui_status_bar_resize(sb);
+ return sb;
+}
+
+
+/**
+ * Destroy a status bar and free all associated resources
+ *
+ * \param sb the status bar to destroy
+ */
+void ro_gui_status_bar_destroy(struct status_bar *sb)
+{
+ os_error *error;
+ assert(sb);
+
+ ro_gui_wimp_event_finalise(sb->w);
+ error = xwimp_delete_window(sb->w);
+ if (error) {
+ LOG("xwimp_delete_window: 0x%x:%s", error->errnum, error->errmess);
+ }
+
+ ro_gui_progress_bar_destroy(sb->pb);
+
+ /* Remove any scheduled redraw callbacks */
+ riscos_schedule(-1, ro_gui_status_bar_redraw_callback, (void *) sb);
+
+ free(sb);
+}
+
+
+/**
+ * Get the handle of the window that represents a status bar
+ *
+ * \param sb the status bar to get the window handle of
+ * \return the status bar's window handle
+ */
+wimp_w ro_gui_status_bar_get_window(struct status_bar *sb)
+{
+ assert(sb);
+
+ return sb->w;
+}
+
+
+/**
+ * Get the proportional width the status bar is currently using
+ *
+ * \param sb the status bar to get the width of
+ * \return the status bar's width (0...10,000)
+ */
+unsigned int ro_gui_status_bar_get_width(struct status_bar *sb)
+{
+ assert(sb);
+
+ return sb->scale;
+}
+
+
+/**
+ * Set the visibility status of the status bar
+ *
+ * \param sb the status bar to check the visiblity of
+ * \param visible if the status bar should be shown or not.
+ * \return whether the status bar is visible
+ */
+void ro_gui_status_bar_set_visible(struct status_bar *sb, bool visible)
+{
+ assert(sb);
+
+ sb->visible = visible;
+ if (visible) {
+ ro_gui_status_bar_resize(sb);
+ } else {
+ os_error *error = xwimp_close_window(sb->w);
+ if (error) {
+ LOG("xwimp_close_window: 0x%x:%s", error->errnum, error->errmess);
+ }
+ }
+}
+
+
+/**
+ * Get the visibility status of the status bar
+ *
+ * \param sb the status bar to check the visiblity of
+ * \return whether the status bar is visible
+ */
+bool ro_gui_status_bar_get_visible(struct status_bar *sb)
+{
+ assert(sb);
+
+ return sb->visible;
+}
+
+
+/**
+ * Set the value of the progress bar
+ *
+ * \param sb the status bar to set the progress of
+ * \param value the value to use
+ */
+void ro_gui_status_bar_set_progress_value(struct status_bar *sb,
+ unsigned int value)
+{
+ assert(sb);
+
+ ro_gui_status_bar_set_progress_range(sb,
+ max(value, ro_gui_progress_bar_get_range(sb->pb)));
+ ro_gui_progress_bar_set_value(sb->pb, value);
+}
+
+
+/**
+ * Set the range of the progress bar
+ *
+ * \param sb the status bar to set the range of
+ * \param range the range of the progress bar
+ */
+void ro_gui_status_bar_set_progress_range(struct status_bar *sb,
+ unsigned int range)
+{
+ unsigned int old_range;
+
+ assert(sb);
+
+ old_range = ro_gui_progress_bar_get_range(sb->pb);
+ ro_gui_progress_bar_set_range(sb->pb, range);
+
+ LOG("Ranges are %i vs %i", old_range, range);
+ if ((old_range == 0) && (range != 0)) {
+ ro_gui_status_position_progress_bar(sb);
+ } else if ((old_range != 0) && (range == 0)) {
+ os_error *error = xwimp_close_window(
+ ro_gui_progress_bar_get_window(sb->pb));
+ if (error) {
+ LOG("xwimp_close_window: 0x%x:%s", error->errnum, error->errmess);
+ }
+ }
+}
+
+
+/**
+ * Set the icon for the progress bar
+ *
+ * \param sb the status bar to set the icon for
+ * \param icon the icon to use, or NULL for no icon
+ */
+void ro_gui_status_bar_set_progress_icon(struct status_bar *sb,
+ const char *icon)
+{
+ assert(sb);
+
+ ro_gui_progress_bar_set_icon(sb->pb, icon);
+}
+
+
+/**
+ * Set the text to display in the status bar
+ *
+ * \param sb the status bar to set the text for
+ * \param text the UTF8 text to display, or NULL for none
+ */
+void ro_gui_status_bar_set_text(struct status_bar *sb, const char *text)
+{
+ assert(sb);
+
+ sb->text = text;
+
+ /* Schedule a window redraw for 1cs' time.
+ *
+ * We do this to ensure that redraws as a result of text changes
+ * do not prevent other applications obtaining CPU time.
+ *
+ * The scheduled callback will be run when we receive the first
+ * null poll after 1cs has elapsed. It may then issue a redraw
+ * request to the Wimp.
+ *
+ * The scheduler ensures that only one instance of the
+ * { callback, handle } pair is registered at once.
+ */
+ if (sb->visible && text != NULL) {
+ riscos_schedule(10, ro_gui_status_bar_redraw_callback, sb);
+ }
+}
+
+
+/**
+ * Resize a status bar following a change in the dimensions of the
+ * parent window.
+ *
+ * \param sb the status bar to resize
+ */
+void ro_gui_status_bar_resize(struct status_bar *sb)
+{
+ int window_width;
+ int status_width, status_height;
+ wimp_window_state state;
+ os_error *error;
+ os_box extent;
+
+ if ((!sb) || (!sb->visible))
+ return;
+
+ /* get the window work area dimensions */
+ state.w = sb->parent;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ return;
+ }
+ window_width = state.visible.x1 - state.visible.x0;
+
+
+ /* recalculate the scaled width */
+ status_width = (window_width * sb->scale) / 10000;
+ if (status_width < WIDGET_WIDTH)
+ status_width = WIDGET_WIDTH;
+ status_height = ro_get_hscroll_height(sb->parent);
+
+ /* resize the status/resize icons */
+ if (status_width != sb->width) {
+ /* update the window extent */
+ int redraw_left, redraw_right;
+
+ extent.x0 = 0;
+ extent.y0 = 0;
+ extent.x1 = status_width;
+ extent.y1 = status_height - 4;
+ error = xwimp_set_extent(sb->w, &extent);
+ if (error) {
+ LOG("xwimp_set_extent: 0x%x: %s", error->errnum, error->errmess);
+ return;
+ }
+
+ /* re-open the nested window */
+ state.w = sb->w;
+ state.xscroll = 0;
+ state.yscroll = 0;
+ state.next = wimp_TOP;
+ state.visible.x0 = state.visible.x0;
+ state.visible.y1 = state.visible.y0 - 2;
+ state.visible.x1 = state.visible.x0 + status_width;
+ state.visible.y0 = state.visible.y1 - status_height + 4;
+ error = xwimp_open_window_nested(PTR_WIMP_OPEN(&state),
+ sb->parent,
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_XORIGIN_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_YORIGIN_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_LS_EDGE_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_BS_EDGE_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_RS_EDGE_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_TS_EDGE_SHIFT);
+ if (error) {
+ LOG("xwimp_open_window_nested: 0x%x: %s", error->errnum, error->errmess);
+ return;
+ }
+ ro_gui_status_position_progress_bar(sb);
+ error = xwimp_resize_icon(sb->w, ICON_WIDGET,
+ status_width - WIDGET_WIDTH, 0,
+ status_width, status_height - 4);
+ if (error) {
+ LOG("xwimp_resize_icon: 0x%x: %s", error->errnum, error->errmess);
+ return;
+ }
+
+ redraw_left = min(status_width, sb->width) - WIDGET_WIDTH - 2;
+ redraw_right = max(status_width, sb->width);
+ xwimp_force_redraw(sb->w, redraw_left, 0,
+ redraw_right, status_height);
+ sb->width = status_width;
+ }
+}
+
+
+/**
+ * Process a WIMP redraw request
+ *
+ * \param redraw the redraw request to process
+ */
+void ro_gui_status_bar_redraw(wimp_draw *redraw)
+{
+ struct status_bar *sb;
+ os_error *error;
+ osbool more;
+ rufl_code code;
+
+ sb = (struct status_bar *)ro_gui_wimp_event_get_user_data(redraw->w);
+ assert(sb);
+
+ /* initialise the plotters */
+ ro_plot_origin_x = 0;
+ ro_plot_origin_y = 0;
+
+ /* redraw the window */
+ error = xwimp_redraw_window(redraw, &more);
+ if (error) {
+ LOG("xwimp_redraw_window: 0x%x: %s", error->errnum, error->errmess);
+ return;
+ }
+ while (more) {
+ /* redraw the status text */
+ if (sb->text) {
+ error = xcolourtrans_set_font_colours(font_CURRENT,
+ 0xeeeeee00, 0x00000000, 14, 0, 0, 0);
+ if (error) {
+ LOG("xcolourtrans_set_font_colours: 0x%x: %s", error->errnum, error->errmess);
+ return;
+ }
+ code = rufl_paint(ro_gui_desktop_font_family,
+ ro_gui_desktop_font_style,
+ ro_gui_desktop_font_size,
+ sb->text, strlen(sb->text),
+ redraw->box.x0 + 6, redraw->box.y0 + 8,
+ rufl_BLEND_FONT);
+ if (code != rufl_OK) {
+ if (code == rufl_FONT_MANAGER_ERROR)
+ LOG("rufl_FONT_MANAGER_ERROR: 0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess);
+ else
+ LOG("rufl_paint: 0x%x", code);
+ }
+ }
+
+ /* separate the widget from the text with a line */
+ ro_plotters.rectangle((redraw->box.x0 + sb->width - WIDGET_WIDTH - 2) >> 1,
+ -redraw->box.y0 >> 1,
+ (redraw->box.x0 + sb->width - WIDGET_WIDTH) >> 1,
+ -redraw->box.y1 >> 1,
+ plot_style_fill_black);
+
+ error = xwimp_get_rectangle(redraw, &more);
+ if (error) {
+ LOG("xwimp_get_rectangle: 0x%x: %s", error->errnum, error->errmess);
+ return;
+ }
+ }
+}
+
+/**
+ * Callback for scheduled redraw
+ *
+ * \param handle Callback handle
+ */
+void ro_gui_status_bar_redraw_callback(void *handle)
+{
+ struct status_bar *sb = handle;
+
+ wimp_force_redraw(sb->w, 0, 0, sb->width - WIDGET_WIDTH, 65536);
+}
+
+
+/**
+ * Process an mouse_click event for a status window.
+ *
+ * \param pointer details of the mouse click
+ */
+bool ro_gui_status_bar_click(wimp_pointer *pointer)
+{
+ wimp_drag drag;
+ os_error *error;
+
+ switch (pointer->i) {
+ case ICON_WIDGET:
+ drag.w = pointer->w;
+ drag.type = wimp_DRAG_SYSTEM_SIZE;
+ drag.initial.x0 = pointer->pos.x;
+ drag.initial.x1 = pointer->pos.x;
+ drag.initial.y0 = pointer->pos.y;
+ drag.initial.y1 = pointer->pos.y;
+ error = xwimp_drag_box(&drag);
+ if (error) {
+ LOG("xwimp_drag_box: 0x%x: %s", error->errnum, error->errmess);
+ }
+ break;
+ }
+ return true;
+}
+
+
+/**
+ * Process an open_window request for a status window.
+ *
+ * \param open the request to process
+ */
+void ro_gui_status_bar_open(wimp_open *open)
+{
+ struct status_bar *sb;
+ int window_width, status_width;
+ wimp_window_state state;
+ os_error *error;
+
+ /* get the parent width for scaling */
+ sb = (struct status_bar *)ro_gui_wimp_event_get_user_data(open->w);
+ state.w = sb->parent;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ return;
+ }
+ window_width = state.visible.x1 - state.visible.x0;
+ if (window_width == 0)
+ window_width = 1;
+ status_width = open->visible.x1 - open->visible.x0;
+ if (status_width <= 12)
+ status_width = 0;
+
+ /* store the new size */
+ sb->scale = (10000 * status_width) / window_width;
+ if (sb->scale > 10000)
+ sb->scale = 10000;
+ ro_gui_status_bar_resize(sb);
+}
+
+
+/**
+ * Reposition the progress component following a change in the
+ * dimension of the status window.
+ *
+ * \param sb the status bar to update
+ */
+void ro_gui_status_position_progress_bar(struct status_bar *sb)
+{
+ wimp_window_state state;
+ os_error *error;
+ int left, right;
+
+ if (!sb)
+ return;
+ if (ro_gui_progress_bar_get_range(sb->pb) == 0)
+ return;
+
+ /* get the window work area dimensions */
+ state.w = sb->w;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ return;
+ }
+
+ /* calculate the dimensions */
+ right = state.visible.x1 - WIDGET_WIDTH - 2;
+ left = max(state.visible.x0, right - PROGRESS_WIDTH);
+
+ /* re-open the nested window */
+ state.w = ro_gui_progress_bar_get_window(sb->pb);
+ state.xscroll = 0;
+ state.yscroll = 0;
+ state.next = wimp_TOP;
+ state.visible.x0 = left;
+ state.visible.x1 = right;
+ error = xwimp_open_window_nested(PTR_WIMP_OPEN(&state),
+ sb->w,
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_XORIGIN_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_YORIGIN_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_LS_EDGE_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_BS_EDGE_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_RS_EDGE_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_TS_EDGE_SHIFT);
+ if (error) {
+ LOG("xwimp_open_window: 0x%x: %s", error->errnum, error->errmess);
+ }
+
+ /* update the progress bar display on non-standard width */
+ if ((right - left) != PROGRESS_WIDTH)
+ ro_gui_progress_bar_update(sb->pb, right - left,
+ state.visible.y1 - state.visible.y0);
+}
diff --git a/frontends/riscos/gui/status_bar.h b/frontends/riscos/gui/status_bar.h
new file mode 100644
index 000000000..8b5bb35aa
--- /dev/null
+++ b/frontends/riscos/gui/status_bar.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2006 Richard Wilson <info@tinct.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * UTF8 status bar (interface).
+ */
+
+#ifndef _NETSURF_RISCOS_STATUS_BAR_H_
+#define _NETSURF_RISCOS_STATUS_BAR_H_
+
+#include <stdbool.h>
+
+struct status_bar;
+
+struct status_bar *ro_gui_status_bar_create(wimp_w parent, unsigned int width);
+void ro_gui_status_bar_destroy(struct status_bar *sb);
+
+wimp_w ro_gui_status_bar_get_window(struct status_bar *sb);
+unsigned int ro_gui_status_bar_get_width(struct status_bar *sb);
+void ro_gui_status_bar_resize(struct status_bar *sb);
+void ro_gui_status_bar_set_visible(struct status_bar *pb, bool visible);
+bool ro_gui_status_bar_get_visible(struct status_bar *sb);
+void ro_gui_status_bar_set_text(struct status_bar *sb, const char *text);
+void ro_gui_status_bar_set_progress_value(struct status_bar *sb,
+ unsigned int value);
+void ro_gui_status_bar_set_progress_range(struct status_bar *sb,
+ unsigned int range);
+void ro_gui_status_bar_set_progress_icon(struct status_bar *sb,
+ const char *icon);
+#endif
diff --git a/frontends/riscos/gui/throbber.c b/frontends/riscos/gui/throbber.c
new file mode 100644
index 000000000..a326f806c
--- /dev/null
+++ b/frontends/riscos/gui/throbber.c
@@ -0,0 +1,418 @@
+/*
+ * Copyright 2004, 2005 Richard Wilson <info@tinct.net>
+ * Copyright 2011 Stephen Fryatt <stevef@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Throbber (implementation).
+ */
+
+#include <alloca.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include "oslib/os.h"
+#include "oslib/osspriteop.h"
+#include "oslib/wimp.h"
+
+#include "utils/log.h"
+#include "riscos/gui.h"
+
+#include "riscos/gui/throbber.h"
+#include "riscos/theme.h"
+#include "riscos/wimp.h"
+
+#define THROBBER_SPRITE_NAME_LENGTH 12
+#define THROBBER_ANIMATE_INTERVAL 10
+
+struct throbber {
+ /** The applied theme (or NULL to use the default) */
+ struct theme_descriptor *theme;
+
+ /** The widget dimensions. */
+ int x_min, y_min;
+
+ /** The window and icon details. */
+ wimp_w window;
+ wimp_i icon;
+ os_box extent;
+ osspriteop_area *sprites;
+ bool hidden;
+ bool shaded;
+
+ /** The animation details. */
+ int max_frame;
+ int current_frame;
+ os_t last_update;
+ char sprite_name[THROBBER_SPRITE_NAME_LENGTH];
+ bool force_redraw;
+};
+
+/*
+ * Private function prototypes.
+ */
+
+static bool ro_gui_throbber_icon_update(struct throbber *throbber);
+static bool ro_gui_throbber_icon_resize(struct throbber *throbber);
+
+/* This is an exported interface documented in throbber.h */
+
+struct throbber *ro_gui_throbber_create(struct theme_descriptor *theme)
+{
+ struct throbber *throbber;
+
+ /* Allocate memory. */
+
+ throbber = malloc(sizeof(struct throbber));
+ if (throbber == NULL) {
+ LOG("No memory for malloc()");
+ return NULL;
+ }
+
+ /* Set up default parameters. If reading the throbber theme data
+ * fails, we give up and return a failure.
+ */
+
+ if (!ro_gui_theme_get_throbber_data(theme, &throbber->max_frame,
+ &throbber->x_min, &throbber->y_min, NULL,
+ &throbber->force_redraw)) {
+ free(throbber);
+ return NULL;
+ }
+
+ throbber->sprites = ro_gui_theme_get_sprites(theme);
+
+ throbber->theme = theme;
+
+ throbber->extent.x0 = 0;
+ throbber->extent.y0 = 0;
+ throbber->extent.x1 = 0;
+ throbber->extent.y1 = 0;
+
+ throbber->current_frame = 0;
+ throbber->last_update = 0;
+
+ throbber->window = NULL;
+ throbber->icon = -1;
+
+ throbber->hidden = false;
+ throbber->shaded = false;
+
+ return throbber;
+}
+
+
+/* This is an exported interface documented in throbber.h */
+
+bool ro_gui_throbber_rebuild(struct throbber *throbber,
+ struct theme_descriptor *theme, theme_style style,
+ wimp_w window, bool shaded)
+{
+ if (throbber == NULL)
+ return false;
+
+ throbber->theme = theme;
+ throbber->window = window;
+ throbber->sprites = ro_gui_theme_get_sprites(theme);
+
+ throbber->icon = -1;
+
+ throbber->shaded = shaded;
+
+ strcpy(throbber->sprite_name, "throbber0");
+
+ if (!ro_gui_theme_get_throbber_data(theme, &throbber->max_frame,
+ &throbber->x_min, &throbber->y_min, NULL,
+ &throbber->force_redraw)) {
+ free(throbber);
+ return false;
+ }
+
+ return ro_gui_throbber_icon_update(throbber);
+}
+
+
+/* This is an exported interface documented in throbber.h */
+
+void ro_gui_throbber_destroy(struct throbber *throbber)
+{
+ if (throbber == NULL)
+ return;
+
+ free(throbber);
+}
+
+
+/* This is an exported interface documented in throbber.h */
+
+bool ro_gui_throbber_get_dims(struct throbber *throbber,
+ int *width, int *height)
+{
+ if (throbber == NULL)
+ return false;
+
+ if (throbber->x_min != -1 && throbber->y_min != -1) {
+ if (width != NULL)
+ *width = throbber->x_min;
+ if (height != NULL)
+ *height = throbber->y_min;
+
+ return true;
+ }
+
+ return false;
+}
+
+
+/* This is an exported interface documented in throbber.h */
+
+bool ro_gui_throbber_set_extent(struct throbber *throbber,
+ int x0, int y0, int x1, int y1)
+{
+ if (throbber == NULL)
+ return false;
+
+ if ((x1 - x0) < throbber->x_min || (y1 - y0) < throbber->y_min)
+ return false;
+
+ if (throbber->extent.x0 == x0 && throbber->extent.y0 == y0 &&
+ throbber->extent.x1 == x1 &&
+ throbber->extent.y1 == y1)
+ return true;
+
+ /* Redraw the relevant bits of the toolbar. */
+
+ if (throbber->window != NULL && throbber->icon != -1) {
+ xwimp_force_redraw(throbber->window,
+ throbber->extent.x0, throbber->extent.y0,
+ throbber->extent.x1, throbber->extent.y1);
+ xwimp_force_redraw(throbber->window, x0, y0, x1, y1);
+ }
+
+ /* Update the throbber position */
+
+ throbber->extent.x0 = x0;
+ throbber->extent.y0 = y0;
+ throbber->extent.x1 = x1;
+ throbber->extent.y1 = y1;
+
+ return ro_gui_throbber_icon_resize(throbber);
+}
+
+
+/**
+ * Create or delete a throbber's icon if required to bring it into sync with
+ * the current hidden setting.
+ *
+ * \param *throbber The throbber to update.
+ * \return true if successful; else false.
+ */
+
+bool ro_gui_throbber_icon_update(struct throbber *throbber)
+{
+ wimp_icon_create icon;
+ os_error *error;
+
+ if (throbber == NULL || throbber->window == NULL)
+ return false;
+
+ if (!throbber->hidden && throbber->icon == -1) {
+ icon.w = throbber->window;
+ icon.icon.extent.x0 = throbber->extent.x0;
+ icon.icon.extent.y0 = throbber->extent.y0;
+ icon.icon.extent.x1 = throbber->extent.x1;
+ icon.icon.extent.y1 = throbber->extent.y1;
+ icon.icon.flags = wimp_ICON_SPRITE | wimp_ICON_INDIRECTED |
+ wimp_ICON_HCENTRED | wimp_ICON_VCENTRED;
+ icon.icon.data.indirected_sprite.id =
+ (osspriteop_id) throbber->sprite_name;
+ icon.icon.data.indirected_sprite.area = throbber->sprites;
+ icon.icon.data.indirected_sprite.size =
+ THROBBER_SPRITE_NAME_LENGTH;
+
+ error = xwimp_create_icon(&icon, &throbber->icon);
+ if (error != NULL) {
+ LOG("xwimp_create_icon: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ throbber->icon = -1;
+ return false;
+ }
+
+ if (!ro_gui_throbber_icon_resize(throbber))
+ return false;
+ } else if (throbber->hidden && throbber->icon != -1) {
+ error = xwimp_delete_icon(throbber->window, throbber->icon);
+ if (error != NULL) {
+ LOG("xwimp_delete_icon: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return false;
+ }
+
+ throbber->icon = -1;
+ }
+
+ if (throbber->icon != -1)
+ ro_gui_set_icon_shaded_state(throbber->window,
+ throbber->icon, throbber->shaded);
+
+ return true;
+}
+
+
+/**
+ * Position the icons in the throbber to take account of the currently
+ * configured extent.
+ *
+ * \param *throbber The throbber to update.
+ * \return true if successful; else false.
+ */
+
+bool ro_gui_throbber_icon_resize(struct throbber *throbber)
+{
+
+ if (throbber->window == NULL)
+ return false;
+
+ if (throbber->icon != -1) {
+ os_error *error;
+ error = xwimp_resize_icon(throbber->window, throbber->icon,
+ throbber->extent.x0, throbber->extent.y0,
+ throbber->extent.x1, throbber->extent.y1);
+ if (error != NULL) {
+ LOG("xwimp_resize_icon: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ throbber->icon = -1;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+/* This is an exported interface documented in throbber.h */
+
+bool ro_gui_throbber_hide(struct throbber *throbber, bool hide)
+{
+ if (throbber == NULL || throbber->hidden == hide)
+ return (throbber == NULL) ? false : true;
+
+ throbber->hidden = hide;
+
+ return ro_gui_throbber_icon_update(throbber);
+}
+
+
+/* This is an exported interface documented in throbber.h */
+
+bool ro_gui_throbber_help_suffix(struct throbber *throbber, wimp_i i,
+ os_coord *mouse, wimp_window_state *state,
+ wimp_mouse_state buttons, const char **suffix)
+{
+ os_coord pos;
+
+ if (throbber == NULL || throbber->hidden)
+ return false;
+
+ /* Check that the click was within our part of the window. */
+
+ pos.x = mouse->x - state->visible.x0 + state->xscroll;
+ pos.y = mouse->y - state->visible.y1 + state->yscroll;
+
+ if (pos.x < throbber->extent.x0 || pos.x > throbber->extent.x1 ||
+ pos.y < throbber->extent.y0 ||
+ pos.y > throbber->extent.y1)
+ return false;
+
+ /* Return a hard-coded icon number that matches the one that was
+ * always allocated to the throbber in a previous implementation.
+ * If Messages can be updated, this could be changed.
+ */
+
+ if (i == throbber->icon)
+ *suffix = "16";
+ else
+ *suffix = "";
+
+ return true;
+}
+
+
+/* This is an exported interface documented in throbber.h */
+
+bool ro_gui_throbber_animate(struct throbber *throbber)
+{
+ os_t t;
+ char sprite_name[THROBBER_SPRITE_NAME_LENGTH];
+
+ if (throbber == NULL || throbber->hidden)
+ return (throbber == NULL) ? false : true;
+
+ xos_read_monotonic_time(&t);
+
+ /* Drop out if we're not ready for the next frame, unless this
+ * call is to start animation from a stopped throbber (ie. if
+ * the current frame is 0).
+ */
+
+ if ((t < (throbber->last_update + THROBBER_ANIMATE_INTERVAL)) &&
+ (throbber->current_frame > 0))
+ return true;
+
+ throbber->last_update = t;
+ throbber->current_frame++;
+
+ if (throbber->current_frame > throbber->max_frame)
+ throbber->current_frame = 1;
+
+ snprintf(sprite_name, THROBBER_SPRITE_NAME_LENGTH,
+ "throbber%i", throbber->current_frame);
+ ro_gui_set_icon_string(throbber->window, throbber->icon,
+ sprite_name, true);
+
+ if (throbber->force_redraw)
+ ro_gui_force_redraw_icon(throbber->window, throbber->icon);
+
+ return true;
+}
+
+
+/* This is an exported interface documented in throbber.h */
+
+bool ro_gui_throbber_stop(struct throbber *throbber)
+{
+ char sprite_name[THROBBER_SPRITE_NAME_LENGTH];
+
+ if (throbber == NULL || throbber->hidden ||
+ throbber->current_frame == 0)
+ return (throbber == FALSE) ? false : true;
+
+ throbber->current_frame = 0;
+ throbber->last_update = 0;
+
+ strcpy(sprite_name, "throbber0");
+ ro_gui_set_icon_string(throbber->window, throbber->icon,
+ sprite_name, true);
+
+ if (throbber->force_redraw)
+ ro_gui_force_redraw_icon(throbber->window, throbber->icon);
+
+ return true;
+}
+
diff --git a/frontends/riscos/gui/throbber.h b/frontends/riscos/gui/throbber.h
new file mode 100644
index 000000000..6b2419b6e
--- /dev/null
+++ b/frontends/riscos/gui/throbber.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2005 Richard Wilson <info@tinct.net>
+ * Copyright 2011 Stephen Fryatt <stevef@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Throbber (interface).
+ */
+
+#ifndef _NETSURF_RISCOS_THROBBER_H_
+#define _NETSURF_RISCOS_THROBBER_H_
+
+#include <stdbool.h>
+#include "riscos/theme.h"
+
+struct throbber;
+
+
+/**
+ * Create a new throbber widget.
+ *
+ * \param *theme The theme to apply (or NULL for the default).
+ * \return A throbber handle, or NULL on failure.
+ */
+
+struct throbber *ro_gui_throbber_create(struct theme_descriptor *theme);
+
+/**
+ * Place a throbber into a toolbar window and initialise any theme-specific
+ * settings. Any previous incarnation of the throbber will be forgotten: this
+ * is for use when a new toolbar is being created, or when a toolbar has been
+ * deleted and rebuilt following a theme change.
+ *
+ * \param *throbber The throbber to rebuild.
+ * \param *theme The theme to apply (or NULL for current).
+ * \param style The theme style to apply.
+ * \param window The window that the throbber is in.
+ * \param shaded true if the bar should be throbber; else false.
+ * \return true on success; else false.
+ */
+
+bool ro_gui_throbber_rebuild(struct throbber *throbber,
+ struct theme_descriptor *theme, theme_style style,
+ wimp_w window, bool shaded);
+
+
+/**
+ * Destroy a throbber widget.
+ *
+ * \param *throbber The throbber to destroy.
+ */
+
+void ro_gui_throbber_destroy(struct throbber *throbber);
+
+
+/**
+ * Return the MINIMUM dimensions required by the throbber, in RO units,
+ * allowing for the current theme.
+ *
+ * \param *throbber The throbber of interest.
+ * \param *width Return the required width.
+ * \param *height Return the required height.
+ * \return true if values are returned; else false.
+ */
+
+bool ro_gui_throbber_get_dims(struct throbber *throbber,
+ int *width, int *height);
+
+
+/**
+ * Set or update the dimensions to be used by the throbber in RO units
+ *
+ * If these are greater than the minimum required, the throbber will fill
+ * the extended space; if less, the call will fail.
+ *
+ * \param throbber The throbber to update.
+ * \param x0 top left of bounding box x coordinate
+ * \param y0 top left of bounding box y coordinate
+ * \param x1 bottom right of bounding box x coordinate
+ * \param y1 bottom right of bounding box y coordinate
+ * \return true if size updated; else false.
+ */
+
+bool ro_gui_throbber_set_extent(struct throbber *throbber,
+ int x0, int y0, int x1, int y1);
+
+
+/**
+ * Show or hide a throbber.
+ *
+ * \param *throbber The throbber to hide.
+ * \param hide true to hide the throbber; false to show it.
+ * \return true if successful; else false.
+ */
+
+bool ro_gui_throbber_hide(struct throbber *throbber, bool hide);
+
+
+/**
+ * Translate mouse data into an interactive help message for the throbber.
+ *
+ * \param throbber The throbber to process.
+ * \param i The wimp icon under the pointer.
+ * \param screenpos The screen position.
+ * \param state The toolbar window state.
+ * \param buttons The mouse button state.
+ * \param suffix Return a help token suffix, or "" for none.
+ * \return true if handled exclusively; else false.
+ */
+
+bool ro_gui_throbber_help_suffix(struct throbber *throbber, wimp_i i,
+ os_coord *screenpos, wimp_window_state *state,
+ wimp_mouse_state buttons, const char **suffix);
+
+/**
+ * Start or update the amimation of a throbber.
+ *
+ * \param *throbber The throbber to amimate.
+ */
+
+bool ro_gui_throbber_animate(struct throbber *throbber);
+
+
+/**
+ * Stop the amimation of a throbber.
+ *
+ * \param *throbber The throbber to amimate.
+ */
+
+bool ro_gui_throbber_stop(struct throbber *throbber);
+
+#endif
+
diff --git a/frontends/riscos/gui/url_bar.c b/frontends/riscos/gui/url_bar.c
new file mode 100644
index 000000000..053014784
--- /dev/null
+++ b/frontends/riscos/gui/url_bar.c
@@ -0,0 +1,1344 @@
+/*
+ * Copyright 2004, 2005 Richard Wilson <info@tinct.net>
+ * Copyright 2011-2014 Stephen Fryatt <stevef@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * URL bars (implementation).
+ */
+
+#include <alloca.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include "oslib/os.h"
+#include "oslib/osspriteop.h"
+#include "oslib/wimp.h"
+
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/utf8.h"
+#include "utils/utils.h"
+#include "content/hlcache.h"
+#include "content/content.h"
+#include "desktop/browser.h"
+#include "desktop/plotters.h"
+
+#include "riscos/gui.h"
+#include "riscos/hotlist.h"
+#include "riscos/gui/url_bar.h"
+#include "riscos/theme.h"
+#include "riscos/url_suggest.h"
+#include "riscos/wimp.h"
+#include "riscos/wimp_event.h"
+#include "riscos/window.h"
+#include "riscos/ucstables.h"
+#include "riscos/filetype.h"
+
+#define URLBAR_HEIGHT 52
+#define URLBAR_FAVICON_SIZE 16
+#define URLBAR_HOTLIST_SIZE 17
+#define URLBAR_FAVICON_WIDTH ((5 + URLBAR_FAVICON_SIZE + 5) * 2)
+#define URLBAR_HOTLIST_WIDTH ((5 + URLBAR_HOTLIST_SIZE + 5) * 2)
+#define URLBAR_MIN_WIDTH 52
+#define URLBAR_GRIGHT_GUTTER 8
+#define URLBAR_FAVICON_NAME_LENGTH 12
+
+struct url_bar {
+ /** The applied theme (or NULL to use the default) */
+ struct theme_descriptor *theme;
+
+ /** The widget dimensions. */
+ int x_min, y_min;
+
+ /** The window and icon details. */
+ wimp_w window;
+ os_box extent;
+
+ wimp_i container_icon;
+
+ char favicon_sprite[URLBAR_FAVICON_NAME_LENGTH];
+ int favicon_type;
+ struct hlcache_handle *favicon_content;
+ os_box favicon_extent;
+ os_coord favicon_offset;
+ int favicon_width, favicon_height;
+
+ wimp_i text_icon;
+ char *text_buffer;
+ size_t text_size;
+ char *text_buffer_utf8;
+
+ wimp_i suggest_icon;
+ int suggest_x, suggest_y;
+
+ bool hidden;
+ bool display;
+ bool shaded;
+
+ struct {
+ bool set;
+ os_box extent;
+ os_coord offset;
+ } hotlist;
+};
+
+static char text_validation[] = "Pptr_write;KN";
+static char suggest_icon[] = "gright";
+static char suggest_validation[] = "R5;Sgright,pgright";
+static char null_text_string[] = "";
+
+struct url_bar_resource {
+ const char *url;
+ struct hlcache_handle *c;
+ int height;
+ bool ready;
+}; /**< Treeview content resource data */
+enum url_bar_resource_id {
+ URLBAR_RES_HOTLIST_ADD = 0,
+ URLBAR_RES_HOTLIST_REMOVE,
+ URLBAR_RES_LAST
+};
+static struct url_bar_resource url_bar_res[URLBAR_RES_LAST] = {
+ { "resource:icons/hotlist-add.png", NULL, 0, false },
+ { "resource:icons/hotlist-rmv.png", NULL, 0, false }
+}; /**< Treeview content resources */
+
+
+static void ro_gui_url_bar_set_hotlist(struct url_bar *url_bar, bool set);
+
+
+/* This is an exported interface documented in url_bar.h */
+
+struct url_bar *ro_gui_url_bar_create(struct theme_descriptor *theme)
+{
+ struct url_bar *url_bar;
+
+ /* Allocate memory. */
+
+ url_bar = malloc(sizeof(struct url_bar));
+ if (url_bar == NULL) {
+ LOG("No memory for malloc()");
+ return NULL;
+ }
+
+ /* Set up default parameters. */
+
+ url_bar->theme = theme;
+
+ url_bar->display = false;
+ url_bar->shaded = false;
+
+ url_bar->x_min = URLBAR_FAVICON_WIDTH + URLBAR_MIN_WIDTH +
+ URLBAR_HOTLIST_WIDTH;
+ url_bar->y_min = URLBAR_HEIGHT;
+
+ url_bar->extent.x0 = 0;
+ url_bar->extent.y0 = 0;
+ url_bar->extent.x1 = 0;
+ url_bar->extent.y1 = 0;
+
+ url_bar->window = NULL;
+ url_bar->container_icon = -1;
+ url_bar->text_icon = -1;
+ url_bar->suggest_icon = -1;
+
+ url_bar->favicon_extent.x0 = 0;
+ url_bar->favicon_extent.y0 = 0;
+ url_bar->favicon_extent.x1 = 0;
+ url_bar->favicon_extent.y1 = 0;
+ url_bar->favicon_width = 0;
+ url_bar->favicon_height = 0;
+ url_bar->favicon_content = NULL;
+ url_bar->favicon_type = 0;
+ strncpy(url_bar->favicon_sprite, "Ssmall_xxx",
+ URLBAR_FAVICON_NAME_LENGTH);
+
+ url_bar->hotlist.set = false;
+ url_bar->hotlist.extent.x0 = 0;
+ url_bar->hotlist.extent.y0 = 0;
+ url_bar->hotlist.extent.x1 = 0;
+ url_bar->hotlist.extent.y1 = 0;
+
+ url_bar->text_size = RO_GUI_MAX_URL_SIZE;
+ url_bar->text_buffer = malloc(url_bar->text_size);
+ if (url_bar->text_buffer == NULL) {
+ free(url_bar);
+ return NULL;
+ }
+ url_bar->text_buffer[0] = 0;
+ url_bar->text_buffer_utf8 = NULL;
+
+ url_bar->hidden = false;
+
+ return url_bar;
+}
+
+
+/**
+ * Position the icons in the URL bar to take account of the currently
+ * configured extent.
+ *
+ * \param *url_bar The URL bar to update.
+ * \param full true to resize everything; false to move only
+ * the right-hand end of the bar.
+ * \return true if successful; else false.
+ */
+
+static bool ro_gui_url_bar_icon_resize(struct url_bar *url_bar, bool full)
+{
+ int x0, y0, x1, y1;
+ int centre;
+ os_error *error;
+ os_coord eig = {1, 1};
+ wimp_caret caret;
+
+ if (url_bar == NULL || url_bar->window == NULL)
+ return false;
+
+ /* calculate 1px in OS units */
+ ro_convert_pixels_to_os_units(&eig, (os_mode) -1);
+
+ /* The vertical centre line of the widget's extent. */
+
+ centre = url_bar->extent.y0 +
+ (url_bar->extent.y1 - url_bar->extent.y0) / 2;
+
+ /* Position the container icon. */
+
+ if (url_bar->container_icon != -1) {
+ x0 = url_bar->extent.x0;
+ x1 = url_bar->extent.x1 -
+ url_bar->suggest_x - URLBAR_GRIGHT_GUTTER;
+
+ y0 = centre - (URLBAR_HEIGHT / 2);
+ y1 = y0 + URLBAR_HEIGHT;
+
+ error = xwimp_resize_icon(url_bar->window,
+ url_bar->container_icon,
+ x0, y0, x1, y1);
+ if (error != NULL) {
+ LOG("xwimp_resize_icon: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ url_bar->container_icon = -1;
+ return false;
+ }
+ }
+
+ /* Position the URL Suggest icon. */
+
+ if (url_bar->suggest_icon != -1) {
+ x0 = url_bar->extent.x1 - url_bar->suggest_x;
+ x1 = url_bar->extent.x1;
+
+ y0 = centre - (url_bar->suggest_y / 2);
+ y1 = y0 + url_bar->suggest_y;
+
+ error = xwimp_resize_icon(url_bar->window,
+ url_bar->suggest_icon,
+ x0, y0, x1, y1);
+ if (error != NULL) {
+ LOG("xwimp_resize_icon: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ url_bar->suggest_icon = -1;
+ return false;
+ }
+ }
+
+ /* Position the Text icon. */
+
+ if (url_bar->text_icon != -1) {
+ x0 = url_bar->extent.x0 + URLBAR_FAVICON_WIDTH;
+ x1 = url_bar->extent.x1 - eig.x - URLBAR_HOTLIST_WIDTH -
+ url_bar->suggest_x - URLBAR_GRIGHT_GUTTER;
+
+ y0 = centre - (URLBAR_HEIGHT / 2) + eig.y;
+ y1 = y0 + URLBAR_HEIGHT - 2 * eig.y;
+
+ error = xwimp_resize_icon(url_bar->window,
+ url_bar->text_icon,
+ x0, y0, x1, y1);
+ if (error != NULL) {
+ LOG("xwimp_resize_icon: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ url_bar->text_icon = -1;
+ return false;
+ }
+
+ if (xwimp_get_caret_position(&caret) == NULL) {
+ if ((caret.w == url_bar->window) &&
+ (caret.i == url_bar->text_icon)) {
+ xwimp_set_caret_position(url_bar->window,
+ url_bar->text_icon, caret.pos.x,
+ caret.pos.y, -1, caret.index);
+ }
+ }
+ }
+
+ /* Position the Favicon icon. */
+
+ url_bar->favicon_extent.x0 = url_bar->extent.x0 + eig.x;
+ url_bar->favicon_extent.x1 = url_bar->extent.x0 + URLBAR_FAVICON_WIDTH;
+ url_bar->favicon_extent.y0 = centre - (URLBAR_HEIGHT / 2) + eig.y;
+ url_bar->favicon_extent.y1 = url_bar->favicon_extent.y0 + URLBAR_HEIGHT
+ - 2 * eig.y;
+
+ /* Position the Hotlist icon. */
+
+ url_bar->hotlist.extent.x0 = url_bar->extent.x1 - eig.x -
+ URLBAR_HOTLIST_WIDTH - url_bar->suggest_x -
+ URLBAR_GRIGHT_GUTTER;
+ url_bar->hotlist.extent.x1 = url_bar->hotlist.extent.x0 +
+ URLBAR_HOTLIST_WIDTH;
+ url_bar->hotlist.extent.y0 = centre - (URLBAR_HEIGHT / 2) + eig.y;
+ url_bar->hotlist.extent.y1 = url_bar->hotlist.extent.y0 + URLBAR_HEIGHT
+ - 2 * eig.y;
+
+ url_bar->hotlist.offset.x = ((url_bar->hotlist.extent.x1 -
+ url_bar->hotlist.extent.x0) -
+ (URLBAR_HOTLIST_SIZE * 2)) / 2;
+ url_bar->hotlist.offset.y = ((url_bar->hotlist.extent.y1 -
+ url_bar->hotlist.extent.y0) -
+ (URLBAR_HOTLIST_SIZE * 2)) / 2 - 1;
+
+ return true;
+}
+
+
+/**
+ * Create or delete a URL bar's icons if required to bring it into sync with
+ * the current hidden setting.
+ *
+ * \param *url_bar The URL bar to update.
+ * \return true if successful; else false.
+ */
+
+static bool ro_gui_url_bar_icon_update(struct url_bar *url_bar)
+{
+ wimp_icon_create icon;
+ os_error *error;
+ bool resize;
+
+ if (url_bar == NULL || url_bar->window == NULL)
+ return false;
+
+ icon.w = url_bar->window;
+ icon.icon.extent.x0 = 0;
+ icon.icon.extent.y0 = 0;
+ icon.icon.extent.x1 = 0;
+ icon.icon.extent.y1 = 0;
+
+ resize = false;
+
+ /* Create or delete the container icon. */
+
+ if (!url_bar->hidden && url_bar->container_icon == -1) {
+ icon.icon.flags = wimp_ICON_BORDER |
+ (wimp_COLOUR_BLACK <<
+ wimp_ICON_FG_COLOUR_SHIFT) |
+ (wimp_BUTTON_DOUBLE_CLICK_DRAG <<
+ wimp_ICON_BUTTON_TYPE_SHIFT);
+ error = xwimp_create_icon(&icon, &url_bar->container_icon);
+ if (error != NULL) {
+ LOG("xwimp_create_icon: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ url_bar->container_icon = -1;
+ return false;
+ }
+
+ resize = true;
+ } else if (url_bar->hidden && url_bar->container_icon != -1){
+ error = xwimp_delete_icon(url_bar->window,
+ url_bar->container_icon);
+ if (error != NULL) {
+ LOG("xwimp_delete_icon: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return false;
+ }
+
+ url_bar->container_icon = -1;
+ }
+
+ /* Create or delete the text icon. */
+
+ if (!url_bar->hidden && url_bar->text_icon == -1) {
+ icon.icon.data.indirected_text.text = url_bar->text_buffer;
+ icon.icon.data.indirected_text.validation = text_validation;
+ icon.icon.data.indirected_text.size = url_bar->text_size;
+ icon.icon.flags = wimp_ICON_TEXT | wimp_ICON_INDIRECTED |
+ wimp_ICON_VCENTRED | wimp_ICON_FILLED |
+ (wimp_COLOUR_BLACK <<
+ wimp_ICON_FG_COLOUR_SHIFT);
+ if (url_bar->display)
+ icon.icon.flags |= (wimp_BUTTON_NEVER <<
+ wimp_ICON_BUTTON_TYPE_SHIFT);
+ else
+ icon.icon.flags |= (wimp_BUTTON_WRITE_CLICK_DRAG <<
+ wimp_ICON_BUTTON_TYPE_SHIFT);
+ error = xwimp_create_icon(&icon, &url_bar->text_icon);
+ if (error) {
+ LOG("xwimp_create_icon: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ url_bar->text_icon = -1;
+ return false;
+ }
+
+ resize = true;
+ } else if (url_bar->hidden && url_bar->text_icon != -1) {
+ error = xwimp_delete_icon(url_bar->window,
+ url_bar->text_icon);
+ if (error != NULL) {
+ LOG("xwimp_delete_icon: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return false;
+ }
+
+ url_bar->text_icon = -1;
+ }
+
+ /* Create or delete the suggest icon. */
+
+ if (!url_bar->hidden && url_bar->suggest_icon == -1) {
+ icon.icon.data.indirected_text.text = null_text_string;
+ icon.icon.data.indirected_text.size = 1;
+ icon.icon.data.indirected_text.validation = suggest_validation;
+ icon.icon.flags = wimp_ICON_TEXT | wimp_ICON_SPRITE |
+ wimp_ICON_INDIRECTED | wimp_ICON_HCENTRED |
+ wimp_ICON_VCENTRED | (wimp_BUTTON_CLICK <<
+ wimp_ICON_BUTTON_TYPE_SHIFT);
+ error = xwimp_create_icon(&icon, &url_bar->suggest_icon);
+ if (error) {
+ LOG("xwimp_create_icon: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return false;
+ }
+
+ if (!url_bar->display)
+ ro_gui_wimp_event_register_menu_gright(url_bar->window,
+ wimp_ICON_WINDOW, url_bar->suggest_icon,
+ ro_gui_url_suggest_menu);
+
+ if (!ro_gui_url_bar_update_urlsuggest(url_bar))
+ return false;
+
+ resize = true;
+ } else if (url_bar->hidden && url_bar->suggest_icon != -1) {
+ ro_gui_wimp_event_deregister(url_bar->window,
+ url_bar->suggest_icon);
+ error = xwimp_delete_icon(url_bar->window,
+ url_bar->suggest_icon);
+ if (error != NULL) {
+ LOG("xwimp_delete_icon: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return false;
+ }
+
+ url_bar->suggest_icon = -1;
+ }
+
+ /* If any icons were created, resize the bar. */
+
+ if (resize && !ro_gui_url_bar_icon_resize(url_bar, true))
+ return false;
+
+ /* If there are any icons, apply shading as necessary. */
+
+ if (url_bar->container_icon != -1)
+ ro_gui_set_icon_shaded_state(url_bar->window,
+ url_bar->container_icon, url_bar->shaded);
+
+ if (url_bar->text_icon != -1)
+ ro_gui_set_icon_shaded_state(url_bar->window,
+ url_bar->text_icon, url_bar->shaded);
+
+ if (url_bar->suggest_icon != -1)
+ ro_gui_set_icon_shaded_state(url_bar->window,
+ url_bar->suggest_icon, url_bar->shaded);
+
+ return true;
+}
+
+
+/* This is an exported interface documented in url_bar.h */
+
+bool ro_gui_url_bar_rebuild(struct url_bar *url_bar,
+ struct theme_descriptor *theme, theme_style style,
+ wimp_w window, bool display, bool shaded)
+{
+ if (url_bar == NULL)
+ return false;
+
+ url_bar->theme = theme;
+ url_bar->window = window;
+
+ url_bar->display = display;
+ url_bar->shaded = shaded;
+
+ url_bar->container_icon = -1;
+ url_bar->text_icon = -1;
+ url_bar->suggest_icon = -1;
+
+ ro_gui_wimp_get_sprite_dimensions((osspriteop_area *) -1,
+ suggest_icon, &url_bar->suggest_x, &url_bar->suggest_y);
+
+ url_bar->x_min = URLBAR_FAVICON_WIDTH + URLBAR_MIN_WIDTH +
+ URLBAR_HOTLIST_WIDTH + URLBAR_GRIGHT_GUTTER +
+ url_bar->suggest_x;
+ url_bar->y_min = (url_bar->suggest_y > URLBAR_HEIGHT) ?
+ url_bar->suggest_y : URLBAR_HEIGHT;
+
+ return ro_gui_url_bar_icon_update(url_bar);
+}
+
+
+/* This is an exported interface documented in url_bar.h */
+
+void ro_gui_url_bar_destroy(struct url_bar *url_bar)
+{
+ if (url_bar == NULL)
+ return;
+
+ if (url_bar->text_buffer_utf8 != NULL)
+ free(url_bar->text_buffer_utf8);
+
+ if (url_bar->text_buffer != NULL)
+ free(url_bar->text_buffer);
+
+ free(url_bar);
+}
+
+
+/* This is an exported interface documented in url_bar.h */
+
+bool ro_gui_url_bar_get_dims(struct url_bar *url_bar,
+ int *width, int *height)
+{
+ if (url_bar == NULL)
+ return false;
+
+ if (url_bar->x_min != -1 && url_bar->y_min != -1) {
+ if (width != NULL)
+ *width = url_bar->x_min;
+ if (height != NULL)
+ *height = url_bar->y_min;
+
+ return true;
+ }
+
+ return false;
+}
+
+
+/* This is an exported interface documented in url_bar.h */
+
+bool ro_gui_url_bar_set_extent(struct url_bar *url_bar,
+ int x0, int y0, int x1, int y1)
+{
+ bool stretch;
+
+ if (url_bar == NULL)
+ return false;
+
+ if ((x1 - x0) < url_bar->x_min || (y1 - y0) < url_bar->y_min)
+ return false;
+
+ if (url_bar->extent.x0 == x0 && url_bar->extent.y0 == y0 &&
+ url_bar->extent.x1 == x1 &&
+ url_bar->extent.y1 == y1)
+ return true;
+
+ /* If it's only the length that changes, less needs to be updated. */
+
+ stretch = (url_bar->extent.x0 == x0 && url_bar->extent.y0 == y0 &&
+ url_bar->extent.y1 == y1) ? true : false;
+
+ /* Redraw the relevant bits of the toolbar. */
+
+ if (url_bar->window != NULL && !url_bar->hidden) {
+ if (stretch) {
+ xwimp_force_redraw(url_bar->window,
+ x0 + URLBAR_FAVICON_WIDTH, y0,
+ (x1 > url_bar->extent.x1) ?
+ x1 : url_bar->extent.x1, y1);
+ } else {
+ xwimp_force_redraw(url_bar->window,
+ url_bar->extent.x0, url_bar->extent.y0,
+ url_bar->extent.x1, url_bar->extent.y1);
+ xwimp_force_redraw(url_bar->window, x0, y0, x1, y1);
+ }
+ }
+
+ /* Reposition the URL bar icons. */
+
+ url_bar->extent.x0 = x0;
+ url_bar->extent.y0 = y0;
+ url_bar->extent.x1 = x1;
+ url_bar->extent.y1 = y1;
+
+ return ro_gui_url_bar_icon_resize(url_bar, !stretch);
+}
+
+
+/* This is an exported interface documented in url_bar.h */
+
+bool ro_gui_url_bar_hide(struct url_bar *url_bar, bool hide)
+{
+ if (url_bar == NULL || url_bar->hidden == hide)
+ return (url_bar == NULL) ? false : true;
+
+ url_bar->hidden = hide;
+
+ return ro_gui_url_bar_icon_update(url_bar);
+}
+
+
+/* This is an exported interface documented in url_bar.h */
+
+void ro_gui_url_bar_redraw(struct url_bar *url_bar, wimp_draw *redraw)
+{
+ wimp_icon icon;
+ struct rect clip;
+ bool draw_favicon = true;
+ bool draw_hotlist = true;
+
+ /* Test for a valid URL bar */
+ if (url_bar == NULL || url_bar->hidden)
+ return;
+
+ if ((redraw->clip.x0 - (redraw->box.x0 - redraw->xscroll)) >
+ (url_bar->favicon_extent.x1) ||
+ (redraw->clip.y0 - (redraw->box.y1 - redraw->yscroll)) >
+ (url_bar->favicon_extent.y1) ||
+ (redraw->clip.x1 - (redraw->box.x0 - redraw->xscroll)) <
+ (url_bar->favicon_extent.x0) ||
+ (redraw->clip.y1 - (redraw->box.y1 - redraw->yscroll)) <
+ (url_bar->favicon_extent.y0)) {
+ /* Favicon not in redraw area */
+ draw_favicon = false;
+ }
+
+ if ((redraw->clip.x0 - (redraw->box.x0 - redraw->xscroll)) >
+ (url_bar->hotlist.extent.x1) ||
+ (redraw->clip.y0 - (redraw->box.y1 - redraw->yscroll)) >
+ (url_bar->hotlist.extent.y1) ||
+ (redraw->clip.x1 - (redraw->box.x0 - redraw->xscroll)) <
+ (url_bar->hotlist.extent.x0) ||
+ (redraw->clip.y1 - (redraw->box.y1 - redraw->yscroll)) <
+ (url_bar->hotlist.extent.y0)) {
+ /* Hotlist icon not in redraw area */
+ draw_hotlist = false;
+ }
+
+ if (draw_favicon) {
+ if (url_bar->favicon_content == NULL) {
+ icon.data.indirected_text.text = null_text_string;
+ icon.data.indirected_text.validation =
+ url_bar->favicon_sprite;
+ icon.data.indirected_text.size = 1;
+ icon.flags = wimp_ICON_TEXT | wimp_ICON_SPRITE |
+ wimp_ICON_INDIRECTED |
+ wimp_ICON_FILLED |
+ wimp_ICON_HCENTRED |
+ wimp_ICON_VCENTRED;
+ icon.extent.x0 = url_bar->favicon_extent.x0;
+ icon.extent.x1 = url_bar->favicon_extent.x1;
+ icon.extent.y0 = url_bar->favicon_extent.y0;
+ icon.extent.y1 = url_bar->favicon_extent.y1;
+
+ xwimp_plot_icon(&icon);
+ } else {
+ struct content_redraw_data data;
+ struct redraw_context ctx = {
+ .interactive = true,
+ .background_images = true,
+ .plot = &ro_plotters
+ };
+
+ xwimp_set_colour(wimp_COLOUR_WHITE);
+ xos_plot(os_MOVE_TO,
+ (redraw->box.x0 - redraw->xscroll) +
+ url_bar->favicon_extent.x0,
+ (redraw->box.y1 - redraw->yscroll) +
+ url_bar->favicon_extent.y0);
+ xos_plot(os_PLOT_TO | os_PLOT_RECTANGLE,
+ (redraw->box.x0 - redraw->xscroll) +
+ url_bar->favicon_extent.x1,
+ (redraw->box.y1 - redraw->yscroll) +
+ url_bar->favicon_extent.y1);
+
+ clip.x0 = (redraw->clip.x0 - ro_plot_origin_x) / 2;
+ clip.y0 = (ro_plot_origin_y - redraw->clip.y0) / 2;
+ clip.x1 = (redraw->clip.x1 - ro_plot_origin_x) / 2;
+ clip.y1 = (ro_plot_origin_y - redraw->clip.y1) / 2;
+
+ data.x = (url_bar->favicon_extent.x0 +
+ url_bar->favicon_offset.x) / 2;
+ data.y = (url_bar->favicon_offset.y -
+ url_bar->favicon_extent.y1) / 2;
+ data.width = url_bar->favicon_width;
+ data.height = url_bar->favicon_height;
+ data.background_colour = 0xFFFFFF;
+ data.scale = 1;
+ data.repeat_x = false;
+ data.repeat_y = false;
+
+ content_redraw(url_bar->favicon_content,
+ &data, &clip, &ctx);
+ }
+ }
+
+ if (draw_hotlist) {
+ struct content_redraw_data data;
+ struct redraw_context ctx = {
+ .interactive = true,
+ .background_images = true,
+ .plot = &ro_plotters
+ };
+ struct url_bar_resource *hotlist_icon = url_bar->hotlist.set ?
+ &(url_bar_res[URLBAR_RES_HOTLIST_REMOVE]) :
+ &(url_bar_res[URLBAR_RES_HOTLIST_ADD]);
+
+ xwimp_set_colour(wimp_COLOUR_WHITE);
+ xos_plot(os_MOVE_TO,
+ (redraw->box.x0 - redraw->xscroll) +
+ url_bar->hotlist.extent.x0,
+ (redraw->box.y1 - redraw->yscroll) +
+ url_bar->hotlist.extent.y0);
+ xos_plot(os_PLOT_TO | os_PLOT_RECTANGLE,
+ (redraw->box.x0 - redraw->xscroll) +
+ url_bar->hotlist.extent.x1,
+ (redraw->box.y1 - redraw->yscroll) +
+ url_bar->hotlist.extent.y1);
+
+ if (hotlist_icon->ready == false) {
+ return;
+ }
+
+ clip.x0 = (redraw->clip.x0 - ro_plot_origin_x) / 2;
+ clip.y0 = (ro_plot_origin_y - redraw->clip.y0) / 2;
+ clip.x1 = (redraw->clip.x1 - ro_plot_origin_x) / 2;
+ clip.y1 = (ro_plot_origin_y - redraw->clip.y1) / 2;
+
+ data.x = (url_bar->hotlist.extent.x0 +
+ url_bar->hotlist.offset.x) / 2;
+ data.y = (url_bar->hotlist.offset.y -
+ url_bar->hotlist.extent.y1) / 2;
+ data.width = URLBAR_HOTLIST_SIZE;
+ data.height = URLBAR_HOTLIST_SIZE;
+ data.background_colour = 0xFFFFFF;
+ data.scale = 1;
+ data.repeat_x = false;
+ data.repeat_y = false;
+
+ content_redraw(hotlist_icon->c, &data, &clip, &ctx);
+ }
+}
+
+
+/* This is an exported interface documented in url_bar.h */
+
+bool ro_gui_url_bar_click(struct url_bar *url_bar,
+ wimp_pointer *pointer, wimp_window_state *state,
+ url_bar_action *action)
+{
+ os_coord pos;
+
+ if (url_bar == NULL || url_bar->hidden ||
+ url_bar->display || url_bar->shaded)
+ return false;
+
+ /* Check that the click was within our part of the window. */
+
+ pos.x = pointer->pos.x - state->visible.x0 + state->xscroll;
+ pos.y = pointer->pos.y - state->visible.y1 + state->yscroll;
+
+ if (pos.x < url_bar->extent.x0 || pos.x > url_bar->extent.x1 ||
+ pos.y < url_bar->extent.y0 ||
+ pos.y > url_bar->extent.y1)
+ return false;
+
+ /* If we have a Select or Adjust click, check if it originated on the
+ * hotlist icon; if it did, return an event.
+ */
+
+ if (pointer->buttons == wimp_SINGLE_SELECT ||
+ pointer->buttons == wimp_SINGLE_ADJUST) {
+ if (pos.x >= url_bar->hotlist.extent.x0 &&
+ pos.x <= url_bar->hotlist.extent.x1 &&
+ pos.y >= url_bar->hotlist.extent.y0 &&
+ pos.y <= url_bar->hotlist.extent.y1) {
+ if (pointer->buttons == wimp_SINGLE_SELECT &&
+ action != NULL)
+ *action = TOOLBAR_URL_SELECT_HOTLIST;
+ else if (pointer->buttons == wimp_SINGLE_ADJUST &&
+ action != NULL)
+ *action = TOOLBAR_URL_ADJUST_HOTLIST;
+ return true;
+ }
+ }
+
+ /* If we find a Select or Adjust drag, check if it originated on the
+ * URL bar or over the favicon. If either, then return an event.
+ */
+
+ if (pointer->buttons == wimp_DRAG_SELECT ||
+ pointer->buttons == wimp_DRAG_ADJUST) {
+ if (pointer->i == url_bar->text_icon) {
+ if (action != NULL)
+ *action = TOOLBAR_URL_DRAG_URL;
+ return true;
+ }
+
+ if (pos.x >= url_bar->favicon_extent.x0 &&
+ pos.x <= url_bar->favicon_extent.x1 &&
+ pos.y >= url_bar->favicon_extent.y0 &&
+ pos.y <= url_bar->favicon_extent.y1) {
+ if (action != NULL)
+ *action = TOOLBAR_URL_DRAG_FAVICON;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+/* This is an exported interface documented in url_bar.h */
+
+bool ro_gui_url_bar_menu_prepare(struct url_bar *url_bar, wimp_i i,
+ wimp_menu *menu, wimp_pointer *pointer)
+{
+ if (url_bar == NULL || url_bar->suggest_icon != i ||
+ menu != ro_gui_url_suggest_menu)
+ return false;
+
+ if (pointer != NULL)
+ return ro_gui_url_suggest_prepare_menu();
+
+ return true;
+}
+
+
+/* This is an exported interface documented in url_bar.h */
+
+bool ro_gui_url_bar_menu_select(struct url_bar *url_bar, wimp_i i,
+ wimp_menu *menu, wimp_selection *selection, menu_action action)
+{
+ const char *urltxt;
+ struct gui_window *g;
+
+ if (url_bar == NULL || url_bar->suggest_icon != i ||
+ menu != ro_gui_url_suggest_menu)
+ return false;
+
+ urltxt = ro_gui_url_suggest_get_selection(selection);
+ g = ro_gui_toolbar_lookup(url_bar->window);
+
+ if (urltxt != NULL && g != NULL && g->bw != NULL) {
+ nsurl *url;
+ nserror error;
+
+ error = nsurl_create(urltxt, &url);
+ if (error != NSERROR_OK) {
+ ro_warn_user(messages_get_errorcode(error), 0);
+ } else {
+ ro_gui_window_set_url(g, url);
+
+ browser_window_navigate(g->bw,
+ url,
+ NULL,
+ BW_NAVIGATE_HISTORY,
+ NULL,
+ NULL,
+ NULL);
+ nsurl_unref(url);
+ }
+ }
+
+ return true;
+}
+
+
+/* This is an exported interface documented in url_bar.h */
+
+bool ro_gui_url_bar_help_suffix(struct url_bar *url_bar, wimp_i i,
+ os_coord *mouse, wimp_window_state *state,
+ wimp_mouse_state buttons, const char **suffix)
+{
+ os_coord pos;
+
+ if (url_bar == NULL || url_bar->hidden)
+ return false;
+
+ /* Check that the click was within our part of the window. */
+
+ pos.x = mouse->x - state->visible.x0 + state->xscroll;
+ pos.y = mouse->y - state->visible.y1 + state->yscroll;
+
+ if (pos.x < url_bar->extent.x0 || pos.x > url_bar->extent.x1 ||
+ pos.y < url_bar->extent.y0 ||
+ pos.y > url_bar->extent.y1)
+ return false;
+
+ /* Return hard-coded icon numbers that match the ones that were
+ * always allocated to the URL bar in a previous implementation.
+ * If Messages can be updated, this could be changed.
+ */
+
+ if (i == url_bar->text_icon)
+ *suffix = "14";
+ else if (i == url_bar->suggest_icon)
+ *suffix = "15";
+ else if (pos.x >= url_bar->hotlist.extent.x0 &&
+ pos.x <= url_bar->hotlist.extent.x1 &&
+ pos.y >= url_bar->hotlist.extent.y0 &&
+ pos.y <= url_bar->hotlist.extent.y1)
+ *suffix = "Hot";
+ else if (pos.x >= url_bar->favicon_extent.x0 &&
+ pos.x <= url_bar->favicon_extent.x1 &&
+ pos.y >= url_bar->favicon_extent.y0 &&
+ pos.y <= url_bar->favicon_extent.y1)
+ *suffix = "Fav";
+ else
+ *suffix = "";
+
+ return true;
+}
+
+
+/* This is an exported interface documented in url_bar.h */
+
+bool ro_gui_url_bar_take_caret(struct url_bar *url_bar)
+{
+ os_error *error;
+
+ if (url_bar == NULL || url_bar->hidden)
+ return false;
+
+ error = xwimp_set_caret_position(url_bar->window, url_bar->text_icon,
+ -1, -1, -1, 0);
+ if (error) {
+ LOG("xwimp_set_caret_position: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+
+ return false;
+ }
+
+ return true;
+}
+
+
+/* This is an exported interface documented in url_bar.h */
+
+void ro_gui_url_bar_set_url(struct url_bar *url_bar, const char *url,
+ bool is_utf8, bool set_caret)
+{
+ wimp_caret caret;
+ os_error *error;
+ char *local_text = NULL;
+ const char *local_url;
+ nsurl *n;
+
+ if (url_bar == NULL || url_bar->text_buffer == NULL || url == NULL)
+ return;
+
+ /* Before we do anything with the URL, get it into local encoding so
+ * that behaviour is consistant with the rest of the URL Bar module
+ * (which will act on the icon's text buffer, which is always in local
+ * encoding).
+ */
+
+ if (is_utf8) {
+ nserror err;
+
+ err = utf8_to_local_encoding(url, 0, &local_text);
+ if (err != NSERROR_OK) {
+ /* A bad encoding should never happen, so assert this */
+ assert(err != NSERROR_BAD_ENCODING);
+ LOG("utf8_to_enc failed");
+ /* Paranoia */
+ local_text = NULL;
+ }
+ local_url = (local_text != NULL) ? local_text : url;
+ } else {
+ local_url = url;
+ }
+
+ /* Copy the text into the icon buffer. If the text is too long, blank
+ * the buffer and warn the user.
+ */
+
+ if (strlen(local_url) >= url_bar->text_size) {
+ url_bar->text_buffer[0] = '\0';
+ ro_warn_user("LongURL", NULL);
+ LOG("Long URL (%zu chars): %s", strlen(url), url);
+ } else {
+ strncpy(url_bar->text_buffer, local_url,
+ url_bar->text_size - 1);
+ url_bar->text_buffer[url_bar->text_size - 1] = '\0';
+ }
+
+ if (local_text != NULL)
+ free(local_text);
+
+ /* Set the hotlist flag. */
+
+ if (nsurl_create(url_bar->text_buffer, &n) == NSERROR_OK) {
+ ro_gui_url_bar_set_hotlist(url_bar, ro_gui_hotlist_has_page(n));
+ nsurl_unref(n);
+ }
+
+ /* If there's no icon, then there's nothing else to do... */
+
+ if (url_bar->text_icon == -1)
+ return;
+
+ /* ...if there is, redraw the icon and fix the caret's position. */
+
+ ro_gui_redraw_icon(url_bar->window, url_bar->text_icon);
+
+ error = xwimp_get_caret_position(&caret);
+ if (error) {
+ LOG("xwimp_get_caret_position: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ if (set_caret || (caret.w == url_bar->window &&
+ caret.i == url_bar->text_icon)) {
+ const char *set_url = ro_gui_get_icon_string(url_bar->window,
+ url_bar->text_icon);
+
+ error = xwimp_set_caret_position(url_bar->window,
+ url_bar->text_icon, 0, 0, -1, strlen(set_url));
+ if (error) {
+ LOG("xwimp_set_caret_position: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+ }
+}
+
+
+/* This is an exported interface documented in url_bar.h */
+
+void ro_gui_url_bar_update_hotlist(struct url_bar *url_bar)
+{
+ const char *url;
+ nsurl *n;
+
+ if (url_bar == NULL)
+ return;
+
+ url = (const char *) url_bar->text_buffer;
+ if (url != NULL && nsurl_create(url, &n) == NSERROR_OK) {
+ ro_gui_url_bar_set_hotlist(url_bar, ro_gui_hotlist_has_page(n));
+ nsurl_unref(n);
+ }
+}
+
+
+/**
+ * Set the state of a URL Bar's hotlist icon.
+ *
+ * \param *url_bar The URL Bar to update.
+ * \param set TRUE to set the hotlist icon; FALSE to clear it.
+ */
+
+static void ro_gui_url_bar_set_hotlist(struct url_bar *url_bar, bool set)
+{
+ if (url_bar == NULL || set == url_bar->hotlist.set)
+ return;
+
+ url_bar->hotlist.set = set;
+
+ if (!url_bar->hidden) {
+ xwimp_force_redraw(url_bar->window,
+ url_bar->hotlist.extent.x0,
+ url_bar->hotlist.extent.y0,
+ url_bar->hotlist.extent.x1,
+ url_bar->hotlist.extent.y1);
+ }
+}
+
+
+/* This is an exported interface documented in url_bar.h */
+
+const char *ro_gui_url_bar_get_url(struct url_bar *url_bar)
+{
+ if ((url_bar == NULL) || (url_bar->text_buffer == NULL))
+ return NULL;
+
+ if (url_bar->text_buffer_utf8 != NULL) {
+ free(url_bar->text_buffer_utf8);
+ url_bar->text_buffer_utf8 = NULL;
+ }
+
+ if (url_bar->text_buffer[0] == '\0')
+ return (const char *) url_bar->text_buffer;
+
+ if (utf8_from_local_encoding(url_bar->text_buffer, 0, &url_bar->text_buffer_utf8) == NSERROR_OK) {
+ return (const char *) url_bar->text_buffer_utf8;
+ }
+
+ return (const char *) url_bar->text_buffer;
+}
+
+
+/* This is an exported interface documented in url_bar.h */
+
+bool ro_gui_url_bar_get_url_extent(struct url_bar *url_bar, os_box *extent)
+{
+ wimp_icon_state state;
+ os_error *error;
+
+ if (url_bar == NULL || url_bar->hidden)
+ return false;
+
+ if (extent == NULL)
+ return true;
+
+ state.w = url_bar->window;
+ state.i = url_bar->container_icon;
+ error = xwimp_get_icon_state(&state);
+ if (error) {
+ LOG("xwimp_get_icon_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return false;
+ }
+
+ extent->x0 = state.icon.extent.x0;
+ extent->y0 = state.icon.extent.y0;
+ extent->x1 = state.icon.extent.x1;
+ extent->y1 = state.icon.extent.y1;
+
+ return true;
+}
+
+
+/* This is an exported interface documented in url_bar.h */
+
+bool ro_gui_url_bar_test_for_text_field_click(struct url_bar *url_bar,
+ wimp_pointer *pointer)
+{
+ if (url_bar == NULL || url_bar->hidden || pointer == NULL)
+ return false;
+
+ return (pointer->w == url_bar->window &&
+ pointer->i == url_bar->text_icon) ? true : false;
+}
+
+
+/* This is an exported interface documented in url_bar.h */
+
+bool ro_gui_url_bar_test_for_text_field_keypress(struct url_bar *url_bar,
+ wimp_key *key)
+{
+ const char *url;
+ nsurl *n;
+
+ if (url_bar == NULL || url_bar->hidden || key == NULL)
+ return false;
+
+ if (key->w != url_bar->window || key->i != url_bar->text_icon)
+ return false;
+
+ /* Update hotlist indicator */
+
+ url = (const char *) url_bar->text_buffer;
+ if (url != NULL && nsurl_create(url, &n) == NSERROR_OK) {
+ ro_gui_url_bar_set_hotlist(url_bar, ro_gui_hotlist_has_page(n));
+ nsurl_unref(n);
+ } else if (url_bar->hotlist.set) {
+ ro_gui_url_bar_set_hotlist(url_bar, false);
+ }
+
+ return true;
+}
+
+
+/* This is an exported interface documented in url_bar.h */
+
+bool ro_gui_url_bar_set_site_favicon(struct url_bar *url_bar,
+ struct hlcache_handle *h)
+{
+ content_type type = CONTENT_NONE;
+
+ if (url_bar == NULL)
+ return false;
+
+ if (h != NULL)
+ type = content_get_type(h);
+
+ // \TODO -- Maybe test for CONTENT_ICO ???
+
+ if (type == CONTENT_IMAGE) {
+ url_bar->favicon_content = h;
+ url_bar->favicon_width = content_get_width(h);
+ url_bar->favicon_height = content_get_height(h);
+
+ if (url_bar->favicon_width > URLBAR_FAVICON_SIZE)
+ url_bar->favicon_width = URLBAR_FAVICON_SIZE;
+
+ if (url_bar->favicon_height > URLBAR_FAVICON_SIZE)
+ url_bar->favicon_height = URLBAR_FAVICON_SIZE;
+
+ url_bar->favicon_offset.x = ((url_bar->favicon_extent.x1 -
+ url_bar->favicon_extent.x0) -
+ (url_bar->favicon_width * 2)) / 2;
+ url_bar->favicon_offset.y = ((url_bar->favicon_extent.y1 -
+ url_bar->favicon_extent.y0) -
+ (url_bar->favicon_height * 2)) / 2;
+ } else {
+ url_bar->favicon_content = NULL;
+
+ if (url_bar->favicon_type != 0)
+ snprintf(url_bar->favicon_sprite,
+ URLBAR_FAVICON_NAME_LENGTH,
+ "Ssmall_%.3x", url_bar->favicon_type);
+ else
+ snprintf(url_bar->favicon_sprite,
+ URLBAR_FAVICON_NAME_LENGTH,
+ "Ssmall_xxx");
+ }
+
+ if (!url_bar->hidden)
+ xwimp_force_redraw(url_bar->window,
+ url_bar->favicon_extent.x0,
+ url_bar->favicon_extent.y0,
+ url_bar->favicon_extent.x1,
+ url_bar->favicon_extent.y1);
+
+ return true;
+}
+
+
+/* This is an exported interface documented in url_bar.h */
+
+bool ro_gui_url_bar_set_content_favicon(struct url_bar *url_bar,
+ struct gui_window *g)
+{
+ int type = 0;
+ char sprite[URLBAR_FAVICON_NAME_LENGTH];
+ struct hlcache_handle *h;
+
+ if (url_bar == NULL || g == NULL)
+ return false;
+
+ h = browser_window_get_content(g->bw);
+ if (h != NULL)
+ type = ro_content_filetype(h);
+
+ if (type != 0) {
+ snprintf(sprite, URLBAR_FAVICON_NAME_LENGTH,
+ "small_%.3x", type);
+
+ if (!ro_gui_wimp_sprite_exists(sprite))
+ type = 0;
+ }
+
+ url_bar->favicon_type = type;
+
+ if (url_bar->favicon_content == NULL) {
+ if (type == 0)
+ snprintf(url_bar->favicon_sprite,
+ URLBAR_FAVICON_NAME_LENGTH, "Ssmall_xxx");
+ else
+ snprintf(url_bar->favicon_sprite,
+ URLBAR_FAVICON_NAME_LENGTH, "S%s", sprite);
+
+ if (!url_bar->hidden)
+ xwimp_force_redraw(url_bar->window,
+ url_bar->favicon_extent.x0,
+ url_bar->favicon_extent.y0,
+ url_bar->favicon_extent.x1,
+ url_bar->favicon_extent.y1);
+ }
+
+ return true;
+}
+
+
+/* This is an exported interface documented in url_bar.h */
+
+bool ro_gui_url_bar_update_urlsuggest(struct url_bar *url_bar)
+{
+ if (url_bar == NULL || url_bar->hidden)
+ return (url_bar == NULL) ? false : true;
+
+ if (url_bar->window != NULL && url_bar->suggest_icon != -1)
+ ro_gui_set_icon_shaded_state(url_bar->window,
+ url_bar->suggest_icon,
+ !ro_gui_url_suggest_get_menu_available());
+
+ return true;
+}
+
+
+/**
+ * Callback for hlcache.
+ */
+static nserror ro_gui_url_bar_res_cb(hlcache_handle *handle,
+ const hlcache_event *event, void *pw)
+{
+ struct url_bar_resource *r = pw;
+
+ switch (event->type) {
+ case CONTENT_MSG_READY:
+ case CONTENT_MSG_DONE:
+ r->ready = true;
+ r->height = content_get_height(handle);
+ break;
+
+ default:
+ break;
+ }
+
+ return NSERROR_OK;
+}
+
+
+/* Exported interface, documented in url_bar.h */
+bool ro_gui_url_bar_init(void)
+{
+ int i;
+
+ for (i = 0; i < URLBAR_RES_LAST; i++) {
+ nsurl *url;
+ if (nsurl_create(url_bar_res[i].url, &url) == NSERROR_OK) {
+ hlcache_handle_retrieve(url, 0, NULL, NULL,
+ ro_gui_url_bar_res_cb,
+ &(url_bar_res[i]), NULL,
+ CONTENT_IMAGE, &(url_bar_res[i].c));
+ nsurl_unref(url);
+ }
+ }
+
+ return true;
+}
+
+
+/* Exported interface, documented in url_bar.h */
+void ro_gui_url_bar_fini(void)
+{
+ int i;
+
+ for (i = 0; i < URLBAR_RES_LAST; i++) {
+ hlcache_handle_release(url_bar_res[i].c);
+ }
+}
diff --git a/frontends/riscos/gui/url_bar.h b/frontends/riscos/gui/url_bar.h
new file mode 100644
index 000000000..981afb35f
--- /dev/null
+++ b/frontends/riscos/gui/url_bar.h
@@ -0,0 +1,329 @@
+/*
+ * Copyright 2005 Richard Wilson <info@tinct.net>
+ * Copyright 2011 Stephen Fryatt <stevef@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * URL bars (interface).
+ */
+
+#ifndef _NETSURF_RISCOS_URLBAR_H_
+#define _NETSURF_RISCOS_URLBAR_H_
+
+#include <stdbool.h>
+#include "riscos/menus.h"
+#include "riscos/theme.h"
+
+/* A list of possible URL bar actions. */
+
+typedef enum {
+ TOOLBAR_URL_NONE = 0, /* Special case: no action */
+ TOOLBAR_URL_DRAG_URL,
+ TOOLBAR_URL_DRAG_FAVICON,
+ TOOLBAR_URL_SELECT_HOTLIST,
+ TOOLBAR_URL_ADJUST_HOTLIST
+} url_bar_action;
+
+struct url_bar;
+struct hlcache_handle;
+
+/**
+ * Initialise the url bar module.
+ *
+ * \return True iff success, else false.
+ */
+
+bool ro_gui_url_bar_init(void);
+
+/**
+ * Finalise the url bar module
+ */
+
+void ro_gui_url_bar_fini(void);
+
+/**
+ * Create a new url bar widget.
+ *
+ * \param *theme The theme to apply (or NULL for the default).
+ * \return A url bar handle, or NULL on failure.
+ */
+
+struct url_bar *ro_gui_url_bar_create(struct theme_descriptor *theme);
+
+
+/**
+ * Place a URL bar into a toolbar window and initialise any theme-specific
+ * settings. Any previous incarnation of the bar will be forgotten: this
+ * is for use when a new toolbar is being created, or when a toolbar has been
+ * deleted and rebuilt following a theme change.
+ *
+ * \param *url_bar The URL bar to rebuild.
+ * \param *theme The theme to apply (or NULL for current).
+ * \param style The theme style to apply.
+ * \param window The window that the bar is in.
+ * \param display true if the bar should be for display only.
+ * \param shaded true if the bar should be shaded; else false.
+ * \return true on success; else false.
+ */
+
+bool ro_gui_url_bar_rebuild(struct url_bar *url_bar,
+ struct theme_descriptor *theme, theme_style style,
+ wimp_w window, bool display, bool shaded);
+
+
+/**
+ * Destroy a url bar widget.
+ *
+ * \param *url_bar The url bar to destroy.
+ */
+
+void ro_gui_url_bar_destroy(struct url_bar *url_bar);
+
+
+/**
+ * Return the MINIMUM dimensions required by the URL bar, in RO units,
+ * allowing for the current theme.
+ *
+ * \param *url_bar The URL bar of interest.
+ * \param *width Return the required width.
+ * \param *height Return the required height.
+ * \return true if values are returned; else false.
+ */
+
+bool ro_gui_url_bar_get_dims(struct url_bar *url_bar,
+ int *width, int *height);
+
+
+/**
+ * Set or update the dimensions to be used by the URL bar, in RO units.
+ * If these are greater than the minimum required, the URL bar will fill
+ * the extended space; if less, the call will fail.
+ *
+ * \param *url_bar The URL bar to update.
+ * \param x0 The minimum X window position.
+ * \param y0 The minimum Y window position.
+ * \param x1 The maximum X window position.
+ * \param y1 The maximum Y window position.
+ * \return true if size updated; else false.
+ */
+
+bool ro_gui_url_bar_set_extent(struct url_bar *url_bar,
+ int x0, int y0, int x1, int y1);
+
+
+/**
+ * Show or hide a URL bar.
+ *
+ * \param *url_bar The URL bar to hide.
+ * \param hide true to hide the bar; false to show it.
+ * \return true if successful; else false.
+ */
+
+bool ro_gui_url_bar_hide(struct url_bar *url_bar, bool hide);
+
+
+/**
+ * Handle redraw event rectangles in a URL bar.
+ *
+ * \param *url_bar The URL bar to use.
+ * \param *redraw The Wimp redraw rectangle to process.
+ */
+
+void ro_gui_url_bar_redraw(struct url_bar *url_bar, wimp_draw *redraw);
+
+
+/**
+ * Handle mouse clicks in a URL bar.
+ *
+ * \param *url_bar The URL bar to use.
+ * \param *pointer The Wimp mouse click event data.
+ * \param *state The toolbar window state.
+ * \param *action Returns the selected action, or
+ * TOOLBAR_URL_NONE.
+ * \return true if the event was handled exclusively;
+ * else false.
+ */
+
+bool ro_gui_url_bar_click(struct url_bar *url_bar,
+ wimp_pointer *pointer, wimp_window_state *state,
+ url_bar_action *action);
+
+
+/**
+ * Process offered menu prepare events from the parent window.
+ *
+ * \param *url_bar The URL bar in question.
+ * \param i The icon owning the menu.
+ * \param *menu The menu to be prepared.
+ * \param *pointer The Wimp Pointer data from the event.
+ * \return true if the event is claimed; else false.
+ */
+
+bool ro_gui_url_bar_menu_prepare(struct url_bar *url_bar, wimp_i i,
+ wimp_menu *menu, wimp_pointer *pointer);
+
+
+/**
+ * Process offered menu select events from the parent window.
+ *
+ * \param *url_bar The URL bar in question.
+ * \param i The icon owning the menu.
+ * \param *menu The menu to be prepared.
+ * \param *selection The wimp menu selection data.
+ * \param action The selected menu action.
+ * \return true if the event is claimed; else false.
+ */
+
+bool ro_gui_url_bar_menu_select(struct url_bar *url_bar, wimp_i i,
+ wimp_menu *menu, wimp_selection *selection, menu_action action);
+
+
+/**
+ * Translate mouse data into an interactive help message for the URL bar.
+ *
+ * \param *url_bar The URL bar to process.
+ * \param i The wimp icon under the pointer.
+ * \param *mouse The mouse position.
+ * \param *state The toolbar window state.
+ * \param buttons The mouse button state.
+ * \param **suffix Return a help token suffix, or "" for none.
+ * \return true if handled exclusively; else false.
+ */
+
+bool ro_gui_url_bar_help_suffix(struct url_bar *url_bar, wimp_i i,
+ os_coord *mouse, wimp_window_state *state,
+ wimp_mouse_state buttons, const char **suffix);
+
+
+/**
+ * Give a URL bar input focus.
+ *
+ * \param *url_bar The URL bar to give focus to.
+ * \return true if successful; else false.
+ */
+
+bool ro_gui_url_bar_take_caret(struct url_bar *url_bar);
+
+
+/**
+ * Set the content of a URL Bar field.
+ *
+ * \param *url_bar The URL Bar to update.
+ * \param *url The new url to insert.
+ * \param is_utf8 true if the string is in utf8 encoding; false
+ * if it is in local encoding.
+ * \param set_caret true if the caret should be placed in the field;
+ * else false.
+ */
+
+void ro_gui_url_bar_set_url(struct url_bar *url_bar, const char *url,
+ bool is_utf8, bool set_caret);
+
+
+/**
+ * Update the state of a URL Bar's hotlist icon to reflect any changes to the
+ * URL or the contents of the hotlist.
+ *
+ * \param *url_bar The URL Bar to update.
+ */
+
+void ro_gui_url_bar_update_hotlist(struct url_bar *url_bar);
+
+
+/**
+ * Return a pointer to the URL contained in a URL bar.
+ *
+ * \param *url_bar The URL Bar to look up the URL from.
+ * \return Pointer to the URL, or NULL.
+ */
+
+const char *ro_gui_url_bar_get_url(struct url_bar *url_bar);
+
+
+/**
+ * Return the current work area coordinates of the URL and favicon field's
+ * bounding box.
+ *
+ * \param *url_bar The URL bar to check.
+ * \param *extent Returns the field extent.
+ * \return true if successful; else false.
+ */
+
+bool ro_gui_url_bar_get_url_extent(struct url_bar *url_bar, os_box *extent);
+
+
+/**
+ * Test a pointer click to see if it was in the URL bar's text field.
+ *
+ * \param url_bar The URL Bar to test.
+ * \param pointer The pointer event data to test.
+ * \return true if the click was in the field; else false.
+ */
+
+bool ro_gui_url_bar_test_for_text_field_click(struct url_bar *url_bar,
+ wimp_pointer *pointer);
+
+
+/**
+ * Test a keypress to see if it was in the URL bar's text field.
+ *
+ * \param url_bar The URL Bar to test.
+ * \param key The key pressed
+ * \return true if the keypress was in the field; else false.
+ */
+
+bool ro_gui_url_bar_test_for_text_field_keypress(struct url_bar *url_bar,
+ wimp_key *key);
+
+
+/**
+ * Set the favicon to a site supplied favicon image, or remove the image
+ * and return to using filetype-based icons.
+ *
+ * \param *url_bar The URL Bar to update the favicon on.
+ * \param *h The content to use, or NULL to unset.
+ * \return true if successful; else false.
+ */
+
+bool ro_gui_url_bar_set_site_favicon(struct url_bar *url_bar,
+ struct hlcache_handle *h);
+
+
+/**
+ * Set the favicon to a RISC OS filetype sprite based on the type of the
+ * content within the supplied window.
+ *
+ * \param *url_bar The URL Bar to update the favicon on.
+ * \param *g The window with the content to use.
+ * \return true if successful; else false.
+ */
+
+bool ro_gui_url_bar_set_content_favicon(struct url_bar *url_bar,
+ struct gui_window *g);
+
+
+/**
+ * Update the state of the URL suggestion pop-up menu icon on a URL bar.
+ *
+ * \param *url_bar The URL bar to update.
+ * \return true if successful; else false.
+ */
+
+bool ro_gui_url_bar_update_urlsuggest(struct url_bar *url_bar);
+
+#endif
+
diff --git a/frontends/riscos/help.c b/frontends/riscos/help.c
new file mode 100644
index 000000000..73cb6957d
--- /dev/null
+++ b/frontends/riscos/help.c
@@ -0,0 +1,361 @@
+/*
+ * Copyright 2004, 2005 Richard Wilson <info@tinct.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Interactive help (implementation).
+ */
+
+#include <oslib/wimp.h>
+#include <oslib/taskmanager.h>
+
+#include "utils/nsoption.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/utf8.h"
+#include "desktop/mouse.h"
+#include "desktop/gui_window.h"
+
+#include "riscos/treeview.h"
+#include "riscos/help.h"
+#include "riscos/wimp_event.h"
+#include "riscos/hotlist.h"
+#include "riscos/global_history.h"
+#include "riscos/cookies.h"
+#include "riscos/wimp.h"
+#include "riscos/iconbar.h"
+#include "riscos/window.h"
+#include "riscos/ucstables.h"
+#include "riscos/gui.h"
+
+/* Recognised help keys
+ ====================
+ Help keys should be registered using the wimp_event system to be
+ recognised. The only special case help values are:
+
+ HelpIconbar Iconbar (no icon suffix is used)
+ HelpBrowser Browser window [*]
+ HelpHotlist Hotlist window [*]
+ HelpGHistory Global history window [*]
+ HelpCookies Cookies window [*]
+
+ HelpIconMenu Iconbar menu
+ HelpBrowserMenu Browser window menu
+ HelpHotlistMenu Hotlist window menu
+ HelpGHistoryMenu Global history window menu
+ HelpCookiesMenu Cookie window menu
+
+ The prefixes are followed by either the icon number (eg 'HelpToolbar7'),
+ or a series of numbers representing the menu structure (eg
+ 'HelpBrowserMenu3-1-2').
+ If '<key><identifier>' is not available, then simply '<key>' is then
+ used. For example if 'HelpToolbar7' is not available then 'HelpToolbar'
+ is then tried.
+ If an item is greyed out then a suffix of 'g' is added (eg
+ 'HelpToolbar7g'). For this to work, windows must have bit 4 of the
+ window flag byte set and the user must be running RISC OS 5.03 or
+ greater.
+ For items marked with an asterisk [*] a call must be made to determine
+ the required help text as the window does not contain any icons. An
+ example of this is the hotlist window where ro_gui_hotlist_help() is
+ called.
+*/
+
+
+static void ro_gui_interactive_help_broadcast(wimp_message *message,
+ char *token);
+static os_t help_time = 0;
+
+
+/**
+ * Attempts to process an interactive help message request
+ *
+ * \param message the request message
+ */
+void ro_gui_interactive_help_request(wimp_message *message)
+{
+ char message_token[32];
+ char menu_buffer[4];
+ wimp_selection menu_tree;
+ help_full_message_request *message_data;
+ wimp_w window;
+ wimp_i icon;
+ unsigned int index;
+ bool greyed = false;
+ wimp_menu *test_menu;
+ os_error *error;
+ const char *auto_text;
+ int i;
+
+ /* check we aren't turned off */
+ if (!nsoption_bool(interactive_help))
+ return;
+
+ /* only accept help requests */
+ if ((!message) || (message->action != message_HELP_REQUEST))
+ return;
+
+ /* remember the time of the request so we can track them */
+ xos_read_monotonic_time(&help_time);
+
+ /* set up our state */
+ message_token[0] = 0x00;
+ message_data = (help_full_message_request *)message;
+ window = message_data->w;
+ icon = message_data->i;
+
+ /* do the basic window checks */
+ auto_text = ro_gui_wimp_event_get_help_prefix(window);
+ if (auto_text != NULL) {
+ const char *auto_suffix = ro_gui_wimp_event_get_help_suffix(
+ window, icon, &message_data->pos,
+ message_data->buttons);
+
+ if (auto_suffix == NULL)
+ sprintf(message_token, "%s%i", auto_text, (int)icon);
+ else
+ sprintf(message_token, "%s%s", auto_text, auto_suffix);
+ } else if (window == wimp_ICON_BAR)
+ sprintf(message_token, "HelpIconbar");
+ else if (ro_gui_hotlist_check_window(message->data.data_xfer.w)) {
+ i = ro_treeview_get_help(message_data);
+ sprintf(message_token,
+ (i >= 0) ? "HelpTree%i" :"HelpHotlist%i", i);
+ } else if (ro_gui_global_history_check_window(
+ message->data.data_xfer.w)) {
+ i = ro_treeview_get_help(message_data);
+ sprintf(message_token,
+ (i >= 0) ? "HelpTree%i" :"HelpGHistory%i", i);
+ } else if (ro_gui_cookies_check_window(message->data.data_xfer.w)) {
+ i = ro_treeview_get_help(message_data);
+ sprintf(message_token,
+ (i >= 0) ? "HelpTree%i" :"HelpCookies%i", i);
+ } else if (ro_gui_window_lookup(window) != NULL)
+ sprintf(message_token, "HelpBrowser%i", (int)icon);
+
+ /* if we've managed to find something so far then we broadcast it */
+ if (message_token[0]) {
+ if ((icon >= 0) &&
+ (ro_gui_get_icon_shaded_state(window, icon)))
+ strcat(message_token, "g");
+ ro_gui_interactive_help_broadcast(message,
+ (char *)message_token);
+ return;
+ }
+
+ /* if we are not on an icon, we can't be in a menu (which stops
+ * separators giving help for their parent) so we abort */
+ if (icon == wimp_ICON_WINDOW)
+ return;
+
+ /* get the current menu tree */
+ error = xwimp_get_menu_state(wimp_GIVEN_WINDOW_AND_ICON,
+ &menu_tree, window, icon);
+ if (error) {
+ LOG("xwimp_get_menu_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+ if (menu_tree.items[0] == -1)
+ return;
+
+ /* get the menu prefix */
+ if (ro_gui_iconbar_check_menu(current_menu))
+ sprintf(message_token, "HelpIconMenu");
+ else if (ro_gui_window_check_menu(current_menu))
+ sprintf(message_token, "HelpBrowserMenu");
+ else if (ro_gui_hotlist_check_menu(current_menu))
+ sprintf(message_token, "HelpHotlistMenu");
+ else if (ro_gui_global_history_check_menu(current_menu))
+ sprintf(message_token, "HelpGHistoryMenu");
+ else if (ro_gui_cookies_check_menu(current_menu))
+ sprintf(message_token, "HelpCookiesMenu");
+ else
+ return;
+
+ /* decode the menu */
+ index = 0;
+ test_menu = current_menu;
+ while (menu_tree.items[index] != -1) {
+ greyed |= test_menu->entries[menu_tree.items[index]].icon_flags
+ & wimp_ICON_SHADED;
+ test_menu = test_menu->entries[menu_tree.items[index]].sub_menu;
+ if (index == 0)
+ sprintf(menu_buffer, "%i", menu_tree.items[index]);
+ else
+ sprintf(menu_buffer, "-%i", menu_tree.items[index]);
+ strcat(message_token, menu_buffer);
+ index++;
+ }
+ if (greyed)
+ strcat(message_token, "g");
+ ro_gui_interactive_help_broadcast(message, (char *)message_token);
+}
+
+
+/**
+ * Broadcasts a help reply
+ *
+ * \param message the original request message
+ * \param token the token to look up
+ */
+static void ro_gui_interactive_help_broadcast(wimp_message *message,
+ char *token)
+{
+ const char *translated_token;
+ help_full_message_reply *reply;
+ char *local_token;
+ os_error *error;
+
+ /* start off with an empty reply */
+ reply = (help_full_message_reply *)message;
+ reply->reply[0] = '\0';
+
+ /* check if the message exists */
+ translated_token = messages_get(token);
+ if (translated_token == token) {
+ /* no default help for 'g' suffix */
+ if (token[strlen(token) - 1] != 'g') {
+ /* find the base key from the token */
+ char *base_token = token;
+ while (base_token[0] != 0x00) {
+ if ((base_token[0] == '-') ||
+ ((base_token[0] >= '0') &&
+ (base_token[0] <= '9')))
+ base_token[0] = 0x00;
+ else
+ ++base_token;
+ }
+ translated_token = messages_get(token);
+ }
+ }
+
+ /* copy our message string */
+ if (translated_token != token) {
+ /* convert to local encoding */
+ nserror err = utf8_to_local_encoding(translated_token, 0,
+ &local_token);
+ if (err != NSERROR_OK) {
+ /* badenc should never happen */
+ assert(err != NSERROR_BAD_ENCODING);
+ /* simply use UTF-8 string */
+ strncpy(reply->reply, translated_token, 235);
+ }
+ else {
+ strncpy(reply->reply, local_token, 235);
+ free(local_token);
+ }
+ reply->reply[235] = '\0';
+ }
+
+ /* broadcast the help reply */
+ reply->size = 256;
+ reply->action = message_HELP_REPLY;
+ reply->your_ref = reply->my_ref;
+ error = xwimp_send_message(wimp_USER_MESSAGE, (wimp_message *)reply,
+ reply->sender);
+ if (error) {
+ LOG("xwimp_send_message: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+}
+
+
+/**
+ * Checks if interactive help is running
+ *
+ * \return non-zero if interactive help is available, or 0 if not available
+ */
+bool ro_gui_interactive_help_available(void)
+{
+ taskmanager_task task;
+ int context = 0;
+ os_t time;
+
+ /* generic test: any help request within the last 100cs */
+ xos_read_monotonic_time(&time);
+ if ((help_time + 100) > time)
+ return true;
+
+ /* special cases: check known application names */
+ do {
+ os_error *error;
+ error = xtaskmanager_enumerate_tasks(context, &task,
+ sizeof(taskmanager_task), &context, 0);
+ if (error) {
+ LOG("xtaskmanager_enumerate_tasks: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("MiscError", error->errmess);
+ }
+
+ /* we can't just use strcmp due to string termination issues */
+ if (!strncmp(task.name, "Help", 4) &&
+ (task.name[4] < 32))
+ return true;
+ else if (!strncmp(task.name, "Bubble Help", 11) &&
+ (task.name[11] < 32))
+ return true;
+ else if (!strncmp(task.name, "Floating Help", 13) &&
+ (task.name[13] < 32))
+ return true;
+ } while (context >= 0);
+ return false;
+}
+
+
+/**
+ * Launches interactive help.
+ */
+void ro_gui_interactive_help_start(void)
+{
+ char *help_start;
+ wimp_t task = 0;
+ os_error *error;
+
+ /* don't launch a second copy of anything */
+ if (ro_gui_interactive_help_available())
+ return;
+
+ /* launch <Help$Start> */
+ help_start = getenv("Help$Start");
+ if ((help_start) && (help_start[0])) {
+ error = xwimp_start_task("<Help$Start>", &task);
+ if (error) {
+ LOG("xwimp_start_tast: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+ }
+
+ /* first attempt failed, launch !Help */
+ if (!task) {
+ error = xwimp_start_task("Resources:$.Apps.!Help", &task);
+ if (error) {
+ LOG("xwimp_start_tast: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+ }
+
+ /* pretend we got a help request straight away */
+ if (task) {
+ error = xos_read_monotonic_time(&help_time);
+ if (error) {
+ LOG("xwimp_read_monotonic_time: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+ }
+}
diff --git a/frontends/riscos/help.h b/frontends/riscos/help.h
new file mode 100644
index 000000000..b09594ac8
--- /dev/null
+++ b/frontends/riscos/help.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2004, 2005 Richard Wilson <info@tinct.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Interactive help (interface).
+ */
+
+#ifndef _NETSURF_RISCOS_HELP_H_
+#define _NETSURF_RISCOS_HELP_H_
+
+#include <stdbool.h>
+#include "oslib/wimp.h"
+
+void ro_gui_interactive_help_request(wimp_message *message);
+bool ro_gui_interactive_help_available(void);
+void ro_gui_interactive_help_start(void);
+
+#endif
diff --git a/frontends/riscos/history.c b/frontends/riscos/history.c
new file mode 100644
index 000000000..9d78f6ded
--- /dev/null
+++ b/frontends/riscos/history.c
@@ -0,0 +1,336 @@
+/*
+ * Copyright 2006 James Bursa <bursa@users.sourceforge.net>
+ * Copyright 2005 Richard Wilson <info@tinct.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Browser history window (RISC OS implementation).
+ *
+ * There is only one history window, not one per browser window.
+ */
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include "oslib/wimp.h"
+
+#include "utils/nsoption.h"
+#include "utils/log.h"
+#include "desktop/browser_history.h"
+#include "desktop/plotters.h"
+
+#include "riscos/dialog.h"
+#include "riscos/gui.h"
+#include "riscos/mouse.h"
+#include "riscos/wimp.h"
+#include "riscos/wimp_event.h"
+#include "riscos/wimputils.h"
+
+static struct browser_window *history_bw;
+/* Last position of mouse in window. */
+static int mouse_x = 0;
+/* Last position of mouse in window. */
+static int mouse_y = 0;
+wimp_w history_window;
+
+static void ro_gui_history_redraw(wimp_draw *redraw);
+static bool ro_gui_history_click(wimp_pointer *pointer);
+static void ro_gui_history_pointer_entering(wimp_entering *entering);
+static void ro_gui_history_track_end(wimp_leaving *leaving, void *data);
+static void ro_gui_history_mouse_at(wimp_pointer *pointer, void *data);
+
+
+/**
+ * Create history window.
+ */
+
+void ro_gui_history_init(void)
+{
+ history_window = ro_gui_dialog_create("history");
+ ro_gui_wimp_event_register_redraw_window(history_window,
+ ro_gui_history_redraw);
+ ro_gui_wimp_event_register_mouse_click(history_window,
+ ro_gui_history_click);
+ ro_gui_wimp_event_register_pointer_entering_window(history_window,
+ ro_gui_history_pointer_entering);
+ ro_gui_wimp_event_set_help_prefix(history_window, "HelpHistory");
+}
+
+
+/**
+ * Open history window.
+ *
+ * \param g The riscos window to open history for.
+ * \param at_pointer open the window at the pointer.
+ */
+
+void ro_gui_history_open(struct gui_window *g, bool at_pointer)
+{
+ struct browser_window *bw;
+ int width, height;
+ os_box box = {0, 0, 0, 0};
+ wimp_window_state state;
+ os_error *error;
+
+ assert(g != NULL);
+ assert(g->bw != NULL);
+ bw = g->bw;
+ history_bw = bw;
+
+ browser_window_history_size(bw, &width, &height);
+ width *= 2;
+ height *= 2;
+
+ /* set extent */
+ box.x1 = width;
+ box.y0 = -height;
+ error = xwimp_set_extent(history_window, &box);
+ if (error) {
+ LOG("xwimp_set_extent: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ /* open full size */
+ state.w = history_window;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+ state.visible.x0 = 0;
+ state.visible.y0 = 0;
+ state.visible.x1 = width;
+ state.visible.y1 = height;
+ state.next = wimp_HIDDEN;
+ error = xwimp_open_window(PTR_WIMP_OPEN(&state));
+ if (error) {
+ LOG("xwimp_open_window: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ ro_gui_dialog_open_persistent(g->window, history_window, at_pointer);
+}
+
+
+/**
+ * Redraw history window.
+ */
+
+void ro_gui_history_redraw(wimp_draw *redraw)
+{
+ osbool more;
+ os_error *error;
+ struct redraw_context ctx = {
+ .interactive = true,
+ .background_images = true,
+ .plot = &ro_plotters
+ };
+
+ error = xwimp_redraw_window(redraw, &more);
+ if (error) {
+ LOG("xwimp_redraw_window: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+ while (more) {
+ ro_plot_origin_x = redraw->box.x0 - redraw->xscroll;
+ ro_plot_origin_y = redraw->box.y1 - redraw->yscroll;
+ browser_window_history_redraw(history_bw, &ctx);
+ error = xwimp_get_rectangle(redraw, &more);
+ if (error) {
+ LOG("xwimp_get_rectangle: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+ }
+}
+
+
+/**
+ * Handle Pointer Entering Window events the history window.
+ *
+ * \param *entering The Wimp_PointerEnteringWindow block.
+ */
+
+void ro_gui_history_pointer_entering(wimp_entering *entering)
+{
+ ro_mouse_track_start(ro_gui_history_track_end,
+ ro_gui_history_mouse_at, NULL);
+}
+
+
+/**
+ * Handle Pointer Leaving Window events the history window. These arrive as the
+ * termination callback handler from ro_mouse's mouse tracking.
+ *
+ * \param *leaving The Wimp_PointerLeavingWindow block.
+ * \param *data NULL data pointer.
+ */
+
+void ro_gui_history_track_end(wimp_leaving *leaving, void *data)
+{
+ ro_gui_dialog_close(dialog_tooltip);
+}
+
+
+/**
+ * Handle mouse movements over the history window.
+ */
+
+void ro_gui_history_mouse_at(wimp_pointer *pointer, void *data)
+{
+ int x, y;
+ int width;
+ const char *url;
+ wimp_window_state state;
+ wimp_icon_state ic;
+ os_box box = {0, 0, 0, 0};
+ os_error *error;
+
+ LOG("Mouse at...");
+
+ /* If the mouse hasn't moved, or if we don't want tooltips, exit */
+ if ((mouse_x == pointer->pos.x && mouse_y == pointer->pos.y) ||
+ !nsoption_bool(history_tooltip))
+ return;
+
+ /* Update mouse position */
+ mouse_x = pointer->pos.x;
+ mouse_y = pointer->pos.y;
+
+ /* Find history tree entry under mouse */
+ state.w = history_window;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ x = (pointer->pos.x - (state.visible.x0 - state.xscroll)) / 2;
+ y = -(pointer->pos.y - (state.visible.y1 - state.yscroll)) / 2;
+ url = browser_window_history_position_url(history_bw, x, y);
+ if (!url) {
+ /* not over a tree entry => close tooltip window. */
+ error = xwimp_close_window(dialog_tooltip);
+ if (error) {
+ LOG("xwimp_close_window: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+ return;
+ }
+
+ /* get width of string */
+ error = xwimptextop_string_width(url,
+ strlen(url) > 256 ? 256 : strlen(url),
+ &width);
+ if (error) {
+ LOG("xwimptextop_string_width: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ ro_gui_set_icon_string(dialog_tooltip, 0, url, true);
+
+ /* resize icon appropriately */
+ ic.w = dialog_tooltip;
+ ic.i = 0;
+ error = xwimp_get_icon_state(&ic);
+ if (error) {
+ LOG("xwimp_get_icon_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+ error = xwimp_resize_icon(dialog_tooltip, 0,
+ ic.icon.extent.x0, ic.icon.extent.y0,
+ width + 16, ic.icon.extent.y1);
+ if (error) {
+ LOG("xwimp_resize_icon: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ state.w = dialog_tooltip;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ /* update window extent */
+ box.x1 = width + 16;
+ box.y0 = -36;
+ error = xwimp_set_extent(dialog_tooltip, &box);
+ if (error) {
+ LOG("xwimp_set_extent: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ /* set visible area */
+ state.visible.x0 = pointer->pos.x + 24;
+ state.visible.y0 = pointer->pos.y - 22 - 36;
+ state.visible.x1 = pointer->pos.x + 24 + width + 16;
+ state.visible.y1 = pointer->pos.y - 22;
+ state.next = wimp_TOP;
+ /* open window */
+ error = xwimp_open_window(PTR_WIMP_OPEN(&state));
+ if (error) {
+ LOG("xwimp_open_window: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+}
+
+
+/**
+ * Handle mouse clicks in the history window.
+ *
+ * \return true if the event was handled, false to pass it on
+ */
+
+bool ro_gui_history_click(wimp_pointer *pointer)
+{
+ int x, y;
+ wimp_window_state state;
+ os_error *error;
+
+ if (pointer->buttons != wimp_CLICK_SELECT &&
+ pointer->buttons != wimp_CLICK_ADJUST)
+ /* return if not select or adjust click */
+ return true;
+
+ state.w = history_window;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return true;
+ }
+
+ x = (pointer->pos.x - (state.visible.x0 - state.xscroll)) / 2;
+ y = -(pointer->pos.y - (state.visible.y1 - state.yscroll)) / 2;
+ browser_window_history_click(history_bw, x, y,
+ pointer->buttons == wimp_CLICK_ADJUST);
+
+ return true;
+}
diff --git a/frontends/riscos/hotlist.c b/frontends/riscos/hotlist.c
new file mode 100644
index 000000000..381978faf
--- /dev/null
+++ b/frontends/riscos/hotlist.c
@@ -0,0 +1,737 @@
+/*
+ * Copyright 2004, 2005 Richard Wilson <info@tinct.net>
+ * Copyright 2010, 2013 Stephen Fryatt <stevef@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Hotlist (implementation).
+ */
+
+#include <ctype.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include "oslib/osfile.h"
+#include "oslib/osmodule.h"
+#include "oslib/wimp.h"
+
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/nsoption.h"
+#include "content/content.h"
+#include "content/hlcache.h"
+#include "content/urldb.h"
+#include "desktop/hotlist.h"
+#include "desktop/tree.h"
+#include "desktop/gui_window.h"
+
+#include "riscos/gui.h"
+#include "riscos/dialog.h"
+#include "riscos/hotlist.h"
+#include "riscos/menus.h"
+#include "riscos/message.h"
+#include "riscos/save.h"
+#include "riscos/toolbar.h"
+#include "riscos/treeview.h"
+#include "riscos/wimp.h"
+#include "riscos/wimp_event.h"
+#include "riscos/query.h"
+
+static void ro_gui_hotlist_toolbar_update_buttons(void);
+static void ro_gui_hotlist_toolbar_save_buttons(char *config);
+static bool ro_gui_hotlist_menu_prepare(wimp_w w, wimp_i i, wimp_menu *menu,
+ wimp_pointer *pointer);
+static void ro_gui_hotlist_menu_warning(wimp_w w, wimp_i i, wimp_menu *menu,
+ wimp_selection *selection, menu_action action);
+static bool ro_gui_hotlist_menu_select(wimp_w w, wimp_i i, wimp_menu *menu,
+ wimp_selection *selection, menu_action action);
+static void ro_gui_hotlist_toolbar_click(button_bar_action action);
+static void ro_gui_hotlist_addurl_bounce(wimp_message *message);
+static void ro_gui_hotlist_scheduled_callback(void *p);
+static void ro_gui_hotlist_remove_confirmed(query_id id,
+ enum query_response res, void *p);
+static void ro_gui_hotlist_remove_cancelled(query_id id,
+ enum query_response res, void *p);
+
+static const query_callback remove_funcs = {
+ ro_gui_hotlist_remove_confirmed,
+ ro_gui_hotlist_remove_cancelled
+};
+
+struct ro_treeview_callbacks ro_hotlist_treeview_callbacks = {
+ ro_gui_hotlist_toolbar_click,
+ ro_gui_hotlist_toolbar_update_buttons,
+ ro_gui_hotlist_toolbar_save_buttons
+};
+
+/* Hotlist Protocol Message Blocks, which are currently not in OSLib. */
+
+struct ro_hotlist_message_hotlist_addurl {
+ wimp_MESSAGE_HEADER_MEMBERS /**< The standard message header. */
+ char *url; /**< Pointer to the URL in RMA. */
+ char *title; /**< Pointer to the title in RMA. */
+ char appname[32]; /**< The application name. */
+};
+
+struct ro_hotlist_message_hotlist_changed {
+ wimp_MESSAGE_HEADER_MEMBERS /**< The standard message header. */
+};
+
+static char *hotlist_url = NULL; /**< URL area claimed from RMA. */
+static char *hotlist_title = NULL; /**< Title area claimed from RMA. */
+
+/** Hotlist Query Handler. */
+
+static query_id hotlist_query = QUERY_INVALID;
+static nsurl *hotlist_delete_url = NULL;
+
+/* The RISC OS hotlist window, toolbar and treeview data. */
+
+static struct ro_hotlist {
+ wimp_w window; /**< The hotlist RO window handle. */
+ struct toolbar *toolbar; /**< The hotlist toolbar handle. */
+ ro_treeview *tv; /**< The hotlist treeview handle. */
+ wimp_menu *menu; /**< The hotlist window menu. */
+} hotlist_window;
+
+/**
+ * Pre-Initialise the hotlist tree. This is called for things that need to
+ * be done at the gui_init() stage, such as loading templates.
+ */
+
+void ro_gui_hotlist_preinitialise(void)
+{
+ /* Create our window. */
+
+ hotlist_window.window = ro_gui_dialog_create("tree");
+ ro_gui_set_window_title(hotlist_window.window,
+ messages_get("Hotlist"));
+}
+
+/**
+ * Initialise the hotlist tree, at the gui_init2() stage.
+ */
+
+void ro_gui_hotlist_postinitialise(void)
+{
+ /* Create our toolbar. */
+
+ hotlist_window.toolbar = ro_toolbar_create(NULL, hotlist_window.window,
+ THEME_STYLE_HOTLIST_TOOLBAR, TOOLBAR_FLAGS_NONE,
+ ro_treeview_get_toolbar_callbacks(), NULL,
+ "HelpHotToolbar");
+ if (hotlist_window.toolbar != NULL) {
+ ro_toolbar_add_buttons(hotlist_window.toolbar,
+ hotlist_toolbar_buttons,
+ nsoption_charp(toolbar_hotlist));
+ ro_toolbar_rebuild(hotlist_window.toolbar);
+ }
+
+ /* Create the treeview with the window and toolbar. */
+ tree_hotlist_path = nsoption_charp(hotlist_path);
+ hotlist_window.tv = ro_treeview_create(hotlist_window.window,
+ hotlist_window.toolbar, &ro_hotlist_treeview_callbacks,
+ TREE_HOTLIST);
+ if (hotlist_window.tv == NULL) {
+ LOG("Failed to allocate treeview");
+ return;
+ }
+
+ ro_toolbar_update_client_data(hotlist_window.toolbar,
+ hotlist_window.tv);
+
+ /* Build the hotlist window menu. */
+
+ static const struct ns_menu hotlist_definition = {
+ "Hotlist", {
+ { "Hotlist", NO_ACTION, 0 },
+ { "Hotlist.New", NO_ACTION, 0 },
+ { "Hotlist.New.Folder", TREE_NEW_FOLDER, 0 },
+ { "Hotlist.New.Link", TREE_NEW_LINK, 0 },
+ { "_Hotlist.Export", HOTLIST_EXPORT, &dialog_saveas },
+ { "Hotlist.Expand", TREE_EXPAND_ALL, 0 },
+ { "Hotlist.Expand.All", TREE_EXPAND_ALL, 0 },
+ { "Hotlist.Expand.Folders", TREE_EXPAND_FOLDERS, 0 },
+ { "Hotlist.Expand.Links", TREE_EXPAND_LINKS, 0 },
+ { "Hotlist.Collapse", TREE_COLLAPSE_ALL, 0 },
+ { "Hotlist.Collapse.All", TREE_COLLAPSE_ALL, 0 },
+ { "Hotlist.Collapse.Folders", TREE_COLLAPSE_FOLDERS, 0 },
+ { "Hotlist.Collapse.Links", TREE_COLLAPSE_LINKS, 0 },
+ { "Hotlist.Toolbars", NO_ACTION, 0 },
+ { "_Hotlist.Toolbars.ToolButtons", TOOLBAR_BUTTONS, 0 },
+ { "Hotlist.Toolbars.EditToolbar", TOOLBAR_EDIT, 0 },
+ { "Selection", TREE_SELECTION, 0 },
+ { "Selection.Edit", TREE_SELECTION_EDIT, 0 },
+ { "Selection.Launch", TREE_SELECTION_LAUNCH, 0 },
+ { "Selection.Delete", TREE_SELECTION_DELETE, 0 },
+ { "SelectAll", TREE_SELECT_ALL, 0 },
+ { "Clear", TREE_CLEAR_SELECTION, 0 },
+ {NULL, 0, 0}
+ }
+ };
+
+ hotlist_window.menu = ro_gui_menu_define_menu(&hotlist_definition);
+
+ ro_gui_wimp_event_register_menu(hotlist_window.window,
+ hotlist_window.menu, false, false);
+ ro_gui_wimp_event_register_menu_prepare(hotlist_window.window,
+ ro_gui_hotlist_menu_prepare);
+ ro_gui_wimp_event_register_menu_selection(hotlist_window.window,
+ ro_gui_hotlist_menu_select);
+ ro_gui_wimp_event_register_menu_warning(hotlist_window.window,
+ ro_gui_hotlist_menu_warning);
+}
+
+/**
+ * Destroy the hotlist window.
+ */
+
+void ro_gui_hotlist_destroy(void)
+{
+ if (hotlist_window.tv == NULL)
+ return;
+
+ tree_hotlist_path = nsoption_charp(hotlist_save);
+ ro_treeview_destroy(hotlist_window.tv);
+}
+
+
+/**
+ * Open the hotlist window.
+ *
+ */
+
+void ro_gui_hotlist_open(void)
+{
+ if (nsoption_bool(external_hotlists) &&
+ nsoption_charp(external_hotlist_app) != NULL &&
+ *nsoption_charp(external_hotlist_app) != '\0') {
+ char command[2048];
+ os_error *error;
+
+ snprintf(command, sizeof(command), "Filer_Run %s",
+ nsoption_charp(external_hotlist_app));
+ error = xos_cli(command);
+
+ if (error == NULL)
+ return;
+
+ LOG("xos_cli: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("Failed to launch external hotlist: %s",
+ error->errmess);
+ }
+
+ ro_gui_hotlist_toolbar_update_buttons();
+
+ if (!ro_gui_dialog_open_top(hotlist_window.window,
+ hotlist_window.toolbar, 600, 800)) {
+ ro_treeview_set_origin(hotlist_window.tv, 0,
+ -(ro_toolbar_height(hotlist_window.toolbar)));
+ }
+}
+
+/**
+ * Handle toolbar button clicks.
+ *
+ * \param action The action to handle
+ */
+
+void ro_gui_hotlist_toolbar_click(button_bar_action action)
+{
+ switch (action) {
+ case TOOLBAR_BUTTON_DELETE:
+ hotlist_keypress(NS_KEY_DELETE_LEFT);
+ ro_toolbar_update_all_hotlists();
+ break;
+
+ case TOOLBAR_BUTTON_EXPAND:
+ hotlist_expand(false);
+ break;
+
+ case TOOLBAR_BUTTON_COLLAPSE:
+ hotlist_contract(false);
+ break;
+
+ case TOOLBAR_BUTTON_OPEN:
+ hotlist_expand(true);
+ break;
+
+ case TOOLBAR_BUTTON_CLOSE:
+ hotlist_contract(true);
+ break;
+
+ case TOOLBAR_BUTTON_LAUNCH:
+ hotlist_keypress(NS_KEY_CR);
+ break;
+
+ case TOOLBAR_BUTTON_CREATE:
+ hotlist_add_folder(NULL, false, 0);
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+/**
+ * Update the button state in the hotlist toolbar.
+ */
+
+void ro_gui_hotlist_toolbar_update_buttons(void)
+{
+ ro_toolbar_set_button_shaded_state(hotlist_window.toolbar,
+ TOOLBAR_BUTTON_DELETE,
+ !hotlist_has_selection());
+
+ ro_toolbar_set_button_shaded_state(hotlist_window.toolbar,
+ TOOLBAR_BUTTON_LAUNCH,
+ !hotlist_has_selection());
+}
+
+
+/**
+ * Save a new button arrangement in the hotlist toolbar.
+ *
+ * \param *config The new button configuration string.
+ */
+
+void ro_gui_hotlist_toolbar_save_buttons(char *config)
+{
+ nsoption_set_charp(toolbar_hotlist, config);
+ ro_gui_save_options();
+}
+
+
+/**
+ * Prepare the hotlist menu for opening
+ *
+ * \param w The window owning the menu.
+ * \param i A wimp icon
+ * \param menu The menu about to be opened.
+ * \param pointer Pointer to the relevant wimp event block, or
+ * NULL for an Adjust click.
+ * \return true if the event was handled; else false.
+ */
+
+bool ro_gui_hotlist_menu_prepare(wimp_w w, wimp_i i, wimp_menu *menu,
+ wimp_pointer *pointer)
+{
+ bool selection;
+
+ if (menu != hotlist_window.menu)
+ return false;
+
+ selection = hotlist_has_selection();
+
+ ro_gui_menu_set_entry_shaded(hotlist_window.menu,
+ TREE_SELECTION, !selection);
+ ro_gui_menu_set_entry_shaded(hotlist_window.menu,
+ TREE_CLEAR_SELECTION, !selection);
+
+ ro_gui_save_prepare(GUI_SAVE_HOTLIST_EXPORT_HTML,
+ NULL, NULL, NULL, NULL);
+
+ ro_gui_menu_set_entry_shaded(menu, TOOLBAR_BUTTONS,
+ ro_toolbar_menu_option_shade(hotlist_window.toolbar));
+ ro_gui_menu_set_entry_ticked(menu, TOOLBAR_BUTTONS,
+ ro_toolbar_menu_buttons_tick(hotlist_window.toolbar));
+
+ ro_gui_menu_set_entry_shaded(menu, TOOLBAR_EDIT,
+ ro_toolbar_menu_edit_shade(hotlist_window.toolbar));
+ ro_gui_menu_set_entry_ticked(menu, TOOLBAR_EDIT,
+ ro_toolbar_menu_edit_tick(hotlist_window.toolbar));
+
+ return true;
+}
+
+
+/**
+ * Handle submenu warnings for the hotlist menu
+ *
+ * \param w The window owning the menu.
+ * \param i The icon owning the menu.
+ * \param *menu The menu to which the warning applies.
+ * \param *selection The wimp menu selection data.
+ * \param action The selected menu action.
+ */
+
+void ro_gui_hotlist_menu_warning(wimp_w w, wimp_i i, wimp_menu *menu,
+ wimp_selection *selection, menu_action action)
+{
+ /* Do nothing */
+}
+
+/**
+ * Handle selections from the hotlist menu
+ *
+ * \param w The window owning the menu.
+ * \param i The icon owning the menu.
+ * \param *menu The menu from which the selection was made.
+ * \param *selection The wimp menu selection data.
+ * \param action The selected menu action.
+ * \return true if action accepted; else false.
+ */
+
+bool ro_gui_hotlist_menu_select(wimp_w w, wimp_i i, wimp_menu *menu,
+ wimp_selection *selection, menu_action action)
+{
+ switch (action) {
+ case HOTLIST_EXPORT:
+ ro_gui_dialog_open_persistent(w, dialog_saveas, true);
+ return true;
+ case TREE_NEW_FOLDER:
+ hotlist_add_folder(NULL, false, 0);
+ return true;
+ case TREE_NEW_LINK:
+ hotlist_add_entry(NULL, NULL, false, 0);
+ return true;
+ case TREE_EXPAND_ALL:
+ hotlist_expand(false);
+ return true;
+ case TREE_EXPAND_FOLDERS:
+ hotlist_expand(true);
+ return true;
+ case TREE_EXPAND_LINKS:
+ hotlist_expand(false);
+ return true;
+ case TREE_COLLAPSE_ALL:
+ hotlist_contract(true);
+ return true;
+ case TREE_COLLAPSE_FOLDERS:
+ hotlist_contract(true);
+ return true;
+ case TREE_COLLAPSE_LINKS:
+ hotlist_contract(false);
+ return true;
+ case TREE_SELECTION_EDIT:
+ hotlist_edit_selection();
+ return true;
+ case TREE_SELECTION_LAUNCH:
+ hotlist_keypress(NS_KEY_CR);
+ return true;
+ case TREE_SELECTION_DELETE:
+ hotlist_keypress(NS_KEY_DELETE_LEFT);
+ ro_toolbar_update_all_hotlists();
+ return true;
+ case TREE_SELECT_ALL:
+ hotlist_keypress(NS_KEY_SELECT_ALL);
+ return true;
+ case TREE_CLEAR_SELECTION:
+ hotlist_keypress(NS_KEY_CLEAR_SELECTION);
+ return true;
+ case TOOLBAR_BUTTONS:
+ ro_toolbar_set_display_buttons(hotlist_window.toolbar,
+ !ro_toolbar_get_display_buttons(
+ hotlist_window.toolbar));
+ return true;
+ case TOOLBAR_EDIT:
+ ro_toolbar_toggle_edit(hotlist_window.toolbar);
+ return true;
+ default:
+ return false;
+ }
+
+ return false;
+}
+
+/**
+ * Check if a particular window handle is the hotlist window
+ *
+ * \param window The window in question
+ * \return true if this window is the hotlist
+ */
+bool ro_gui_hotlist_check_window(wimp_w window)
+{
+ if (hotlist_window.window == window)
+ return true;
+ else
+ return false;
+}
+
+/**
+ * Check if a particular menu handle is the hotlist menu
+ *
+ * \param *menu The menu in question.
+ * \return true if this menu is the hotlist menu
+ */
+
+bool ro_gui_hotlist_check_menu(wimp_menu *menu)
+{
+ if (hotlist_window.menu == menu)
+ return true;
+ else
+ return false;
+}
+
+
+/**
+ * Add a URL to the hotlist. This will be passed on to the core hotlist, then
+ * Message_HotlistAddURL will broadcast to any bookmark applications via the
+ * Hotlist Protocol.
+ *
+ * \param *url The URL to be added.
+ */
+
+void ro_gui_hotlist_add_page(nsurl *url)
+{
+ const struct url_data *data;
+ wimp_message message;
+ struct ro_hotlist_message_hotlist_addurl *add_url =
+ (struct ro_hotlist_message_hotlist_addurl *) &message;
+
+ if (url == NULL)
+ return;
+
+ /* If we're not using external hotlists, add the page to NetSurf's
+ * own hotlist and return...
+ */
+
+ if (!nsoption_bool(external_hotlists)) {
+ hotlist_add_url(url);
+ return;
+ }
+
+ /* ...otherwise try broadcasting the details to any other
+ * interested parties. If no-one answers, we'll fall back to
+ * NetSurf's hotlist anyway when the message bounces.
+ */
+
+ ro_gui_hotlist_add_cleanup();
+
+ data = urldb_get_url_data(url);
+ if (data == NULL)
+ return;
+
+ hotlist_url = osmodule_alloc(nsurl_length(url) + 1);
+ hotlist_title = osmodule_alloc(strlen(data->title) + 1);
+
+ if (hotlist_url == NULL || hotlist_title == NULL) {
+ ro_gui_hotlist_add_cleanup();
+ return;
+ }
+
+ strcpy(hotlist_url, nsurl_access(url));
+ strcpy(hotlist_title, data->title);
+
+ add_url->size = 60;
+ add_url->your_ref = 0;
+ add_url->action = message_HOTLIST_ADD_URL;
+ add_url->url = hotlist_url;
+ add_url->title = hotlist_title;
+ strcpy(add_url->appname, "NetSurf");
+
+ if (!ro_message_send_message(wimp_USER_MESSAGE_RECORDED, &message, 0,
+ ro_gui_hotlist_addurl_bounce))
+ ro_gui_hotlist_add_cleanup();
+
+ /* Listen for the next Null poll, as an indication that the
+ * message didn't bounce.
+ */
+
+ riscos_schedule(0, ro_gui_hotlist_scheduled_callback, NULL);
+}
+
+
+/**
+ * Handle bounced Message_HotlistAddURL, so that RMA storage can be freed.
+ *
+ * \param *message The bounced message content.
+ */
+
+static void ro_gui_hotlist_addurl_bounce(wimp_message *message)
+{
+ if (hotlist_url != NULL) {
+ nsurl *nsurl;
+
+ if (nsurl_create(hotlist_url, &nsurl) != NSERROR_OK)
+ return;
+
+ hotlist_add_url(nsurl);
+ nsurl_unref(nsurl);
+ }
+
+ ro_gui_hotlist_add_cleanup();
+
+ /* There's no longer any need to listen for the next Null poll. */
+
+ riscos_schedule(-1, ro_gui_hotlist_scheduled_callback, NULL);
+}
+
+
+/**
+ * Callback to schedule for the next available Null poll, by which point
+ * a hotlist client will have claimed the Message_HotlistAddURL and any
+ * details in RMA can safely be discarded.
+ *
+ * \param *p Unused data pointer.
+ */
+
+static void ro_gui_hotlist_scheduled_callback(void *p)
+{
+ ro_gui_hotlist_add_cleanup();
+}
+
+
+/**
+ * Clean up RMA storage used by the Message_HotlistAddURL protocol.
+ */
+
+void ro_gui_hotlist_add_cleanup(void)
+{
+ if (hotlist_url != NULL) {
+ osmodule_free(hotlist_url);
+ hotlist_url = NULL;
+ }
+
+ if (hotlist_title != NULL) {
+ osmodule_free(hotlist_title);
+ hotlist_title = NULL;
+ }
+}
+
+
+/**
+ * Remove a URL from the hotlist. This will be passed on to the core hotlist,
+ * unless we're configured to use external hotlists in which case we ignore it.
+ *
+ * \param *url The URL to be removed.
+ */
+
+void ro_gui_hotlist_remove_page(nsurl *url)
+{
+ if (url == NULL || nsoption_bool(external_hotlists) ||
+ !hotlist_has_url(url))
+ return;
+
+ /* Clean up any existing delete attempts before continuing. */
+
+ if (hotlist_query != QUERY_INVALID) {
+ query_close(hotlist_query);
+ hotlist_query = QUERY_INVALID;
+ }
+
+ if (hotlist_delete_url != NULL) {
+ nsurl_unref(hotlist_delete_url);
+ hotlist_delete_url = NULL;
+ }
+
+ /* Check with the user before removing the URL, unless they don't
+ * want us to be careful in which case just do it.
+ */
+
+ if (nsoption_bool(confirm_hotlist_remove)) {
+ hotlist_query = query_user("RemoveHotlist", NULL,
+ &remove_funcs, NULL,
+ messages_get("Remove"),
+ messages_get("DontRemove"));
+
+ hotlist_delete_url = nsurl_ref(url);
+ } else {
+ hotlist_remove_url(url);
+ ro_toolbar_update_all_hotlists();
+ }
+}
+
+
+/**
+ * Callback confirming a URL delete query.
+ *
+ * \param id The ID of the query calling us.
+ * \param res The user's response to the query.
+ * \param *p Callback data (always NULL).
+ */
+
+static void ro_gui_hotlist_remove_confirmed(query_id id,
+ enum query_response res, void *p)
+{
+ hotlist_remove_url(hotlist_delete_url);
+ ro_toolbar_update_all_hotlists();
+
+ nsurl_unref(hotlist_delete_url);
+ hotlist_delete_url = NULL;
+ hotlist_query = QUERY_INVALID;
+}
+
+
+/**
+ * Callback cancelling a URL delete query.
+ *
+ * \param id The ID of the query calling us.
+ * \param res The user's response to the query.
+ * \param *p Callback data (always NULL).
+ */
+
+static void ro_gui_hotlist_remove_cancelled(query_id id,
+ enum query_response res, void *p)
+{
+ nsurl_unref(hotlist_delete_url);
+ hotlist_delete_url = NULL;
+ hotlist_query = QUERY_INVALID;
+}
+
+
+/**
+ * Report whether the hotlist contains a given URL. This will be passed on to
+ * the core hotlist, unless we're configured to use an external hotlist in which
+ * case we always report false.
+ *
+ * \param *url The URL to be tested.
+ * \return true if the hotlist contains the URL; else false.
+ */
+
+bool ro_gui_hotlist_has_page(nsurl *url)
+{
+ if (url == NULL || nsoption_bool(external_hotlists))
+ return false;
+
+ return hotlist_has_url(url);
+}
+
+
+#if 0
+/**
+ * Handle URL dropped on hotlist
+ *
+ * \param message the wimp message we're acting on
+ * \param url the URL to add
+ */
+void ro_gui_hotlist_url_drop(wimp_message *message, const char *url)
+{
+ int x, y;
+ nsurl *nsurl;
+
+ if (hotlist_window.window != message->data.data_xfer.w)
+ return;
+
+ if (url == NULL)
+ return;
+
+ if (nsurl_create(url, &nsurl) != NSERROR_OK)
+ return;
+
+ ro_gui_tree_get_tree_coordinates(hotlist_window.tree,
+ message->data.data_xfer.pos.x,
+ message->data.data_xfer.pos.y,
+ &x, &y);
+
+ hotlist_add_entry(nsurl, NULL, true, y);
+ nsurl_unref(nsurl);
+}
+#endif
diff --git a/frontends/riscos/hotlist.h b/frontends/riscos/hotlist.h
new file mode 100644
index 000000000..0b87a2e96
--- /dev/null
+++ b/frontends/riscos/hotlist.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2006 Richard Wilson <info@tinct.net>
+ * Copyright 2010, 2013 Stephen Fryatt <stevef@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Hotlist (interface).
+ */
+
+#ifndef _NETSURF_RISCOS_HOTLIST_H_
+#define _NETSURF_RISCOS_HOTLIST_H_
+
+/* Hotlist Protocol Messages, which are currently not in OSLib. */
+
+#ifndef message_HOTLIST_ADD_URL
+#define message_HOTLIST_ADD_URL 0x4af81
+#endif
+
+#ifndef message_HOTLIST_CHANGED
+#define message_HOTLIST_CHANGED 0x4af82
+#endif
+
+#include "riscos/menus.h"
+
+struct nsurl;
+
+void ro_gui_hotlist_preinitialise(void);
+void ro_gui_hotlist_postinitialise(void);
+void ro_gui_hotlist_destroy(void);
+void ro_gui_hotlist_open(void);
+void ro_gui_hotlist_save(void);
+bool ro_gui_hotlist_check_window(wimp_w window);
+bool ro_gui_hotlist_check_menu(wimp_menu *menu);
+void ro_gui_hotlist_add_page(struct nsurl *url);
+void ro_gui_hotlist_add_cleanup(void);
+void ro_gui_hotlist_remove_page(struct nsurl *url);
+bool ro_gui_hotlist_has_page(struct nsurl *url);
+
+#endif
diff --git a/frontends/riscos/iconbar.c b/frontends/riscos/iconbar.c
new file mode 100644
index 000000000..9cff116a1
--- /dev/null
+++ b/frontends/riscos/iconbar.c
@@ -0,0 +1,261 @@
+/*
+ * Copyright 2010 Stephen Fryatt <stevef@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Iconbar icon and menus (implementation).
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <features.h>
+#include <oslib/os.h>
+#include <oslib/osbyte.h>
+#include <oslib/wimp.h>
+
+#include "utils/nsoption.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/nsurl.h"
+#include "desktop/browser.h"
+
+#include "riscos/gui.h"
+#include "riscos/configure.h"
+#include "riscos/cookies.h"
+#include "riscos/dialog.h"
+#include "riscos/global_history.h"
+#include "riscos/hotlist.h"
+#include "riscos/iconbar.h"
+#include "riscos/wimp_event.h"
+
+static bool ro_gui_iconbar_click(wimp_pointer *pointer);
+
+static bool ro_gui_iconbar_menu_select(wimp_w w, wimp_i i, wimp_menu *menu,
+ wimp_selection *selection, menu_action action);
+static void ro_gui_iconbar_menu_warning(wimp_w w, wimp_i i, wimp_menu *menu,
+ wimp_selection *selection, menu_action action);
+
+
+static wimp_menu *ro_gui_iconbar_menu = NULL; /**< Iconbar menu handle */
+
+/**
+ * Initialise the iconbar menus, create an icon and register the necessary
+ * handlers to look after them all.
+ */
+
+void ro_gui_iconbar_initialise(void)
+{
+ os_error *error;
+
+ /* Build the iconbar menu */
+
+ static const struct ns_menu iconbar_definition = {
+ "NetSurf", {
+ { "Info", NO_ACTION, &dialog_info },
+ { "AppHelpNoShortcut", HELP_OPEN_CONTENTS, 0 },
+ { "Open", BROWSER_NAVIGATE_URL, 0 },
+ { "Open.OpenURL", BROWSER_NAVIGATE_URL, &dialog_openurl },
+ { "Open.HotlistShowNoShortcut", HOTLIST_SHOW, 0 },
+ { "Open.HistGlobalNoShortcut", HISTORY_SHOW_GLOBAL, 0 },
+ { "Open.ShowCookies", COOKIES_SHOW, 0 },
+ { "Choices", CHOICES_SHOW, 0 },
+ { "Quit", APPLICATION_QUIT, 0 },
+ {NULL, 0, 0}
+ }
+ };
+ ro_gui_iconbar_menu = ro_gui_menu_define_menu(&iconbar_definition);
+
+ /* Create an iconbar icon. */
+
+ wimp_icon_create icon = {
+ wimp_ICON_BAR_RIGHT,
+ { { 0, 0, 68, 68 },
+ wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED |
+ (wimp_BUTTON_CLICK << wimp_ICON_BUTTON_TYPE_SHIFT),
+ { "!netsurf" } } };
+ error = xwimp_create_icon(&icon, 0);
+ if (error) {
+ LOG("xwimp_create_icon: 0x%x: %s", error->errnum, error->errmess);
+ die(error->errmess);
+ }
+
+ /* Register handlers to look after clicks and menu actions. */
+
+ ro_gui_wimp_event_register_mouse_click(wimp_ICON_BAR,
+ ro_gui_iconbar_click);
+
+ ro_gui_wimp_event_register_menu(wimp_ICON_BAR, ro_gui_iconbar_menu,
+ true, true);
+ ro_gui_wimp_event_register_menu_selection(wimp_ICON_BAR,
+ ro_gui_iconbar_menu_select);
+ ro_gui_wimp_event_register_menu_warning(wimp_ICON_BAR,
+ ro_gui_iconbar_menu_warning);
+}
+
+
+/**
+ * Handle Mouse_Click events on the iconbar icon.
+ *
+ * \param *pointer The wimp event block to be processed.
+ * \return true if the event was handled; else false.
+ */
+
+bool ro_gui_iconbar_click(wimp_pointer *pointer)
+{
+ int key_down = 0;
+ nsurl *url;
+ nserror error;
+
+ switch (pointer->buttons) {
+ case wimp_CLICK_SELECT:
+ if (nsoption_charp(homepage_url) != NULL) {
+ error = nsurl_create(nsoption_charp(homepage_url), &url);
+ } else {
+ error = nsurl_create(NETSURF_HOMEPAGE, &url);
+ }
+
+ /* create an initial browser window */
+ if (error == NSERROR_OK) {
+ error = browser_window_create(BW_CREATE_HISTORY,
+ url,
+ NULL,
+ NULL,
+ NULL);
+ nsurl_unref(url);
+ }
+ if (error != NSERROR_OK) {
+ ro_warn_user(messages_get_errorcode(error), 0);
+ }
+ break;
+
+ case wimp_CLICK_ADJUST:
+ xosbyte1(osbyte_SCAN_KEYBOARD, 0 ^ 0x80, 0, &key_down);
+ if (key_down == 0)
+ ro_gui_hotlist_open();
+ break;
+ }
+
+ return true;
+}
+
+/**
+ * Handle submenu warnings for the iconbar menu
+ *
+ * \param w The window owning the menu.
+ * \param i The icon owning the menu.
+ * \param *menu The menu to which the warning applies.
+ * \param *selection The wimp menu selection data.
+ * \param action The selected menu action.
+ */
+
+void ro_gui_iconbar_menu_warning(wimp_w w, wimp_i i, wimp_menu *menu,
+ wimp_selection *selection, menu_action action)
+{
+ if (w != wimp_ICON_BAR || i != wimp_ICON_WINDOW)
+ return;
+
+ switch (action) {
+ case BROWSER_NAVIGATE_URL:
+ ro_gui_dialog_prepare_open_url();
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * Handle selections from the iconbar menu
+ *
+ * \param w The window owning the menu.
+ * \param i The icon owning the menu.
+ * \param menu The wimp menu
+ * \param selection The wimp menu selection data.
+ * \param action The selected menu action.
+ * \return true if action accepted; else false.
+ */
+
+bool ro_gui_iconbar_menu_select(wimp_w w, wimp_i i, wimp_menu *menu,
+ wimp_selection *selection, menu_action action)
+{
+ nsurl *url;
+ nserror error;
+
+ if (w != wimp_ICON_BAR || i != wimp_ICON_WINDOW)
+ return false;
+
+ switch (action) {
+ case HELP_OPEN_CONTENTS:
+ error = nsurl_create("http://www.netsurf-browser.org/documentation/", &url);
+ if (error == NSERROR_OK) {
+ error = browser_window_create(BW_CREATE_HISTORY,
+ url,
+ NULL,
+ NULL,
+ NULL);
+ nsurl_unref(url);
+ }
+ if (error != NSERROR_OK) {
+ ro_warn_user(messages_get_errorcode(error), 0);
+ }
+ return true;
+
+ case BROWSER_NAVIGATE_URL:
+ ro_gui_dialog_prepare_open_url();
+ ro_gui_dialog_open_persistent(NULL, dialog_openurl, true);
+ return true;
+ case HOTLIST_SHOW:
+ ro_gui_hotlist_open();
+ return true;
+ case HISTORY_SHOW_GLOBAL:
+ ro_gui_global_history_open();
+ return true;
+ case COOKIES_SHOW:
+ ro_gui_cookies_open();
+ return true;
+ case CHOICES_SHOW:
+ ro_gui_configure_show();
+ return true;
+ case APPLICATION_QUIT:
+ if (ro_gui_prequit()) {
+ LOG("QUIT in response to user request");
+ riscos_done = true;
+ }
+ return true;
+ default:
+ return false;
+ }
+
+ return false;
+}
+
+/**
+ * Check if a particular menu handle is the iconbar menu
+ *
+ * \param *menu The menu in question.
+ * \return true if this menu is the iconbar menu
+ */
+
+bool ro_gui_iconbar_check_menu(wimp_menu *menu)
+{
+ return (ro_gui_iconbar_menu == menu) ? true : false;
+}
+
diff --git a/frontends/riscos/iconbar.h b/frontends/riscos/iconbar.h
new file mode 100644
index 000000000..e40f9acd8
--- /dev/null
+++ b/frontends/riscos/iconbar.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2010 Stephen Fryatt <stevef@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Iconbar icon and menus (interface).
+ */
+
+#include <stdbool.h>
+
+#ifndef _NETSURF_RISCOS_ICONBAR_H_
+#define _NETSURF_RISCOS_ICONBAR_H_
+
+void ro_gui_iconbar_initialise(void);
+bool ro_gui_iconbar_check_menu(wimp_menu *menu);
+
+#endif
+
diff --git a/frontends/riscos/image.c b/frontends/riscos/image.c
new file mode 100644
index 000000000..acbe62d98
--- /dev/null
+++ b/frontends/riscos/image.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2004 John M Bell <jmb202@ecs.soton.ac.uk>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdbool.h>
+#include <swis.h>
+#include <stdlib.h>
+#include <oslib/colourtrans.h>
+#include <oslib/osspriteop.h>
+
+#include "utils/nsoption.h"
+#include "utils/log.h"
+
+#include "riscos/image.h"
+#include "riscos/gui.h"
+#include "riscos/tinct.h"
+
+static bool image_redraw_tinct(osspriteop_id header, int x, int y,
+ int req_width, int req_height, int width, int height,
+ colour background_colour, bool repeatx, bool repeaty,
+ bool alpha, unsigned int tinct_options);
+static bool image_redraw_os(osspriteop_id header, int x, int y,
+ int req_width, int req_height, int width, int height);
+
+/**
+ * Plot an image at the given coordinates using the method specified
+ *
+ * \param area The sprite area containing the sprite
+ * \param x Left edge of sprite
+ * \param y Top edge of sprite
+ * \param req_width The requested width of the sprite
+ * \param req_height The requested height of the sprite
+ * \param width The actual width of the sprite
+ * \param height The actual height of the sprite
+ * \param background_colour The background colour to blend to
+ * \param repeatx Repeat the image in the x direction
+ * \param repeaty Repeat the image in the y direction
+ * \param background Use background image settings (otherwise foreground)
+ * \param type The plot method to use
+ * \return true on success, false otherwise
+ */
+bool image_redraw(osspriteop_area *area, int x, int y, int req_width,
+ int req_height, int width, int height,
+ colour background_colour,
+ bool repeatx, bool repeaty, bool background, image_type type)
+{
+ unsigned int tinct_options;
+
+ /* failed decompression/loading can result in no image being present */
+ if (!area)
+ return false;
+
+ osspriteop_id header = (osspriteop_id)
+ ((char*) area + area->first);
+ req_width *= 2;
+ req_height *= 2;
+ width *= 2;
+ height *= 2;
+ tinct_options = background ? nsoption_int(plot_bg_quality) :
+ nsoption_int(plot_fg_quality);
+ switch (type) {
+ case IMAGE_PLOT_TINCT_ALPHA:
+ return image_redraw_tinct(header, x, y,
+ req_width, req_height,
+ width, height,
+ background_colour,
+ repeatx, repeaty, true,
+ tinct_options);
+ case IMAGE_PLOT_TINCT_OPAQUE:
+ return image_redraw_tinct(header, x, y,
+ req_width, req_height,
+ width, height,
+ background_colour,
+ repeatx, repeaty, false,
+ tinct_options);
+ case IMAGE_PLOT_OS:
+ return image_redraw_os(header, x, y, req_width,
+ req_height, width, height);
+ default:
+ break;
+ }
+
+ return false;
+}
+
+/**
+ * Plot an image at the given coordinates using tinct
+ *
+ * \param header The sprite header
+ * \param x Left edge of sprite
+ * \param y Top edge of sprite
+ * \param req_width The requested width of the sprite
+ * \param req_height The requested height of the sprite
+ * \param width The actual width of the sprite
+ * \param height The actual height of the sprite
+ * \param background_colour The background colour to blend to
+ * \param repeatx Repeat the image in the x direction
+ * \param repeaty Repeat the image in the y direction
+ * \param alpha Use the alpha channel
+ * \param tinct_options The base option set to use
+ * \return true on success, false otherwise
+ */
+bool image_redraw_tinct(osspriteop_id header, int x, int y,
+ int req_width, int req_height, int width, int height,
+ colour background_colour, bool repeatx, bool repeaty,
+ bool alpha, unsigned int tinct_options)
+{
+ _kernel_oserror *error;
+
+ /* Set up our flagword
+ */
+ tinct_options |= background_colour << tinct_BACKGROUND_SHIFT;
+ if (print_active)
+ tinct_options |= tinct_USE_OS_SPRITE_OP;
+ if (repeatx)
+ tinct_options |= tinct_FILL_HORIZONTALLY;
+ if (repeaty)
+ tinct_options |= tinct_FILL_VERTICALLY;
+
+ if (alpha) {
+ error = _swix(Tinct_PlotScaledAlpha, _INR(2,7),
+ header, x, y - req_height,
+ req_width, req_height, tinct_options);
+ } else {
+ error = _swix(Tinct_PlotScaled, _INR(2,7),
+ header, x, y - req_height,
+ req_width, req_height, tinct_options);
+ }
+
+ if (error) {
+ LOG("xtinct_plotscaled%s: 0x%x: %s", (alpha ? "alpha" : ""), error->errnum, error->errmess);
+ return false;
+ }
+
+ return true;
+}
+
+
+/**
+ * Plot an image at the given coordinates using os_spriteop
+ *
+ * \param header The sprite header
+ * \param x Left edge of sprite
+ * \param y Top edge of sprite
+ * \param req_width The requested width of the sprite
+ * \param req_height The requested height of the sprite
+ * \param width The actual width of the sprite
+ * \param height The actual height of the sprite
+ * \return true on success, false otherwise
+ */
+bool image_redraw_os(osspriteop_id header, int x, int y, int req_width,
+ int req_height, int width, int height)
+{
+ int size;
+ os_factors f;
+ osspriteop_trans_tab *table;
+ os_error *error;
+
+ error = xcolourtrans_generate_table_for_sprite(
+ (osspriteop_area *)0x100, header,
+ os_CURRENT_MODE,
+ colourtrans_CURRENT_PALETTE,
+ 0, colourtrans_GIVEN_SPRITE, 0, 0, &size);
+ if (error) {
+ LOG("xcolourtrans_generate_table_for_sprite: 0x%x: %s", error->errnum, error->errmess);
+ return false;
+ }
+
+ table = calloc(size, sizeof(char));
+ if (!table) {
+ LOG("malloc failed");
+ ro_warn_user("NoMemory", 0);
+ return false;
+ }
+
+ error = xcolourtrans_generate_table_for_sprite(
+ (osspriteop_area *)0x100, header,
+ os_CURRENT_MODE,
+ colourtrans_CURRENT_PALETTE,
+ table, colourtrans_GIVEN_SPRITE, 0, 0, 0);
+ if (error) {
+ LOG("xcolourtrans_generate_table_for_sprite: 0x%x: %s", error->errnum, error->errmess);
+ free(table);
+ return false;
+ }
+
+ f.xmul = req_width;
+ f.ymul = req_height;
+ f.xdiv = width;
+ f.ydiv = height;
+
+ error = xosspriteop_put_sprite_scaled(osspriteop_PTR,
+ (osspriteop_area *)0x100, header,
+ x, (int)(y - req_height),
+ 8, &f, table);
+ if (error) {
+ LOG("xosspriteop_put_sprite_scaled: 0x%x: %s", error->errnum, error->errmess);
+ free(table);
+ return false;
+ }
+
+ free(table);
+
+ return true;
+}
diff --git a/frontends/riscos/image.h b/frontends/riscos/image.h
new file mode 100644
index 000000000..a11388c13
--- /dev/null
+++ b/frontends/riscos/image.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2004 John M Bell <jmb202@ecs.soton.ac.uk>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _NETSURF_RISCOS_IMAGE_H_
+#define _NETSURF_RISCOS_IMAGE_H_
+
+#include <stdbool.h>
+#include "desktop/plot_style.h"
+#include "oslib/osspriteop.h"
+
+struct osspriteop_area;
+
+typedef enum {
+ IMAGE_PLOT_TINCT_ALPHA,
+ IMAGE_PLOT_TINCT_OPAQUE,
+ IMAGE_PLOT_OS
+} image_type;
+
+bool image_redraw(osspriteop_area *area, int x, int y, int req_width,
+ int req_height, int width, int height,
+ colour background_colour,
+ bool repeatx, bool repeaty, bool background, image_type type);
+
+#endif
diff --git a/frontends/riscos/menus.c b/frontends/riscos/menus.c
new file mode 100644
index 000000000..37285c9d1
--- /dev/null
+++ b/frontends/riscos/menus.c
@@ -0,0 +1,958 @@
+/*
+ * Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
+ * Copyright 2005 James Bursa <bursa@users.sourceforge.net>
+ * Copyright 2003 John M Bell <jmb202@ecs.soton.ac.uk>
+ * Copyright 2005 Richard Wilson <info@tinct.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Menu creation and handling implementation.
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include "oslib/os.h"
+#include "oslib/osbyte.h"
+#include "oslib/osgbpb.h"
+#include "oslib/territory.h"
+#include "oslib/wimp.h"
+
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/utf8.h"
+#include "content/content.h"
+#include "content/hlcache.h"
+#include "content/urldb.h"
+#include "desktop/cookie_manager.h"
+#include "desktop/browser.h"
+#include "desktop/textinput.h"
+
+#include "riscos/dialog.h"
+#include "riscos/configure.h"
+#include "riscos/cookies.h"
+#include "riscos/gui.h"
+#include "riscos/global_history.h"
+#include "riscos/help.h"
+#include "riscos/hotlist.h"
+#include "riscos/menus.h"
+#include "utils/nsoption.h"
+#include "riscos/save.h"
+#include "riscos/tinct.h"
+#include "riscos/toolbar.h"
+#include "riscos/treeview.h"
+#include "riscos/url_suggest.h"
+#include "riscos/wimp.h"
+#include "riscos/wimp_event.h"
+#include "riscos/ucstables.h"
+
+struct menu_definition_entry {
+ menu_action action; /**< menu action */
+ wimp_menu_entry *menu_entry; /**< corresponding menu entry */
+ const char *entry_key; /**< Messages key for entry text */
+ struct menu_definition_entry *next; /**< next menu entry */
+};
+
+struct menu_definition {
+ wimp_menu *menu; /**< corresponding menu */
+ const char *title_key; /**< Messages key for title text */
+ int current_encoding; /**< Identifier for current text encoding of menu text (as per OS_Byte,71,127) */
+ struct menu_definition_entry *entries; /**< menu entries */
+ struct menu_definition *next; /**< next menu */
+};
+
+static void ro_gui_menu_closed(void);
+static void ro_gui_menu_define_menu_add(struct menu_definition *definition,
+ const struct ns_menu *menu, int depth,
+ wimp_menu_entry *parent_entry,
+ int first, int last, const char *prefix, int prefix_length);
+static struct menu_definition *ro_gui_menu_find_menu(wimp_menu *menu);
+static struct menu_definition_entry *ro_gui_menu_find_entry(wimp_menu *menu,
+ menu_action action);
+static menu_action ro_gui_menu_find_action(wimp_menu *menu,
+ wimp_menu_entry *menu_entry);
+static int ro_gui_menu_get_checksum(void);
+static bool ro_gui_menu_translate(struct menu_definition *menu);
+
+
+/* default menu item flags */
+#define DEFAULT_FLAGS (wimp_ICON_TEXT | wimp_ICON_FILLED | \
+ (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) | \
+ (wimp_COLOUR_WHITE << wimp_ICON_BG_COLOUR_SHIFT))
+
+/** The currently defined menus to perform actions for */
+static struct menu_definition *ro_gui_menu_definitions;
+/** The current menu being worked with (may not be open) */
+wimp_menu *current_menu;
+/** Whether a menu is currently open */
+bool current_menu_open = false;
+/** Window that owns the current menu */
+wimp_w current_menu_window;
+/** Icon that owns the current menu (only valid for popup menus) */
+static wimp_i current_menu_icon;
+/** The available menus */
+wimp_menu *image_quality_menu, *proxy_type_menu, *languages_menu;
+
+/* the values given in PRM 3-157 for how to check menus/windows are
+ * incorrect so we use a hack of checking if the sub-menu has bit 0
+ * set which is undocumented but true of window handles on
+ * all target OS versions */
+#define IS_MENU(menu) !((int)(menu) & 1)
+
+/**
+ * Create menu structures.
+ */
+
+void ro_gui_menu_init(void)
+{
+ /* image quality menu */
+ static const struct ns_menu images_definition = {
+ "Display", {
+ { "ImgStyle0", NO_ACTION, 0 },
+ { "ImgStyle1", NO_ACTION, 0 },
+ { "ImgStyle2", NO_ACTION, 0 },
+ { "ImgStyle3", NO_ACTION, 0 },
+ {NULL, 0, 0}
+ }
+ };
+ image_quality_menu = ro_gui_menu_define_menu(&images_definition);
+
+ /* proxy menu */
+ static const struct ns_menu proxy_type_definition = {
+ "ProxyType", {
+ { "ProxyNone", NO_ACTION, 0 },
+ { "ProxyNoAuth", NO_ACTION, 0 },
+ { "ProxyBasic", NO_ACTION, 0 },
+ { "ProxyNTLM", NO_ACTION, 0 },
+ {NULL, 0, 0}
+ }
+ };
+ proxy_type_menu = ro_gui_menu_define_menu(&proxy_type_definition);
+
+ /* special case menus */
+ ro_gui_url_suggest_init();
+
+ /* Note: This table *must* be kept in sync with the LangNames file */
+ static const struct ns_menu lang_definition = {
+ "Languages", {
+ { "lang_af", NO_ACTION, 0 },
+ { "lang_bm", NO_ACTION, 0 },
+ { "lang_ca", NO_ACTION, 0 },
+ { "lang_cs", NO_ACTION, 0 },
+ { "lang_cy", NO_ACTION, 0 },
+ { "lang_da", NO_ACTION, 0 },
+ { "lang_de", NO_ACTION, 0 },
+ { "lang_en", NO_ACTION, 0 },
+ { "lang_es", NO_ACTION, 0 },
+ { "lang_et", NO_ACTION, 0 },
+ { "lang_eu", NO_ACTION, 0 },
+ { "lang_ff", NO_ACTION, 0 },
+ { "lang_fi", NO_ACTION, 0 },
+ { "lang_fr", NO_ACTION, 0 },
+ { "lang_ga", NO_ACTION, 0 },
+ { "lang_gl", NO_ACTION, 0 },
+ { "lang_ha", NO_ACTION, 0 },
+ { "lang_hr", NO_ACTION, 0 },
+ { "lang_hu", NO_ACTION, 0 },
+ { "lang_id", NO_ACTION, 0 },
+ { "lang_is", NO_ACTION, 0 },
+ { "lang_it", NO_ACTION, 0 },
+ { "lang_lt", NO_ACTION, 0 },
+ { "lang_lv", NO_ACTION, 0 },
+ { "lang_ms", NO_ACTION, 0 },
+ { "lang_mt", NO_ACTION, 0 },
+ { "lang_nl", NO_ACTION, 0 },
+ { "lang_no", NO_ACTION, 0 },
+ { "lang_pl", NO_ACTION, 0 },
+ { "lang_pt", NO_ACTION, 0 },
+ { "lang_rn", NO_ACTION, 0 },
+ { "lang_ro", NO_ACTION, 0 },
+ { "lang_rw", NO_ACTION, 0 },
+ { "lang_sk", NO_ACTION, 0 },
+ { "lang_sl", NO_ACTION, 0 },
+ { "lang_so", NO_ACTION, 0 },
+ { "lang_sq", NO_ACTION, 0 },
+ { "lang_sr", NO_ACTION, 0 },
+ { "lang_sv", NO_ACTION, 0 },
+ { "lang_sw", NO_ACTION, 0 },
+ { "lang_tr", NO_ACTION, 0 },
+ { "lang_uz", NO_ACTION, 0 },
+ { "lang_vi", NO_ACTION, 0 },
+ { "lang_wo", NO_ACTION, 0 },
+ { "lang_xs", NO_ACTION, 0 },
+ { "lang_yo", NO_ACTION, 0 },
+ { "lang_zu", NO_ACTION, 0 },
+ { NULL, 0, 0 }
+ }
+ };
+ languages_menu = ro_gui_menu_define_menu(&lang_definition);
+}
+
+
+/**
+ * Display a menu.
+ *
+ * \param *menu Pointer to the menu to be displayed.
+ * \param x The x position.
+ * \param y The y position.
+ * \param w The window that the menu belongs to.
+ */
+
+void ro_gui_menu_create(wimp_menu *menu, int x, int y, wimp_w w)
+{
+ os_error *error;
+ struct menu_definition *definition;
+
+ /* translate menu, if necessary (this returns quickly
+ * if there's nothing to be done) */
+ definition = ro_gui_menu_find_menu(menu);
+ if (definition) {
+ if (!ro_gui_menu_translate(definition)) {
+ ro_warn_user("NoMemory", 0);
+ return;
+ }
+ }
+
+ /* store the menu characteristics */
+ current_menu = menu;
+ current_menu_window = w;
+ current_menu_icon = wimp_ICON_WINDOW;
+
+ /* create the menu */
+ current_menu_open = true;
+ error = xwimp_create_menu(menu, x - 64, y);
+ if (error) {
+ LOG("xwimp_create_menu: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("MenuError", error->errmess);
+ ro_gui_menu_closed();
+ }
+}
+
+
+/**
+ * Display a pop-up menu next to the specified icon.
+ *
+ * \param menu menu to open
+ * \param w window handle
+ * \param i icon handle
+ */
+
+void ro_gui_popup_menu(wimp_menu *menu, wimp_w w, wimp_i i)
+{
+ wimp_window_state state;
+ wimp_icon_state icon_state;
+ os_error *error;
+
+ state.w = w;
+ icon_state.w = w;
+ icon_state.i = i;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("MenuError", error->errmess);
+ return;
+ }
+
+ error = xwimp_get_icon_state(&icon_state);
+ if (error) {
+ LOG("xwimp_get_icon_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("MenuError", error->errmess);
+ return;
+ }
+
+ ro_gui_menu_create(menu,
+ state.visible.x0 + icon_state.icon.extent.x1 + 64,
+ state.visible.y1 + icon_state.icon.extent.y1 -
+ state.yscroll, w);
+ current_menu_icon = i;
+}
+
+
+/**
+ * Forcibly close any menu or transient dialogue box that is currently open.
+ */
+
+void ro_gui_menu_destroy(void)
+{
+ os_error *error;
+
+ if (current_menu == NULL)
+ return;
+
+ error = xwimp_create_menu(wimp_CLOSE_MENU, 0, 0);
+ if (error) {
+ LOG("xwimp_create_menu: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("MenuError", error->errmess);
+ }
+
+ ro_gui_menu_closed();
+}
+
+
+/**
+ * Allow the current menu window to change, if the window is deleted and
+ * recreated while a menu is active on an Adjust-click.
+ *
+ * \param from The original window handle.
+ * \param to The new replacement window handle.
+ */
+
+void ro_gui_menu_window_changed(wimp_w from, wimp_w to)
+{
+
+ if (from == current_menu_window)
+ current_menu_window = to;
+}
+
+
+/**
+ * Handle menu selection.
+ */
+
+void ro_gui_menu_selection(wimp_selection *selection)
+{
+ int i; //, j;
+ wimp_menu_entry *menu_entry;
+ menu_action action;
+ wimp_pointer pointer;
+ os_error *error;
+ int previous_menu_icon = current_menu_icon;
+
+ /* if we are using gui_multitask then menu selection events
+ * may be delivered after the menu has been closed. As such,
+ * we simply ignore these events. */
+ if (!current_menu)
+ return;
+
+ assert(current_menu_window);
+
+ /* get the menu entry and associated action and definition */
+ menu_entry = &current_menu->entries[selection->items[0]];
+ for (i = 1; selection->items[i] != -1; i++)
+ menu_entry = &menu_entry->sub_menu->
+ entries[selection->items[i]];
+ action = ro_gui_menu_find_action(current_menu, menu_entry);
+
+ /* Deal with the menu action. If this manages to re-prepare the
+ * menu for re-opening, we test for and act on Adjust clicks.
+ */
+
+ if (!ro_gui_wimp_event_menu_selection(current_menu_window,
+ current_menu_icon, current_menu, selection, action))
+ return;
+
+ /* re-open the menu for Adjust clicks */
+ error = xwimp_get_pointer_info(&pointer);
+ if (error) {
+ LOG("xwimp_get_pointer_info: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ ro_gui_menu_closed();
+ return;
+ }
+
+ if (pointer.buttons != wimp_CLICK_ADJUST) {
+ ro_gui_menu_closed();
+ return;
+ }
+
+ ro_gui_menu_create(current_menu, 0, 0, current_menu_window);
+ current_menu_icon = previous_menu_icon;
+}
+
+
+/**
+ * Handle Message_MenuWarning.
+ */
+void ro_gui_menu_warning(wimp_message_menu_warning *warning)
+{
+ int i;
+ menu_action action;
+ wimp_menu_entry *menu_entry;
+ os_error *error;
+
+ assert(current_menu);
+ assert(current_menu_window);
+
+ /* get the sub-menu of the warning */
+ if (warning->selection.items[0] == -1)
+ return;
+ menu_entry = &current_menu->entries[warning->selection.items[0]];
+ for (i = 1; warning->selection.items[i] != -1; i++)
+ menu_entry = &menu_entry->sub_menu->
+ entries[warning->selection.items[i]];
+ action = ro_gui_menu_find_action(current_menu, menu_entry);
+
+ /* Process the warning via Wimp_Event, then register the resulting
+ * submenu with the module.
+ */
+
+ ro_gui_wimp_event_submenu_warning(current_menu_window,
+ current_menu_icon, current_menu, &(warning->selection),
+ action);
+
+ if (IS_MENU(menu_entry->sub_menu)) {
+ ro_gui_wimp_event_register_submenu((wimp_w) 0);
+ } else {
+ ro_gui_wimp_event_register_submenu((wimp_w)
+ menu_entry->sub_menu);
+
+ /* If this is a dialogue box, remove the close and back icons.
+ */
+
+ ro_gui_wimp_update_window_furniture((wimp_w)
+ menu_entry->sub_menu,
+ wimp_WINDOW_CLOSE_ICON | wimp_WINDOW_BACK_ICON,
+ 0);
+ }
+
+ /* open the sub-menu */
+
+ error = xwimp_create_sub_menu(menu_entry->sub_menu,
+ warning->pos.x, warning->pos.y);
+ if (error) {
+ LOG("xwimp_create_sub_menu: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("MenuError", error->errmess);
+ }
+}
+
+
+/**
+ * Handle Message_MenusDeleted, removing our current record of an open menu
+ * if it matches the deleted menu handle.
+ *
+ * \param *deleted The message block.
+ */
+
+void ro_gui_menu_message_deleted(wimp_message_menus_deleted *deleted)
+{
+ if (deleted != NULL && deleted->menu == current_menu)
+ ro_gui_menu_closed();
+}
+
+
+/**
+ * Clean up after a menu has been closed, or forcibly close an open menu.
+ */
+
+static void ro_gui_menu_closed(void)
+{
+ if (current_menu != NULL)
+ ro_gui_wimp_event_menus_closed(current_menu_window,
+ current_menu_icon, current_menu);
+
+ current_menu = NULL;
+ current_menu_window = NULL;
+ current_menu_icon = 0;
+ current_menu_open = false;
+}
+
+
+/**
+ * Update the current menu by sending it a Menu Prepare event through wimp_event
+ * and then reopening it if the contents has changed.
+ *
+ * \param *menu The menu to refresh: if 0, the current menu will be
+ * refreshed regardless, otherwise it will be refreshed
+ * only if it matches the supplied handle.
+ */
+
+void ro_gui_menu_refresh(wimp_menu *menu)
+{
+ int checksum = 0;
+
+ if (!current_menu_open)
+ return;
+
+ checksum = ro_gui_menu_get_checksum();
+
+ if (!ro_gui_wimp_event_prepare_menu(current_menu_window,
+ current_menu_icon, current_menu))
+ return;
+
+ /* \TODO -- Call the menu's event handler here. */
+
+ if (checksum != ro_gui_menu_get_checksum()) {
+ os_error *error;
+ error = xwimp_create_menu(current_menu, 0, 0);
+ if (error) {
+ LOG("xwimp_create_menu: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("MenuError", error->errmess);
+ }
+ }
+}
+
+
+
+
+/**
+ * Creates a wimp_menu and adds it to the list to handle actions for.
+ *
+ * \param menu The data to create the menu with
+ * \return The menu created, or NULL on failure
+ */
+wimp_menu *ro_gui_menu_define_menu(const struct ns_menu *menu)
+{
+ struct menu_definition *definition;
+ int entry;
+
+ definition = calloc(sizeof(struct menu_definition), 1);
+ if (!definition) {
+ die("No memory to create menu definition.");
+ return NULL; /* For the benefit of scan-build */
+ }
+
+ /* link in the menu to our list */
+ definition->next = ro_gui_menu_definitions;
+ ro_gui_menu_definitions = definition;
+
+ /* count number of menu entries */
+ for (entry = 0; menu->entries[entry].text; entry++)
+ /* do nothing */;
+
+ /* create our definitions */
+ ro_gui_menu_define_menu_add(definition, menu, 0, NULL,
+ 0, entry, NULL, 0);
+
+ /* and translate menu into current encoding */
+ if (!ro_gui_menu_translate(definition))
+ die("No memory to translate menu.");
+
+ return definition->menu;
+}
+
+/**
+ * Create a wimp menu tree from ns_menu data.
+ * This function does *not* deal with the menu textual content - it simply
+ * creates and populates the appropriate structures. Textual content is
+ * generated by ro_gui_menu_translate_menu()
+ *
+ * \param definition Top level menu definition
+ * \param menu Menu declaration data
+ * \param depth Depth of menu we're currently building
+ * \param parent_entry Entry in parent menu, or NULL if root menu
+ * \param first First index in declaration data that is used by this menu
+ * \param last Last index in declaration data that is used by this menu
+ * \param prefix Prefix pf menu declaration string already seen
+ * \param prefix_length Length of prefix
+ */
+void ro_gui_menu_define_menu_add(struct menu_definition *definition,
+ const struct ns_menu *menu, int depth,
+ wimp_menu_entry *parent_entry, int first, int last,
+ const char *prefix, int prefix_length)
+{
+ int entry;
+ int entries = 0;
+ int matches[last - first + 1];
+ const char *text, *menu_text;
+ wimp_menu *new_menu;
+ struct menu_definition_entry *definition_entry;
+
+ /* step 1: store the matches for depth and subset string */
+ for (entry = first; entry < last; entry++) {
+ const char *match;
+ int cur_depth = 0;
+ match = menu->entries[entry].text;
+
+ /* skip specials at start of string */
+ while (!isalnum(*match))
+ match++;
+
+ /* attempt prefix match */
+ if ((prefix) && (strncmp(match, prefix, prefix_length)))
+ continue;
+
+ /* Find depth of this entry */
+ while (*match)
+ if (*match++ == '.')
+ cur_depth++;
+
+ if (depth == cur_depth)
+ matches[entries++] = entry;
+ }
+ matches[entries] = last;
+
+ /* no entries, so exit */
+ if (entries == 0)
+ return;
+
+ /* step 2: build and link the menu. we must use realloc to stop
+ * our memory fragmenting so we can test for sub-menus easily */
+ new_menu = (wimp_menu *)malloc(wimp_SIZEOF_MENU(entries));
+ if (!new_menu)
+ die("No memory to create menu.");
+
+ if (parent_entry) {
+ /* Fix up sub menu pointer */
+ parent_entry->sub_menu = new_menu;
+ } else {
+ /* Root menu => fill in definition struct */
+ definition->title_key = menu->title;
+ definition->current_encoding = 0;
+ definition->menu = new_menu;
+ }
+
+ /* this is fixed up in ro_gui_menu_translate() */
+ new_menu->title_data.indirected_text.text = NULL;
+
+ /* fill in menu flags */
+ ro_gui_menu_init_structure(new_menu, entries);
+
+ /* and then create the entries */
+ for (entry = 0; entry < entries; entry++) {
+ /* add the entry */
+ int id = matches[entry];
+
+ text = menu->entries[id].text;
+
+ /* fill in menu flags from specials at start of string */
+ new_menu->entries[entry].menu_flags = 0;
+ while (!isalnum(*text)) {
+ if (*text == '_')
+ new_menu->entries[entry].menu_flags |=
+ wimp_MENU_SEPARATE;
+ text++;
+ }
+
+ /* get messages key for menu entry */
+ menu_text = strrchr(text, '.');
+ if (!menu_text)
+ /* no '.' => top-level entry */
+ menu_text = text;
+ else
+ menu_text++; /* and move past the '.' */
+
+ /* fill in submenu data */
+ if (menu->entries[id].sub_window)
+ new_menu->entries[entry].sub_menu =
+ (wimp_menu *) (*menu->entries[id].sub_window);
+
+ /* this is fixed up in ro_gui_menu_translate() */
+ new_menu->entries[entry].data.indirected_text.text = NULL;
+
+ /* create definition entry */
+ definition_entry =
+ malloc(sizeof(struct menu_definition_entry));
+ if (!definition_entry)
+ die("Unable to create menu definition entry");
+ definition_entry->action = menu->entries[id].action;
+ definition_entry->menu_entry = &new_menu->entries[entry];
+ definition_entry->entry_key = menu_text;
+ definition_entry->next = definition->entries;
+ definition->entries = definition_entry;
+
+ /* recurse */
+ if (new_menu->entries[entry].sub_menu == wimp_NO_SUB_MENU) {
+ ro_gui_menu_define_menu_add(definition, menu,
+ depth + 1, &new_menu->entries[entry],
+ matches[entry], matches[entry + 1],
+ text, strlen(text));
+ }
+
+ /* give menu warnings */
+ if (new_menu->entries[entry].sub_menu != wimp_NO_SUB_MENU)
+ new_menu->entries[entry].menu_flags |=
+ wimp_MENU_GIVE_WARNING;
+ }
+ new_menu->entries[0].menu_flags |= wimp_MENU_TITLE_INDIRECTED;
+ new_menu->entries[entries - 1].menu_flags |= wimp_MENU_LAST;
+}
+
+
+/**
+ * Initialise the basic state of a menu structure so all entries are
+ * indirected text with no flags, no submenu.
+ */
+void ro_gui_menu_init_structure(wimp_menu *menu, int entries)
+{
+ int i;
+
+ menu->title_fg = wimp_COLOUR_BLACK;
+ menu->title_bg = wimp_COLOUR_LIGHT_GREY;
+ menu->work_fg = wimp_COLOUR_BLACK;
+ menu->work_bg = wimp_COLOUR_WHITE;
+ menu->width = 200;
+ menu->height = wimp_MENU_ITEM_HEIGHT;
+ menu->gap = wimp_MENU_ITEM_GAP;
+
+ for (i = 0; i < entries; i++) {
+ menu->entries[i].menu_flags = 0;
+ menu->entries[i].sub_menu = wimp_NO_SUB_MENU;
+ menu->entries[i].icon_flags =
+ DEFAULT_FLAGS | wimp_ICON_INDIRECTED;
+ menu->entries[i].data.indirected_text.validation =
+ (char *)-1;
+ }
+ menu->entries[0].menu_flags |= wimp_MENU_TITLE_INDIRECTED;
+ menu->entries[i - 1].menu_flags |= wimp_MENU_LAST;
+}
+
+
+/**
+ * Finds the menu_definition corresponding to a wimp_menu.
+ *
+ * \param menu the menu to find the definition for
+ * \return the associated definition, or NULL if one could not be found
+ */
+struct menu_definition *ro_gui_menu_find_menu(wimp_menu *menu)
+{
+ struct menu_definition *definition;
+
+ if (!menu)
+ return NULL;
+
+ for (definition = ro_gui_menu_definitions; definition;
+ definition = definition->next)
+ if (definition->menu == menu)
+ return definition;
+ return NULL;
+}
+
+
+/**
+ * Finds the key associated with a menu entry translation.
+ *
+ * \param menu the menu to search
+ * \param translated the translated text
+ * \return the original message key, or NULL if one could not be found
+ */
+const char *ro_gui_menu_find_menu_entry_key(wimp_menu *menu,
+ const char *translated)
+{
+ struct menu_definition_entry *entry;
+ struct menu_definition *definition = ro_gui_menu_find_menu(menu);
+
+ if (!definition)
+ return NULL;
+
+ for (entry = definition->entries; entry; entry = entry->next)
+ if (!strcmp(entry->menu_entry->data.indirected_text.text, translated))
+ return entry->entry_key;
+ return NULL;
+}
+
+
+/**
+ * Finds the menu_definition_entry corresponding to an action for a wimp_menu.
+ *
+ * \param menu the menu to search for an action within
+ * \param action the action to find
+ * \return the associated menu entry, or NULL if one could not be found
+ */
+struct menu_definition_entry *ro_gui_menu_find_entry(wimp_menu *menu,
+ menu_action action)
+{
+ struct menu_definition_entry *entry;
+ struct menu_definition *definition = ro_gui_menu_find_menu(menu);
+
+ if (!definition)
+ return NULL;
+
+ for (entry = definition->entries; entry; entry = entry->next)
+ if (entry->action == action)
+ return entry;
+ return NULL;
+}
+
+
+/**
+ * Finds the action corresponding to a wimp_menu_entry for a wimp_menu.
+ *
+ * \param menu the menu to search for an action within
+ * \param menu_entry the menu_entry to find
+ * \return the associated action, or 0 if one could not be found
+ */
+menu_action ro_gui_menu_find_action(wimp_menu *menu, wimp_menu_entry *menu_entry)
+{
+ struct menu_definition_entry *entry;
+ struct menu_definition *definition = ro_gui_menu_find_menu(menu);
+
+ if (!definition)
+ return NO_ACTION;
+
+ for (entry = definition->entries; entry; entry = entry->next) {
+ if (entry->menu_entry == menu_entry)
+ return entry->action;
+ }
+ return NO_ACTION;
+}
+
+
+/**
+ * Sets an action within a menu as having a specific ticked status.
+ *
+ * \param menu the menu containing the action
+ * \param action the action to tick/untick
+ * \param shaded whether to set the item as shaded
+ */
+void ro_gui_menu_set_entry_shaded(wimp_menu *menu, menu_action action,
+ bool shaded)
+{
+ struct menu_definition_entry *entry;
+ struct menu_definition *definition = ro_gui_menu_find_menu(menu);
+
+ if (!definition)
+ return;
+
+ /* we can't use find_entry as multiple actions may appear in one menu */
+ for (entry = definition->entries; entry; entry = entry->next)
+ if (entry->action == action) {
+ if (shaded)
+ entry->menu_entry->icon_flags |= wimp_ICON_SHADED;
+ else
+ entry->menu_entry->icon_flags &= ~wimp_ICON_SHADED;
+ }
+}
+
+
+/**
+ * Sets an action within a menu as having a specific ticked status.
+ *
+ * \param menu the menu containing the action
+ * \param action the action to tick/untick
+ * \param ticked whether to set the item as ticked
+ */
+void ro_gui_menu_set_entry_ticked(wimp_menu *menu, menu_action action,
+ bool ticked)
+{
+ struct menu_definition_entry *entry =
+ ro_gui_menu_find_entry(menu, action);
+ if (entry) {
+ if (ticked)
+ entry->menu_entry->menu_flags |= wimp_MENU_TICKED;
+ else
+ entry->menu_entry->menu_flags &= ~wimp_MENU_TICKED;
+ }
+}
+
+
+/**
+ * Calculates a simple checksum for the current menu state
+ */
+int ro_gui_menu_get_checksum(void)
+{
+ wimp_selection menu_tree;
+ int i = 0, j, checksum = 0;
+ os_error *error;
+ wimp_menu *menu;
+
+ if (!current_menu_open)
+ return 0;
+
+ error = xwimp_get_menu_state((wimp_menu_state_flags)0,
+ &menu_tree, 0, 0);
+ if (error) {
+ LOG("xwimp_get_menu_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("MenuError", error->errmess);
+ return 0;
+ }
+
+ menu = current_menu;
+ do {
+ j = 0;
+ do {
+ if (menu->entries[j].icon_flags & wimp_ICON_SHADED)
+ checksum ^= (1 << (i + j * 2));
+ if (menu->entries[j].menu_flags & wimp_MENU_TICKED)
+ checksum ^= (2 << (i + j * 2));
+ } while (!(menu->entries[j++].menu_flags & wimp_MENU_LAST));
+
+ j = menu_tree.items[i++];
+ if (j != -1) {
+ menu = menu->entries[j].sub_menu;
+ if ((!menu) || (menu == wimp_NO_SUB_MENU) || (!IS_MENU(menu)))
+ break;
+ }
+ } while (j != -1);
+
+ return checksum;
+}
+
+/**
+ * Translate a menu's textual content into the system local encoding
+ *
+ * \param menu The menu to translate
+ * \return false if out of memory, true otherwise
+ */
+bool ro_gui_menu_translate(struct menu_definition *menu)
+{
+ os_error *error;
+ int alphabet;
+ struct menu_definition_entry *entry;
+ char *translated;
+ nserror err;
+
+ /* read current alphabet */
+ error = xosbyte1(osbyte_ALPHABET_NUMBER, 127, 0, &alphabet);
+ if (error) {
+ LOG("failed reading alphabet: 0x%x: %s", error->errnum, error->errmess);
+ /* assume Latin1 */
+ alphabet = territory_ALPHABET_LATIN1;
+ }
+
+ if (menu->current_encoding == alphabet)
+ /* menu text is already in the correct encoding */
+ return true;
+
+ /* translate root menu title text */
+ free(menu->menu->title_data.indirected_text.text);
+ err = utf8_to_local_encoding(messages_get(menu->title_key),
+ 0, &translated);
+ if (err != NSERROR_OK) {
+ assert(err != NSERROR_BAD_ENCODING);
+ LOG("utf8_to_enc failed");
+ return false;
+ }
+
+ /* and fill in WIMP menu field */
+ menu->menu->title_data.indirected_text.text = translated;
+
+ /* now the menu entries */
+ for (entry = menu->entries; entry; entry = entry->next) {
+ wimp_menu *submenu = entry->menu_entry->sub_menu;
+
+ /* tranlate menu entry text */
+ free(entry->menu_entry->data.indirected_text.text);
+ err = utf8_to_local_encoding(messages_get(entry->entry_key),
+ 0, &translated);
+ if (err != NSERROR_OK) {
+ assert(err != NSERROR_BAD_ENCODING);
+ LOG("utf8_to_enc failed");
+ return false;
+ }
+
+ /* fill in WIMP menu fields */
+ entry->menu_entry->data.indirected_text.text = translated;
+ entry->menu_entry->data.indirected_text.validation =
+ (char *) -1;
+ entry->menu_entry->data.indirected_text.size =
+ strlen(translated);
+
+ /* child menu title - this is the same as the text of
+ * the parent menu entry, so just copy the pointer */
+ if (submenu != wimp_NO_SUB_MENU && IS_MENU(submenu)) {
+ submenu->title_data.indirected_text.text =
+ translated;
+ }
+ }
+
+ /* finally, set the current encoding of the menu */
+ menu->current_encoding = alphabet;
+
+ return true;
+}
+
diff --git a/frontends/riscos/menus.h b/frontends/riscos/menus.h
new file mode 100644
index 000000000..7faa87ed6
--- /dev/null
+++ b/frontends/riscos/menus.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright 2005 Richard Wilson <info@tinct.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _NETSURF_RISCOS_MENUS_H_
+#define _NETSURF_RISCOS_MENUS_H_
+
+extern wimp_menu *image_quality_menu, *proxy_type_menu, *languages_menu;
+
+extern wimp_menu *current_menu;
+
+typedef enum {
+
+ /* no/unknown actions */
+ NO_ACTION,
+
+ /* help actions */
+ HELP_OPEN_CONTENTS,
+ HELP_OPEN_GUIDE,
+ HELP_OPEN_INFORMATION,
+ HELP_OPEN_CREDITS,
+ HELP_OPEN_LICENCE,
+ HELP_LAUNCH_INTERACTIVE,
+
+ /* history actions */
+ HISTORY_SHOW_LOCAL,
+ HISTORY_SHOW_GLOBAL,
+
+ /* hotlist actions */
+ HOTLIST_ADD_URL,
+ HOTLIST_SHOW,
+
+ /* cookie actions */
+ COOKIES_SHOW,
+ COOKIES_DELETE,
+
+ /* page actions */
+ BROWSER_PAGE,
+ BROWSER_PAGE_INFO,
+ BROWSER_PRINT,
+ BROWSER_NEW_WINDOW,
+ BROWSER_VIEW_SOURCE,
+
+ /* object actions */
+ BROWSER_OBJECT,
+ BROWSER_OBJECT_OBJECT,
+ BROWSER_OBJECT_LINK,
+ BROWSER_OBJECT_INFO,
+ BROWSER_OBJECT_PRINT,
+ BROWSER_OBJECT_RELOAD,
+ BROWSER_LINK_SAVE,
+ BROWSER_LINK_DOWNLOAD,
+ BROWSER_LINK_NEW_WINDOW,
+
+ /* save actions */
+ BROWSER_OBJECT_SAVE,
+ BROWSER_OBJECT_EXPORT,
+ BROWSER_OBJECT_EXPORT_SPRITE,
+ BROWSER_OBJECT_EXPORT_DRAW,
+ BROWSER_OBJECT_SAVE_URL_URI,
+ BROWSER_OBJECT_SAVE_URL_URL,
+ BROWSER_OBJECT_SAVE_URL_TEXT,
+ BROWSER_SAVE,
+ BROWSER_SAVE_COMPLETE,
+ BROWSER_EXPORT_DRAW,
+ BROWSER_EXPORT_PDF,
+ BROWSER_EXPORT_TEXT,
+ BROWSER_SAVE_URL_URI,
+ BROWSER_SAVE_URL_URL,
+ BROWSER_SAVE_URL_TEXT,
+ BROWSER_LINK_SAVE_URI,
+ BROWSER_LINK_SAVE_URL,
+ BROWSER_LINK_SAVE_TEXT,
+ HOTLIST_EXPORT,
+ HISTORY_EXPORT,
+
+ /* selection actions */
+ BROWSER_SELECTION,
+ BROWSER_SELECTION_SAVE,
+ BROWSER_SELECTION_COPY,
+ BROWSER_SELECTION_CUT,
+ BROWSER_SELECTION_PASTE,
+ BROWSER_SELECTION_CLEAR,
+ BROWSER_SELECTION_ALL,
+
+ /* navigation actions */
+ BROWSER_NAVIGATE_HOME,
+ BROWSER_NAVIGATE_BACK,
+ BROWSER_NAVIGATE_FORWARD,
+ BROWSER_NAVIGATE_UP,
+ BROWSER_NAVIGATE_RELOAD,
+ BROWSER_NAVIGATE_RELOAD_ALL,
+ BROWSER_NAVIGATE_STOP,
+ BROWSER_NAVIGATE_URL,
+
+ /* browser window/display actions */
+ BROWSER_SCALE_VIEW,
+ BROWSER_FIND_TEXT,
+ BROWSER_IMAGES_FOREGROUND,
+ BROWSER_IMAGES_BACKGROUND,
+ BROWSER_BUFFER_ANIMS,
+ BROWSER_BUFFER_ALL,
+ BROWSER_SAVE_VIEW,
+ BROWSER_WINDOW_DEFAULT,
+ BROWSER_WINDOW_STAGGER,
+ BROWSER_WINDOW_COPY,
+ BROWSER_WINDOW_RESET,
+
+ /* tree actions */
+ TREE_NEW_FOLDER,
+ TREE_NEW_LINK,
+ TREE_EXPAND_ALL,
+ TREE_EXPAND_FOLDERS,
+ TREE_EXPAND_LINKS,
+ TREE_COLLAPSE_ALL,
+ TREE_COLLAPSE_FOLDERS,
+ TREE_COLLAPSE_LINKS,
+ TREE_SELECTION,
+ TREE_SELECTION_EDIT,
+ TREE_SELECTION_LAUNCH,
+ TREE_SELECTION_DELETE,
+ TREE_SELECT_ALL,
+ TREE_CLEAR_SELECTION,
+
+ /* toolbar actions */
+ TOOLBAR_BUTTONS,
+ TOOLBAR_ADDRESS_BAR,
+ TOOLBAR_THROBBER,
+ TOOLBAR_EDIT,
+
+ /* misc actions */
+ CHOICES_SHOW,
+ APPLICATION_QUIT,
+} menu_action;
+
+
+/* Menu entry structures for use when defining menus. */
+
+struct ns_menu_entry {
+ const char *text; /**< menu text (from messages) */
+ menu_action action; /**< associated action */
+ wimp_w *sub_window; /**< sub-window if any */
+};
+
+struct ns_menu {
+ const char *title;
+ struct ns_menu_entry entries[];
+};
+
+
+void ro_gui_menu_init(void);
+void ro_gui_menu_create(wimp_menu* menu, int x, int y, wimp_w w);
+void ro_gui_menu_destroy(void);
+void ro_gui_popup_menu(wimp_menu *menu, wimp_w w, wimp_i i);
+void ro_gui_menu_window_changed(wimp_w from, wimp_w to);
+void ro_gui_menu_selection(wimp_selection* selection);
+void ro_gui_menu_warning(wimp_message_menu_warning *warning);
+void ro_gui_menu_message_deleted(wimp_message_menus_deleted *deleted);
+void ro_gui_menu_refresh(wimp_menu *menu);
+void ro_gui_menu_init_structure(wimp_menu *menu, int entries);
+const char *ro_gui_menu_find_menu_entry_key(wimp_menu *menu,
+ const char *translated);
+wimp_menu *ro_gui_menu_define_menu(const struct ns_menu *menu);
+void ro_gui_menu_set_entry_shaded(wimp_menu *menu, menu_action action,
+ bool shaded);
+void ro_gui_menu_set_entry_ticked(wimp_menu *menu, menu_action action,
+ bool ticked);
+
+#endif
diff --git a/frontends/riscos/message.c b/frontends/riscos/message.c
new file mode 100644
index 000000000..1c54ea0b7
--- /dev/null
+++ b/frontends/riscos/message.c
@@ -0,0 +1,247 @@
+/*
+ * Copyright 2006 Richard Wilson <info@tinct.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Automated RISC OS message routing (implementation).
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include "oslib/os.h"
+#include "oslib/wimp.h"
+
+#include "utils/log.h"
+
+#include "riscos/message.h"
+#include "riscos/gui.h"
+
+struct active_message {
+ unsigned int message_code;
+ int id;
+ void (*callback)(wimp_message *message);
+ struct active_message *next;
+ struct active_message *previous;
+};
+struct active_message *current_messages = NULL;
+
+static struct active_message *ro_message_add(unsigned int message_code,
+ void (*callback)(wimp_message *message));
+static void ro_message_free(int ref);
+
+
+/**
+ * Sends a message and registers a return route for a bounce.
+ *
+ * \param event the message event type
+ * \param message the message to register a route back for
+ * \param task the task to send a message to, or 0 for broadcast
+ * \param callback the code to call on a bounce
+ * \return true on success, false otherwise
+ */
+bool ro_message_send_message(wimp_event_no event, wimp_message *message,
+ wimp_t task, void (*callback)(wimp_message *message))
+{
+ os_error *error;
+
+ assert(message);
+
+ /* send a message */
+ error = xwimp_send_message(event, message, task);
+ if (error) {
+ LOG("xwimp_send_message: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return false;
+ }
+
+ /* register the default bounce handler */
+ if (callback) {
+ assert(event == wimp_USER_MESSAGE_RECORDED);
+ return ro_message_register_handler(message, message->action,
+ callback);
+ }
+ return true;
+}
+
+
+/**
+ * Sends a message and registers a return route for a bounce.
+ *
+ * \param event the message event type
+ * \param message the message to register a route back for
+ * \param to_w the window to send the message to
+ * \param to_i the icon
+ * \param callback the code to call on a bounce
+ * \param to_t receives the task handle of the window's creator
+ * \return true on success, false otherwise
+ */
+bool ro_message_send_message_to_window(wimp_event_no event, wimp_message *message,
+ wimp_w to_w, wimp_i to_i, void (*callback)(wimp_message *message),
+ wimp_t *to_t)
+{
+ os_error *error;
+
+ assert(message);
+
+ /* send a message */
+ error = xwimp_send_message_to_window(event, message, to_w, to_i, to_t);
+ if (error) {
+ LOG("xwimp_send_message_to_window: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return false;
+ }
+
+ /* register the default bounce handler */
+ if (callback) {
+ assert(event == wimp_USER_MESSAGE_RECORDED);
+ return ro_message_register_handler(message, message->action,
+ callback);
+ }
+ return true;
+}
+
+
+/**
+ * Registers a return route for a message.
+ *
+ * This function must be called after wimp_send_message so that a
+ * valid value is present in the my_ref field.
+ *
+ * \param message the message to register a route back for
+ * \param message_code the message action code to route
+ * \param callback the code to call for a matched action
+ * \return true on success, false on memory exhaustion
+ */
+bool ro_message_register_handler(wimp_message *message,
+ unsigned int message_code,
+ void (*callback)(wimp_message *message))
+{
+ struct active_message *add;
+
+ assert(message);
+ assert(callback);
+
+ add = ro_message_add(message_code, callback);
+ if (add)
+ add->id = message->my_ref;
+ return (add != NULL);
+}
+
+
+/**
+ * Registers a route for a message code.
+ *
+ * \param message_code the message action code to route
+ * \param callback the code to call for a matched action
+ * \return true on success, false on memory exhaustion
+ */
+bool ro_message_register_route(unsigned int message_code,
+ void (*callback)(wimp_message *message))
+{
+ assert(callback);
+
+ return (ro_message_add(message_code, callback) != NULL);
+}
+
+struct active_message *ro_message_add(unsigned int message_code,
+ void (*callback)(wimp_message *message))
+{
+ struct active_message *add;
+
+ assert(callback);
+
+ add = (struct active_message *)malloc(sizeof(*add));
+ if (!add)
+ return NULL;
+ add->message_code = message_code;
+ add->id = 0;
+ add->callback = callback;
+ add->next = current_messages;
+ add->previous = NULL;
+ current_messages = add;
+ return add;
+}
+
+
+/**
+ * Attempts to route a message.
+ *
+ * \param event wimp event
+ * \param message the message to attempt to route
+ * \return true if message was routed, false otherwise
+ */
+bool ro_message_handle_message(wimp_event_no event, wimp_message *message)
+{
+ struct active_message *test;
+
+ assert(message);
+
+ if (event == wimp_USER_MESSAGE_ACKNOWLEDGE) {
+ /* handle message acknowledgement */
+ bool handled = false;
+ int ref = message->my_ref;
+
+ if (ref == 0)
+ return false;
+
+ /* handle the message */
+ for (test = current_messages; test; test = test->next) {
+ if ((ref == test->id) &&
+ (message->action == test->message_code)) {
+ handled = true;
+ if (test->callback)
+ test->callback(message);
+ break;
+ }
+ }
+
+ /* remove all handlers for this id */
+ ro_message_free(ref);
+ return handled;
+ } else {
+ /* handle simple routing */
+ for (test = current_messages; test; test = test->next) {
+ if ((test->id == 0) &&
+ (message->action == test->message_code)) {
+ test->callback(message);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+
+void ro_message_free(int ref)
+{
+ struct active_message *test;
+ struct active_message *next = current_messages;
+
+ while ((test = next)) {
+ next = test->next;
+ if (ref == test->id) {
+ if (test->previous)
+ test->previous->next = test->next;
+ if (test->next)
+ test->next->previous = test->previous;
+ if (current_messages == test)
+ current_messages = test->next;
+ free(test);
+ }
+ }
+}
diff --git a/frontends/riscos/message.h b/frontends/riscos/message.h
new file mode 100644
index 000000000..8c1a515f2
--- /dev/null
+++ b/frontends/riscos/message.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2006 Richard Wilson <info@tinct.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Automated RISC OS message routing (interface).
+ */
+
+
+#ifndef _NETSURF_RISCOS_MESSAGE_H_
+#define _NETSURF_RISCOS_MESSAGE_H_
+
+#include <stdbool.h>
+#include "oslib/wimp.h"
+
+bool ro_message_send_message(wimp_event_no event, wimp_message *message,
+ wimp_t task, void (*callback)(wimp_message *message));
+bool ro_message_send_message_to_window(wimp_event_no event, wimp_message *message,
+ wimp_w to_w, wimp_i to_i, void (*callback)(wimp_message *message),
+ wimp_t *to_t);
+bool ro_message_register_handler(wimp_message *message,
+ unsigned int message_code,
+ void (*callback)(wimp_message *message));
+bool ro_message_register_route(unsigned int message_code,
+ void (*callback)(wimp_message *message));
+bool ro_message_handle_message(wimp_event_no event, wimp_message *message);
+
+#endif
diff --git a/frontends/riscos/mouse.c b/frontends/riscos/mouse.c
new file mode 100644
index 000000000..a0cc0e7ce
--- /dev/null
+++ b/frontends/riscos/mouse.c
@@ -0,0 +1,282 @@
+/*
+ * Copyright 2013 Stephen Fryatt <stevef@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Mouse dragging and tracking support implementation.
+ *
+ * Two different functions are provided:-
+ *
+ * 1. Wimp_DragBox support, allowing clients to start a drag and specify
+ * callbacks to be used
+ *
+ * - on Null Polls while the drag is active,
+ * - when the drag terminates with Event_DragEnd, and
+ * - when the drag terminates with Escape being pressed.
+ *
+ * 2. Mouse tracking support, allowing clients to track the mouse while it
+ * remains in the current window and specify callbacks to be used
+ *
+ * - on Null Polls while the pointer is in the window, and
+ * - when the pointer leaves the window.
+ */
+
+#include <assert.h>
+#include <oslib/wimp.h>
+
+#include "utils/log.h"
+
+#include "riscos/mouse.h"
+#include "riscos/gui.h"
+
+/* Data for the wimp drag handler. */
+
+static void (*ro_mouse_drag_end_callback)(wimp_dragged *dragged, void *data)
+ = NULL;
+static void (*ro_mouse_drag_track_callback)(wimp_pointer *pointer, void *data)
+ = NULL;
+static void (*ro_mouse_drag_cancel_callback)(void *data) = NULL;
+static void *ro_mouse_drag_data = NULL;
+
+static bool ro_mouse_ignore_leaving_event = false;
+
+/* Data for the wimp poll handler. */
+
+static void (*ro_mouse_poll_end_callback)(wimp_leaving *leaving, void *data)
+ = NULL;
+static void (*ro_mouse_poll_track_callback)(wimp_pointer *pointer, void *data)
+ = NULL;
+static void *ro_mouse_poll_data = NULL;
+
+
+/**
+ * Process Null polls for any drags and mouse trackers that are currently
+ * active.
+ */
+
+void ro_mouse_poll(void)
+{
+ wimp_pointer pointer;
+ os_error *error;
+
+ /* If no trackers are active, just exit. */
+
+ if (ro_mouse_drag_track_callback == NULL &&
+ ro_mouse_poll_track_callback == NULL)
+ return;
+
+ error = xwimp_get_pointer_info(&pointer);
+ if (error) {
+ LOG("xwimp_get_pointer_info: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ /* Process the drag tracker, if one is active. */
+
+ if (ro_mouse_drag_track_callback != NULL)
+ ro_mouse_drag_track_callback(&pointer, ro_mouse_drag_data);
+
+ /* Process the window tracker, if one is active. */
+
+ if (ro_mouse_poll_track_callback != NULL)
+ ro_mouse_poll_track_callback(&pointer, ro_mouse_poll_data);
+}
+
+
+/**
+ * Start a drag, providing a function to be called when the Wimp_DragEnd event
+ * is received and optionally a tracking function to be called on null polls
+ * in between times.
+ *
+ * \param *drag_end Callback for when the drag terminates, or NULL for none.
+ * \param *drag_track Callback for mouse tracking during the drag, or NULL for
+ * none.
+ * \param *drag_cancel Callback for cancelling the drag, or NULL if the drag
+ * can't be cancelled.
+ * \param *data Data to be passed to the callback functions, or NULL.
+ */
+
+void ro_mouse_drag_start(void (*drag_end)(wimp_dragged *dragged, void *data),
+ void (*drag_track)(wimp_pointer *pointer, void *data),
+ void (*drag_cancel)(void *data), void *data)
+{
+ /* A drag should never be started when one is already in progress. */
+
+ assert(ro_mouse_drag_end_callback == NULL &&
+ ro_mouse_drag_track_callback == NULL &&
+ ro_mouse_drag_cancel_callback == NULL &&
+ ro_mouse_drag_data == NULL);
+
+ ro_mouse_drag_end_callback = drag_end;
+ ro_mouse_drag_track_callback = drag_track;
+ ro_mouse_drag_cancel_callback = drag_cancel;
+ ro_mouse_drag_data = data;
+
+ /* The Wimp sends a PointerLeaving event when Wimp_DragBox is called,
+ * so we mask out the next event that will come our way.
+ */
+
+ ro_mouse_ignore_leaving_event = true;
+}
+
+
+/**
+ * Process Wimp_DragEnd events by terminating an active drag track and passing
+ * the details on to any registered event handler.
+ *
+ * \param *dragged The Wimp_DragEnd data block.
+ */
+
+void ro_mouse_drag_end(wimp_dragged *dragged)
+{
+ if (ro_mouse_drag_end_callback != NULL)
+ ro_mouse_drag_end_callback(dragged, ro_mouse_drag_data);
+ else
+ ro_warn_user("WimpError", "No callback");
+
+ /* Wimp_DragEnd is a one-shot event, so clear the data ready for
+ * another claimant.
+ */
+
+ ro_mouse_drag_end_callback = NULL;
+ ro_mouse_drag_track_callback = NULL;
+ ro_mouse_drag_cancel_callback = NULL;
+ ro_mouse_drag_data = NULL;
+}
+
+
+/**
+ * Start tracking the mouse in a window, providing a function to be called on
+ * null polls and optionally one to be called when it leaves the window.
+ *
+ * \param *poll_end Callback for when the pointer leaves the window, or
+ * NULL for none. Claimants can receive *leaving==NULL if
+ * a new tracker is started before a PointerLeaving event
+ * is received.
+ * \param *poll_track Callback for mouse tracking while the pointer remains
+ * in the window, or NULL for none.
+ * \param *data Data to be passed to the callback functions, or NULL.
+ */
+
+void ro_mouse_track_start(void (*poll_end)(wimp_leaving *leaving, void *data),
+ void (*poll_track)(wimp_pointer *pointer, void *data),
+ void *data)
+{
+ /* It should never be possible for the mouse to be in two windows
+ * at the same time! However, some third-party extensions to RISC OS
+ * appear to make this possible (MouseAxess being one), so in the
+ * event that there's still a claimant we tidy them up first and then
+ * log the fact in case there are any unexpected consequences.
+ *
+ * NB: The Poll End callback will get called with *leaving == NULL in
+ * this situation, as there's no PointerLeaving event to pass on.
+ */
+
+ if (ro_mouse_poll_end_callback != NULL ||
+ ro_mouse_poll_track_callback != NULL ||
+ ro_mouse_poll_data != NULL) {
+ if (ro_mouse_poll_end_callback != NULL &&
+ ro_mouse_ignore_leaving_event == false)
+ ro_mouse_poll_end_callback(NULL, ro_mouse_poll_data);
+
+ LOG("Unexpected mouse track termination.");
+
+ ro_mouse_ignore_leaving_event = false;
+ ro_mouse_poll_end_callback = NULL;
+ ro_mouse_poll_track_callback = NULL;
+ ro_mouse_poll_data = NULL;
+ }
+
+ /* Now record details of the new claimant. */
+
+ ro_mouse_poll_end_callback = poll_end;
+ ro_mouse_poll_track_callback = poll_track;
+ ro_mouse_poll_data = data;
+}
+
+
+/**
+ * Process Wimp_PointerLeaving events by terminating an active mouse track and
+ * passing the details on to any registered event handler.
+ *
+ * If the ignore mask is set, we don't pass the event on to the client as it
+ * is assumed that it's a result of starting a Wimp_DragBox operation.
+ *
+ * \param *leaving The Wimp_PointerLeaving data block.
+ */
+
+void ro_mouse_pointer_leaving_window(wimp_leaving *leaving)
+{
+ if (ro_mouse_poll_end_callback != NULL &&
+ ro_mouse_ignore_leaving_event == false)
+ ro_mouse_poll_end_callback(leaving, ro_mouse_poll_data);
+
+ ro_mouse_ignore_leaving_event = false;
+
+ /* Poll tracking is a one-shot event, so clear the data ready for
+ * another claimant.
+ */
+
+ ro_mouse_poll_end_callback = NULL;
+ ro_mouse_poll_track_callback = NULL;
+ ro_mouse_poll_data = NULL;
+}
+
+
+/**
+ * Kill any tracking events if the data pointers match the supplied pointer.
+ *
+ * \param *data The data of the client to be killed.
+ */
+
+void ro_mouse_kill(void *data)
+{
+ if (data == ro_mouse_drag_data) {
+ ro_mouse_drag_end_callback = NULL;
+ ro_mouse_drag_track_callback = NULL;
+ ro_mouse_drag_cancel_callback = NULL;
+ ro_mouse_drag_data = NULL;
+ }
+
+ if (data == ro_mouse_poll_data) {
+ ro_mouse_poll_end_callback = NULL;
+ ro_mouse_poll_track_callback = NULL;
+ ro_mouse_poll_data = NULL;
+ }
+}
+
+
+/**
+ * Return the desired polling interval to allow the mouse tracking to be
+ * carried out.
+ *
+ * \return Desired poll interval (0 for none required).
+ */
+
+os_t ro_mouse_poll_interval(void)
+{
+ if (ro_mouse_drag_track_callback != NULL)
+ return 4;
+
+ if (ro_mouse_poll_track_callback != NULL)
+ return 10;
+
+ return 0;
+
+}
+
diff --git a/frontends/riscos/mouse.h b/frontends/riscos/mouse.h
new file mode 100644
index 000000000..6bc5c13e1
--- /dev/null
+++ b/frontends/riscos/mouse.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2013 Stephen Fryatt <stevef@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+/** \file
+ * Mouse dragging and tracking support interface for RISC OS.
+ */
+
+#ifndef _NETSURF_RISCOS_MOUSE_H_
+#define _NETSURF_RISCOS_MOUSE_H_
+
+
+/**
+ * Process Null polls for any drags and mouse trackers that are currently
+ * active.
+ */
+
+void ro_mouse_poll(void);
+
+
+/**
+ * Start a drag, providing a function to be called when the Wimp_DragEnd event
+ * is received and optionally a tracking function to be called on null polls
+ * in between times.
+ *
+ * \param *drag_end Callback for when the drag terminates, or NULL for none.
+ * \param *drag_track Callback for mouse tracking during the drag, or NULL for
+ * none.
+ * \param *drag_cancel Callback for cancelling the drag, or NULL if the drag
+ * can't be cancelled.
+ * \param *data Data to be passed to the callback functions, or NULL.
+ */
+
+void ro_mouse_drag_start(void (*drag_end)(wimp_dragged *dragged, void *data),
+ void (*drag_track)(wimp_pointer *pointer, void *data),
+ void (*drag_cancel)(void *data), void *data);
+
+
+/**
+ * Process Wimp_DragEnd events by passing the details on to any registered
+ * event handler.
+ *
+ * \param *dragged The Wimp_DragEnd data block.
+ */
+
+void ro_mouse_drag_end(wimp_dragged *dragged);
+
+
+/**
+ * Start tracking the mouse in a window, providing a function to be called on
+ * null polls and optionally one to be called when it leaves the window.
+ *
+ * \param *poll_end Callback for when the pointer leaves the window, or
+ * NULL for none. Claimants can receive *leaving==NULL if
+ * a new tracker is started before a PointerLeaving event
+ * is received.
+ * \param *poll_track Callback for mouse tracking while the pointer remains
+ * in the window, or NULL for none.
+ * \param *data Data to be passed to the callback functions, or NULL.
+ */
+
+void ro_mouse_track_start(void (*poll_end)(wimp_leaving *leaving, void *data),
+ void (*poll_track)(wimp_pointer *pointer, void *data),
+ void *data);
+
+/**
+ * Process Wimp_PointerLeaving events by terminating an active mouse track and
+ * passing the details on to any registered event handler.
+ *
+ * \param *leaving The Wimp_PointerLeaving data block.
+ */
+
+void ro_mouse_pointer_leaving_window(wimp_leaving *leaving);
+
+
+/**
+ * Kill any tracking events if the data pointers match the supplied pointer.
+ *
+ * \param *data The data of the client to be killed.
+ */
+
+void ro_mouse_kill(void *data);
+
+
+/**
+ * Return the desired polling interval to allow the mouse tracking to be
+ * carried out.
+ *
+ * \return Desired poll interval (0 for none required).
+ */
+
+os_t ro_mouse_poll_interval(void);
+
+#endif
+
diff --git a/frontends/riscos/options.h b/frontends/riscos/options.h
new file mode 100644
index 000000000..cb2b78bd8
--- /dev/null
+++ b/frontends/riscos/options.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2012 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * RISC OS specific options.
+ */
+
+#ifndef _NETSURF_RISCOS_OPTIONS_H_
+#define _NETSURF_RISCOS_OPTIONS_H_
+
+#include "riscos/tinct.h"
+
+/* setup longer default reflow time */
+#define DEFAULT_REFLOW_PERIOD 100 /* time in cs */
+
+#define CHOICES_PREFIX "<Choices$Write>.WWW.NetSurf."
+
+#endif
+
+NSOPTION_STRING(theme, "Aletheia")
+NSOPTION_STRING(language, NULL)
+NSOPTION_INTEGER(plot_fg_quality, tinct_ERROR_DIFFUSE)
+NSOPTION_INTEGER(plot_bg_quality, tinct_DITHER)
+NSOPTION_BOOL(history_tooltip, true)
+NSOPTION_BOOL(toolbar_show_buttons, true)
+NSOPTION_BOOL(toolbar_show_address, true)
+NSOPTION_BOOL(toolbar_show_throbber, true)
+NSOPTION_STRING(toolbar_browser, "0123|58|9")
+NSOPTION_STRING(toolbar_hotlist, "40|12|3")
+NSOPTION_STRING(toolbar_history, "0|12|3")
+NSOPTION_STRING(toolbar_cookies, "0|12")
+NSOPTION_BOOL(window_stagger, true)
+NSOPTION_BOOL(window_size_clone, true)
+NSOPTION_BOOL(buffer_animations, true)
+NSOPTION_BOOL(buffer_everything, true)
+NSOPTION_BOOL(open_browser_at_startup, false)
+NSOPTION_BOOL(no_plugins, false)
+NSOPTION_BOOL(block_popups, false)
+NSOPTION_BOOL(strip_extensions, false)
+NSOPTION_BOOL(confirm_overwrite, true)
+NSOPTION_BOOL(confirm_hotlist_remove, true)
+NSOPTION_STRING(url_path, "NetSurf:URL")
+NSOPTION_STRING(url_save, CHOICES_PREFIX "URL")
+NSOPTION_STRING(hotlist_path, "NetSurf:Hotlist")
+NSOPTION_STRING(hotlist_save, CHOICES_PREFIX "Hotlist")
+NSOPTION_STRING(recent_path, "NetSurf:Recent")
+NSOPTION_STRING(recent_save, CHOICES_PREFIX "Recent")
+NSOPTION_STRING(theme_path, "NetSurf:Themes")
+NSOPTION_STRING(theme_save, CHOICES_PREFIX "Themes")
+NSOPTION_BOOL(thumbnail_iconise, true)
+NSOPTION_BOOL(interactive_help, true)
+NSOPTION_BOOL(external_hotlists, false)
+NSOPTION_STRING(external_hotlist_app, NULL)
diff --git a/frontends/riscos/oslib_pre7.h b/frontends/riscos/oslib_pre7.h
new file mode 100644
index 000000000..a99bd0349
--- /dev/null
+++ b/frontends/riscos/oslib_pre7.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2008 John Tytgat <joty@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Backward compatible defines to make NetSurf buildable with pre-OSLib 7
+ * releases.
+ */
+
+#ifndef _NETSURF_RISCOS_OSLIB_PRE7_H_
+#define _NETSURF_RISCOS_OSLIB_PRE7_H_
+
+#include "oslib/colourtrans.h"
+
+/**
+ * After OSLib 6.90, there was a rename of colourtrans defines in order
+ * to avoid namespace clashes:
+ * svn diff -c 238 https://ro-oslib.svn.sourceforge.net/svnroot/ro-oslib/trunk/\!OSLib/Source/Core/oslib/ColourTrans.swi
+ * Foresee some backwards compatibility until we've switched to OSLib 7.
+*/
+#ifndef colourtrans_SET_BG_GCOL
+# define colourtrans_SET_BG_GCOL colourtrans_SET_BG
+#endif
+#ifndef colourtrans_USE_ECFS_GCOL
+# define colourtrans_USE_ECFS_GCOL colourtrans_USE_ECFS
+#endif
+
+#endif
diff --git a/frontends/riscos/palettes.c b/frontends/riscos/palettes.c
new file mode 100644
index 000000000..631d8802a
--- /dev/null
+++ b/frontends/riscos/palettes.c
@@ -0,0 +1,321 @@
+/*
+ * Copyright 2006 Adrian Lees <adrianl@users.sourceforge.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Palette definitions for sprites
+ */
+
+#include "riscos/palettes.h"
+
+
+const os_colour default_palette1[] =
+{
+ 0xffffff00, 0xffffff00,
+ 0x00000000, 0x00000000
+};
+
+
+const os_colour default_palette2[] =
+{
+ 0xffffff00, 0xffffff00,
+ 0xbbbbbb00, 0xbbbbbb00,
+ 0x77777700, 0x77777700,
+ 0x00000000, 0x00000000
+};
+
+
+const os_colour wimp_palette[] =
+{
+ 0xffffff00, 0xffffff00,
+ 0xdddddd00, 0xdddddd00,
+ 0xbbbbbb00, 0xbbbbbb00,
+ 0x99999900, 0x99999900,
+ 0x77777700, 0x77777700,
+ 0x55555500, 0x55555500,
+ 0x33333300, 0x33333300,
+ 0x00000000, 0x00000000,
+ 0x99440000, 0x99440000,
+ 0x00eeee00, 0x00eeee00,
+ 0x00cc0000, 0x00cc0000,
+ 0x0000dd00, 0x0000dd00,
+ 0xbbeeee00, 0xbbeeee00,
+ 0x00885500, 0x00885500,
+ 0x00bbff00, 0x00bbff00,
+ 0xffbb0000, 0xffbb0000
+};
+
+
+const os_colour default_palette8[] =
+{
+ 0x00000010, 0x00000010,
+ 0x11111110, 0x11111110,
+ 0x22222210, 0x22222210,
+ 0x33333310, 0x33333310,
+ 0x00004410, 0x00004410,
+ 0x11115510, 0x11115510,
+ 0x22226610, 0x22226610,
+ 0x33337710, 0x33337710,
+ 0x44000010, 0x44000010,
+ 0x55111110, 0x55111110,
+ 0x66222210, 0x66222210,
+ 0x77333310, 0x77333310,
+ 0x44004410, 0x44004410,
+ 0x55115510, 0x55115510,
+ 0x66226610, 0x66226610,
+ 0x77337710, 0x77337710,
+ 0x00008810, 0x00008810,
+ 0x11119910, 0x11119910,
+ 0x2222AA10, 0x2222AA10,
+ 0x3333BB10, 0x3333BB10,
+ 0x0000CC10, 0x0000CC10,
+ 0x1111DD10, 0x1111DD10,
+ 0x2222EE10, 0x2222EE10,
+ 0x3333FF10, 0x3333FF10,
+ 0x44008810, 0x44008810,
+ 0x55119910, 0x55119910,
+ 0x6622AA10, 0x6622AA10,
+ 0x7733BB10, 0x7733BB10,
+ 0x4400CC10, 0x4400CC10,
+ 0x5511DD10, 0x5511DD10,
+ 0x6622EE10, 0x6622EE10,
+ 0x7733FF10, 0x7733FF10,
+ 0x00440010, 0x00440010,
+ 0x11551110, 0x11551110,
+ 0x22662210, 0x22662210,
+ 0x33773310, 0x33773310,
+ 0x00444410, 0x00444410,
+ 0x11555510, 0x11555510,
+ 0x22666610, 0x22666610,
+ 0x33777710, 0x33777710,
+ 0x44440010, 0x44440010,
+ 0x55551110, 0x55551110,
+ 0x66662210, 0x66662210,
+ 0x77773310, 0x77773310,
+ 0x44444410, 0x44444410,
+ 0x55555510, 0x55555510,
+ 0x66666610, 0x66666610,
+ 0x77777710, 0x77777710,
+ 0x00448810, 0x00448810,
+ 0x11559910, 0x11559910,
+ 0x2266AA10, 0x2266AA10,
+ 0x3377BB10, 0x3377BB10,
+ 0x0044CC10, 0x0044CC10,
+ 0x1155DD10, 0x1155DD10,
+ 0x2266EE10, 0x2266EE10,
+ 0x3377FF10, 0x3377FF10,
+ 0x44448810, 0x44448810,
+ 0x55559910, 0x55559910,
+ 0x6666AA10, 0x6666AA10,
+ 0x7777BB10, 0x7777BB10,
+ 0x4444CC10, 0x4444CC10,
+ 0x5555DD10, 0x5555DD10,
+ 0x6666EE10, 0x6666EE10,
+ 0x7777FF10, 0x7777FF10,
+ 0x00880010, 0x00880010,
+ 0x11991110, 0x11991110,
+ 0x22AA2210, 0x22AA2210,
+ 0x33BB3310, 0x33BB3310,
+ 0x00884410, 0x00884410,
+ 0x11995510, 0x11995510,
+ 0x22AA6610, 0x22AA6610,
+ 0x33BB7710, 0x33BB7710,
+ 0x44880010, 0x44880010,
+ 0x55991110, 0x55991110,
+ 0x66AA2210, 0x66AA2210,
+ 0x77BB3310, 0x77BB3310,
+ 0x44884410, 0x44884410,
+ 0x55995510, 0x55995510,
+ 0x66AA6610, 0x66AA6610,
+ 0x77BB7710, 0x77BB7710,
+ 0x00888810, 0x00888810,
+ 0x11999910, 0x11999910,
+ 0x22AAAA10, 0x22AAAA10,
+ 0x33BBBB10, 0x33BBBB10,
+ 0x0088CC10, 0x0088CC10,
+ 0x1199DD10, 0x1199DD10,
+ 0x22AAEE10, 0x22AAEE10,
+ 0x33BBFF10, 0x33BBFF10,
+ 0x44888810, 0x44888810,
+ 0x55999910, 0x55999910,
+ 0x66AAAA10, 0x66AAAA10,
+ 0x77BBBB10, 0x77BBBB10,
+ 0x4488CC10, 0x4488CC10,
+ 0x5599DD10, 0x5599DD10,
+ 0x66AAEE10, 0x66AAEE10,
+ 0x77BBFF10, 0x77BBFF10,
+ 0x00CC0010, 0x00CC0010,
+ 0x11DD1110, 0x11DD1110,
+ 0x22EE2210, 0x22EE2210,
+ 0x33FF3310, 0x33FF3310,
+ 0x00CC4410, 0x00CC4410,
+ 0x11DD5510, 0x11DD5510,
+ 0x22EE6610, 0x22EE6610,
+ 0x33FF7710, 0x33FF7710,
+ 0x44CC0010, 0x44CC0010,
+ 0x55DD1110, 0x55DD1110,
+ 0x66EE2210, 0x66EE2210,
+ 0x77FF3310, 0x77FF3310,
+ 0x44CC4410, 0x44CC4410,
+ 0x55DD5510, 0x55DD5510,
+ 0x66EE6610, 0x66EE6610,
+ 0x77FF7710, 0x77FF7710,
+ 0x00CC8810, 0x00CC8810,
+ 0x11DD9910, 0x11DD9910,
+ 0x22EEAA10, 0x22EEAA10,
+ 0x33FFBB10, 0x33FFBB10,
+ 0x00CCCC10, 0x00CCCC10,
+ 0x11DDDD10, 0x11DDDD10,
+ 0x22EEEE10, 0x22EEEE10,
+ 0x33FFFF10, 0x33FFFF10,
+ 0x44CC8810, 0x44CC8810,
+ 0x55DD9910, 0x55DD9910,
+ 0x66EEAA10, 0x66EEAA10,
+ 0x77FFBB10, 0x77FFBB10,
+ 0x44CCCC10, 0x44CCCC10,
+ 0x55DDDD10, 0x55DDDD10,
+ 0x66EEEE10, 0x66EEEE10,
+ 0x77FFFF10, 0x77FFFF10,
+ 0x88000010, 0x88000010,
+ 0x99111110, 0x99111110,
+ 0xAA222210, 0xAA222210,
+ 0xBB333310, 0xBB333310,
+ 0x88004410, 0x88004410,
+ 0x99115510, 0x99115510,
+ 0xAA226610, 0xAA226610,
+ 0xBB337710, 0xBB337710,
+ 0xCC000010, 0xCC000010,
+ 0xDD111110, 0xDD111110,
+ 0xEE222210, 0xEE222210,
+ 0xFF333310, 0xFF333310,
+ 0xCC004410, 0xCC004410,
+ 0xDD115510, 0xDD115510,
+ 0xEE226610, 0xEE226610,
+ 0xFF337710, 0xFF337710,
+ 0x88008810, 0x88008810,
+ 0x99119910, 0x99119910,
+ 0xAA22AA10, 0xAA22AA10,
+ 0xBB33BB10, 0xBB33BB10,
+ 0x8800CC10, 0x8800CC10,
+ 0x9911DD10, 0x9911DD10,
+ 0xAA22EE10, 0xAA22EE10,
+ 0xBB33FF10, 0xBB33FF10,
+ 0xCC008810, 0xCC008810,
+ 0xDD119910, 0xDD119910,
+ 0xEE22AA10, 0xEE22AA10,
+ 0xFF33BB10, 0xFF33BB10,
+ 0xCC00CC10, 0xCC00CC10,
+ 0xDD11DD10, 0xDD11DD10,
+ 0xEE22EE10, 0xEE22EE10,
+ 0xFF33FF10, 0xFF33FF10,
+ 0x88440010, 0x88440010,
+ 0x99551110, 0x99551110,
+ 0xAA662210, 0xAA662210,
+ 0xBB773310, 0xBB773310,
+ 0x88444410, 0x88444410,
+ 0x99555510, 0x99555510,
+ 0xAA666610, 0xAA666610,
+ 0xBB777710, 0xBB777710,
+ 0xCC440010, 0xCC440010,
+ 0xDD551110, 0xDD551110,
+ 0xEE662210, 0xEE662210,
+ 0xFF773310, 0xFF773310,
+ 0xCC444410, 0xCC444410,
+ 0xDD555510, 0xDD555510,
+ 0xEE666610, 0xEE666610,
+ 0xFF777710, 0xFF777710,
+ 0x88448810, 0x88448810,
+ 0x99559910, 0x99559910,
+ 0xAA66AA10, 0xAA66AA10,
+ 0xBB77BB10, 0xBB77BB10,
+ 0x8844CC10, 0x8844CC10,
+ 0x9955DD10, 0x9955DD10,
+ 0xAA66EE10, 0xAA66EE10,
+ 0xBB77FF10, 0xBB77FF10,
+ 0xCC448810, 0xCC448810,
+ 0xDD559910, 0xDD559910,
+ 0xEE66AA10, 0xEE66AA10,
+ 0xFF77BB10, 0xFF77BB10,
+ 0xCC44CC10, 0xCC44CC10,
+ 0xDD55DD10, 0xDD55DD10,
+ 0xEE66EE10, 0xEE66EE10,
+ 0xFF77FF10, 0xFF77FF10,
+ 0x88880010, 0x88880010,
+ 0x99991110, 0x99991110,
+ 0xAAAA2210, 0xAAAA2210,
+ 0xBBBB3310, 0xBBBB3310,
+ 0x88884410, 0x88884410,
+ 0x99995510, 0x99995510,
+ 0xAAAA6610, 0xAAAA6610,
+ 0xBBBB7710, 0xBBBB7710,
+ 0xCC880010, 0xCC880010,
+ 0xDD991110, 0xDD991110,
+ 0xEEAA2210, 0xEEAA2210,
+ 0xFFBB3310, 0xFFBB3310,
+ 0xCC884410, 0xCC884410,
+ 0xDD995510, 0xDD995510,
+ 0xEEAA6610, 0xEEAA6610,
+ 0xFFBB7710, 0xFFBB7710,
+ 0x88888810, 0x88888810,
+ 0x99999910, 0x99999910,
+ 0xAAAAAA10, 0xAAAAAA10,
+ 0xBBBBBB10, 0xBBBBBB10,
+ 0x8888CC10, 0x8888CC10,
+ 0x9999DD10, 0x9999DD10,
+ 0xAAAAEE10, 0xAAAAEE10,
+ 0xBBBBFF10, 0xBBBBFF10,
+ 0xCC888810, 0xCC888810,
+ 0xDD999910, 0xDD999910,
+ 0xEEAAAA10, 0xEEAAAA10,
+ 0xFFBBBB10, 0xFFBBBB10,
+ 0xCC88CC10, 0xCC88CC10,
+ 0xDD99DD10, 0xDD99DD10,
+ 0xEEAAEE10, 0xEEAAEE10,
+ 0xFFBBFF10, 0xFFBBFF10,
+ 0x88CC0010, 0x88CC0010,
+ 0x99DD1110, 0x99DD1110,
+ 0xAAEE2210, 0xAAEE2210,
+ 0xBBFF3310, 0xBBFF3310,
+ 0x88CC4410, 0x88CC4410,
+ 0x99DD5510, 0x99DD5510,
+ 0xAAEE6610, 0xAAEE6610,
+ 0xBBFF7710, 0xBBFF7710,
+ 0xCCCC0010, 0xCCCC0010,
+ 0xDDDD1110, 0xDDDD1110,
+ 0xEEEE2210, 0xEEEE2210,
+ 0xFFFF3310, 0xFFFF3310,
+ 0xCCCC4410, 0xCCCC4410,
+ 0xDDDD5510, 0xDDDD5510,
+ 0xEEEE6610, 0xEEEE6610,
+ 0xFFFF7710, 0xFFFF7710,
+ 0x88CC8810, 0x88CC8810,
+ 0x99DD9910, 0x99DD9910,
+ 0xAAEEAA10, 0xAAEEAA10,
+ 0xBBFFBB10, 0xBBFFBB10,
+ 0x88CCCC10, 0x88CCCC10,
+ 0x99DDDD10, 0x99DDDD10,
+ 0xAAEEEE10, 0xAAEEEE10,
+ 0xBBFFFF10, 0xBBFFFF10,
+ 0xCCCC8810, 0xCCCC8810,
+ 0xDDDD9910, 0xDDDD9910,
+ 0xEEEEAA10, 0xEEEEAA10,
+ 0xFFFFBB10, 0xFFFFBB10,
+ 0xCCCCCC10, 0xCCCCCC10,
+ 0xDDDDDD10, 0xDDDDDD10,
+ 0xEEEEEE10, 0xEEEEEE10,
+ 0xFFFFFF10, 0xFFFFFF10
+};
diff --git a/frontends/riscos/palettes.h b/frontends/riscos/palettes.h
new file mode 100644
index 000000000..82fccb467
--- /dev/null
+++ b/frontends/riscos/palettes.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2006 Adrian Lees <adrianl@users.sourceforge.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Palette definitions for sprites
+ */
+
+#ifndef __NETSURF_RISCOS_PALETTES_H_
+#define __NETSURF_RISCOS_PALETTES_H_
+#include "oslib/os.h"
+
+extern const os_colour default_palette1[];
+extern const os_colour default_palette2[];
+extern const os_colour wimp_palette[];
+extern const os_colour default_palette8[];
+extern const os_colour captured_palette8[];
+
+#endif
diff --git a/frontends/riscos/plotters.c b/frontends/riscos/plotters.c
new file mode 100644
index 000000000..38fd9d74a
--- /dev/null
+++ b/frontends/riscos/plotters.c
@@ -0,0 +1,525 @@
+/*
+ * Copyright 2004 James Bursa <bursa@users.sourceforge.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Target independent plotting (RISC OS screen implementation).
+ */
+
+#include <stdbool.h>
+#include <math.h>
+#include "oslib/colourtrans.h"
+#include "oslib/draw.h"
+#include "oslib/os.h"
+
+#include "utils/log.h"
+#include "utils/utils.h"
+#include "desktop/plotters.h"
+
+#include "riscos/bitmap.h"
+#include "riscos/image.h"
+#include "riscos/gui.h"
+#include "riscos/font.h"
+#include "riscos/oslib_pre7.h"
+
+static bool ro_plot_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style);
+static bool ro_plot_line(int x0, int y0, int x1, int y1, const plot_style_t *style);
+static bool ro_plot_draw_path(const draw_path * const path, int width,
+ colour c, bool dotted, bool dashed);
+static bool ro_plot_polygon(const int *p, unsigned int n, const plot_style_t *style);
+static bool ro_plot_path(const float *p, unsigned int n, colour fill, float width,
+ colour c, const float transform[6]);
+static bool ro_plot_clip(const struct rect *clip);
+static bool ro_plot_text(int x, int y, const char *text, size_t length,
+ const plot_font_style_t *fstyle);
+static bool ro_plot_disc(int x, int y, int radius, const plot_style_t *style);
+static bool ro_plot_arc(int x, int y, int radius, int angle1, int angle2,
+ const plot_style_t *style);
+static bool ro_plot_bitmap(int x, int y, int width, int height,
+ struct bitmap *bitmap, colour bg,
+ bitmap_flags_t flags);
+
+
+struct plotter_table plot;
+
+const struct plotter_table ro_plotters = {
+ .rectangle = ro_plot_rectangle,
+ .line = ro_plot_line,
+ .polygon = ro_plot_polygon,
+ .clip = ro_plot_clip,
+ .text = ro_plot_text,
+ .disc = ro_plot_disc,
+ .arc = ro_plot_arc,
+ .bitmap = ro_plot_bitmap,
+ .path = ro_plot_path,
+ .option_knockout = true,
+};
+
+int ro_plot_origin_x = 0;
+int ro_plot_origin_y = 0;
+
+/** One version of the A9home OS is incapable of drawing patterned lines */
+bool ro_plot_patterned_lines = true;
+
+
+
+bool ro_plot_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style)
+{
+ if (style->fill_type != PLOT_OP_TYPE_NONE) {
+ os_error *error;
+ error = xcolourtrans_set_gcol(style->fill_colour << 8,
+ colourtrans_USE_ECFS_GCOL,
+ os_ACTION_OVERWRITE, 0, 0);
+ if (error) {
+ LOG("xcolourtrans_set_gcol: 0x%x: %s", error->errnum, error->errmess);
+ return false;
+ }
+
+ error = xos_plot(os_MOVE_TO,
+ ro_plot_origin_x + x0 * 2,
+ ro_plot_origin_y - y0 * 2 - 1);
+ if (error) {
+ LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
+ return false;
+ }
+
+ error = xos_plot(os_PLOT_RECTANGLE | os_PLOT_TO,
+ ro_plot_origin_x + x1 * 2 - 1,
+ ro_plot_origin_y - y1 * 2);
+ if (error) {
+ LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
+ return false;
+ }
+ }
+
+ if (style->stroke_type != PLOT_OP_TYPE_NONE) {
+ bool dotted = false;
+ bool dashed = false;
+
+ const int path[] = { draw_MOVE_TO,
+ (ro_plot_origin_x + x0 * 2) * 256,
+ (ro_plot_origin_y - y0 * 2 - 1) * 256,
+ draw_LINE_TO,
+ (ro_plot_origin_x + (x1) * 2) * 256,
+ (ro_plot_origin_y - y0 * 2 - 1) * 256,
+ draw_LINE_TO,
+ (ro_plot_origin_x + (x1) * 2) * 256,
+ (ro_plot_origin_y - (y1) * 2 - 1) * 256,
+ draw_LINE_TO,
+ (ro_plot_origin_x + x0 * 2) * 256,
+ (ro_plot_origin_y - (y1) * 2 - 1) * 256,
+ draw_CLOSE_LINE,
+ (ro_plot_origin_x + x0 * 2) * 256,
+ (ro_plot_origin_y - y0 * 2 - 1) * 256,
+ draw_END_PATH };
+
+ if (style->stroke_type == PLOT_OP_TYPE_DOT)
+ dotted = true;
+
+ if (style->stroke_type == PLOT_OP_TYPE_DASH)
+ dashed = true;
+
+ ro_plot_draw_path((const draw_path *)path,
+ style->stroke_width,
+ style->stroke_colour,
+ dotted, dashed);
+ }
+
+ return true;
+}
+
+
+bool ro_plot_line(int x0, int y0, int x1, int y1, const plot_style_t *style)
+{
+ if (style->stroke_type != PLOT_OP_TYPE_NONE) {
+ const int path[] = { draw_MOVE_TO,
+ (ro_plot_origin_x + x0 * 2) * 256,
+ (ro_plot_origin_y - y0 * 2 - 1) * 256,
+ draw_LINE_TO,
+ (ro_plot_origin_x + x1 * 2) * 256,
+ (ro_plot_origin_y - y1 * 2 - 1) * 256,
+ draw_END_PATH };
+ bool dotted = false;
+ bool dashed = false;
+
+ if (style->stroke_type == PLOT_OP_TYPE_DOT)
+ dotted = true;
+
+ if (style->stroke_type == PLOT_OP_TYPE_DASH)
+ dashed = true;
+
+ return ro_plot_draw_path((const draw_path *)path,
+ style->stroke_width,
+ style->stroke_colour,
+ dotted, dashed);
+ }
+ return true;
+}
+
+
+bool ro_plot_draw_path(const draw_path * const path, int width,
+ colour c, bool dotted, bool dashed)
+{
+ static const draw_line_style line_style = { draw_JOIN_MITRED,
+ draw_CAP_BUTT, draw_CAP_BUTT, 0, 0x7fffffff,
+ 0, 0, 0, 0 };
+ draw_dash_pattern dash = { 0, 1, { 512 } };
+ const draw_dash_pattern *dash_pattern = 0;
+ os_error *error;
+
+ if (width < 1)
+ width = 1;
+
+ if (ro_plot_patterned_lines) {
+ if (dotted) {
+ dash.elements[0] = 512 * width;
+ dash_pattern = &dash;
+ } else if (dashed) {
+ dash.elements[0] = 1536 * width;
+ dash_pattern = &dash;
+ }
+ }
+
+ error = xcolourtrans_set_gcol(c << 8, 0, os_ACTION_OVERWRITE, 0, 0);
+ if (error) {
+ LOG("xcolourtrans_set_gcol: 0x%x: %s", error->errnum, error->errmess);
+ return false;
+ }
+
+ error = xdraw_stroke(path, 0, 0, 0, width * 2 * 256,
+ &line_style, dash_pattern);
+ if (error) {
+ LOG("xdraw_stroke: 0x%x: %s", error->errnum, error->errmess);
+ return false;
+ }
+
+ return true;
+}
+
+
+bool ro_plot_polygon(const int *p, unsigned int n, const plot_style_t *style)
+{
+ int path[n * 3 + 2];
+ unsigned int i;
+ os_error *error;
+
+ for (i = 0; i != n; i++) {
+ path[i * 3 + 0] = draw_LINE_TO;
+ path[i * 3 + 1] = (ro_plot_origin_x + p[i * 2 + 0] * 2) * 256;
+ path[i * 3 + 2] = (ro_plot_origin_y - p[i * 2 + 1] * 2) * 256;
+ }
+ path[0] = draw_MOVE_TO;
+ path[n * 3] = draw_END_PATH;
+ path[n * 3 + 1] = 0;
+
+ error = xcolourtrans_set_gcol(style->fill_colour << 8, 0, os_ACTION_OVERWRITE, 0, 0);
+ if (error) {
+ LOG("xcolourtrans_set_gcol: 0x%x: %s", error->errnum, error->errmess);
+ return false;
+ }
+ error = xdraw_fill((draw_path *) path, 0, 0, 0);
+ if (error) {
+ LOG("xdraw_fill: 0x%x: %s", error->errnum, error->errmess);
+ return false;
+ }
+
+ return true;
+}
+
+
+bool ro_plot_path(const float *p, unsigned int n, colour fill, float width,
+ colour c, const float transform[6])
+{
+ static const draw_line_style line_style = { draw_JOIN_MITRED,
+ draw_CAP_BUTT, draw_CAP_BUTT, 0, 0x7fffffff,
+ 0, 0, 0, 0 };
+ int *path = 0;
+ unsigned int i;
+ os_trfm trfm;
+ os_error *error;
+
+ if (n == 0)
+ return true;
+
+ if (p[0] != PLOTTER_PATH_MOVE) {
+ LOG("path doesn't start with a move");
+ goto error;
+ }
+
+ path = malloc(sizeof *path * (n + 10));
+ if (!path) {
+ LOG("out of memory");
+ goto error;
+ }
+
+ for (i = 0; i < n; ) {
+ if (p[i] == PLOTTER_PATH_MOVE) {
+ path[i] = draw_MOVE_TO;
+ path[i + 1] = p[i + 1] * 2 * 256;
+ path[i + 2] = -p[i + 2] * 2 * 256;
+ i += 3;
+ } else if (p[i] == PLOTTER_PATH_CLOSE) {
+ path[i] = draw_CLOSE_LINE;
+ i++;
+ } else if (p[i] == PLOTTER_PATH_LINE) {
+ path[i] = draw_LINE_TO;
+ path[i + 1] = p[i + 1] * 2 * 256;
+ path[i + 2] = -p[i + 2] * 2 * 256;
+ i += 3;
+ } else if (p[i] == PLOTTER_PATH_BEZIER) {
+ path[i] = draw_BEZIER_TO;
+ path[i + 1] = p[i + 1] * 2 * 256;
+ path[i + 2] = -p[i + 2] * 2 * 256;
+ path[i + 3] = p[i + 3] * 2 * 256;
+ path[i + 4] = -p[i + 4] * 2 * 256;
+ path[i + 5] = p[i + 5] * 2 * 256;
+ path[i + 6] = -p[i + 6] * 2 * 256;
+ i += 7;
+ } else {
+ LOG("bad path command %f", p[i]);
+ goto error;
+ }
+ }
+ path[i] = draw_END_PATH;
+ path[i + 1] = 0;
+
+ trfm.entries[0][0] = transform[0] * 0x10000;
+ trfm.entries[0][1] = transform[1] * 0x10000;
+ trfm.entries[1][0] = transform[2] * 0x10000;
+ trfm.entries[1][1] = transform[3] * 0x10000;
+ trfm.entries[2][0] = (ro_plot_origin_x + transform[4] * 2) * 256;
+ trfm.entries[2][1] = (ro_plot_origin_y - transform[5] * 2) * 256;
+
+ if (fill != NS_TRANSPARENT) {
+ error = xcolourtrans_set_gcol(fill << 8, 0,
+ os_ACTION_OVERWRITE, 0, 0);
+ if (error) {
+ LOG("xcolourtrans_set_gcol: 0x%x: %s", error->errnum, error->errmess);
+ goto error;
+ }
+
+ error = xdraw_fill((draw_path *) path, 0, &trfm, 0);
+ if (error) {
+ LOG("xdraw_stroke: 0x%x: %s", error->errnum, error->errmess);
+ goto error;
+ }
+ }
+
+ if (c != NS_TRANSPARENT) {
+ error = xcolourtrans_set_gcol(c << 8, 0,
+ os_ACTION_OVERWRITE, 0, 0);
+ if (error) {
+ LOG("xcolourtrans_set_gcol: 0x%x: %s", error->errnum, error->errmess);
+ goto error;
+ }
+
+ error = xdraw_stroke((draw_path *) path, 0, &trfm, 0,
+ width * 2 * 256, &line_style, 0);
+ if (error) {
+ LOG("xdraw_stroke: 0x%x: %s", error->errnum, error->errmess);
+ goto error;
+ }
+ }
+
+ free(path);
+ return true;
+
+error:
+ free(path);
+ return false;
+}
+
+
+
+
+bool ro_plot_clip(const struct rect *clip)
+{
+ os_error *error;
+ char buf[12];
+
+ int clip_x0 = ro_plot_origin_x + clip->x0 * 2;
+ int clip_y0 = ro_plot_origin_y - clip->y0 * 2 - 1;
+ int clip_x1 = ro_plot_origin_x + clip->x1 * 2 - 1;
+ int clip_y1 = ro_plot_origin_y - clip->y1 * 2;
+
+ if (clip_x1 < clip_x0 || clip_y0 < clip_y1) {
+ LOG("bad clip rectangle %i %i %i %i", clip_x0, clip_y0, clip_x1, clip_y1);
+ return false;
+ }
+
+ buf[0] = os_VDU_SET_GRAPHICS_WINDOW;
+ buf[1] = clip_x0;
+ buf[2] = clip_x0 >> 8;
+ buf[3] = clip_y1;
+ buf[4] = clip_y1 >> 8;
+ buf[5] = clip_x1;
+ buf[6] = clip_x1 >> 8;
+ buf[7] = clip_y0;
+ buf[8] = clip_y0 >> 8;
+
+ error = xos_writen(buf, 9);
+ if (error) {
+ LOG("xos_writen: 0x%x: %s", error->errnum, error->errmess);
+ return false;
+ }
+
+ return true;
+}
+
+
+bool ro_plot_text(int x, int y, const char *text, size_t length,
+ const plot_font_style_t *fstyle)
+{
+ os_error *error;
+
+ error = xcolourtrans_set_font_colours(font_CURRENT,
+ fstyle->background << 8, fstyle->foreground << 8,
+ 14, 0, 0, 0);
+ if (error) {
+ LOG("xcolourtrans_set_font_colours: 0x%x: %s", error->errnum, error->errmess);
+ return false;
+ }
+
+ return nsfont_paint(fstyle, text, length,
+ ro_plot_origin_x + x * 2,
+ ro_plot_origin_y - y * 2);
+}
+
+
+bool ro_plot_disc(int x, int y, int radius, const plot_style_t *style)
+{
+ os_error *error;
+ if (style->fill_type != PLOT_OP_TYPE_NONE) {
+ error = xcolourtrans_set_gcol(style->fill_colour << 8, 0,
+ os_ACTION_OVERWRITE, 0, 0);
+ if (error) {
+ LOG("xcolourtrans_set_gcol: 0x%x: %s", error->errnum, error->errmess);
+ return false;
+ }
+ error = xos_plot(os_MOVE_TO,
+ ro_plot_origin_x + x * 2,
+ ro_plot_origin_y - y * 2);
+ if (error) {
+ LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
+ return false;
+ }
+ error = xos_plot(os_PLOT_CIRCLE | os_PLOT_BY, radius * 2, 0);
+ if (error) {
+ LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
+ return false;
+ }
+ }
+
+ if (style->stroke_type != PLOT_OP_TYPE_NONE) {
+
+ error = xcolourtrans_set_gcol(style->stroke_colour << 8, 0,
+ os_ACTION_OVERWRITE, 0, 0);
+ if (error) {
+ LOG("xcolourtrans_set_gcol: 0x%x: %s", error->errnum, error->errmess);
+ return false;
+ }
+ error = xos_plot(os_MOVE_TO,
+ ro_plot_origin_x + x * 2,
+ ro_plot_origin_y - y * 2);
+ if (error) {
+ LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
+ return false;
+ }
+ error = xos_plot(os_PLOT_CIRCLE_OUTLINE | os_PLOT_BY,
+ radius * 2, 0);
+
+ if (error) {
+ LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
+ return false;
+ }
+ }
+ return true;
+}
+
+bool ro_plot_arc(int x, int y, int radius, int angle1, int angle2, const plot_style_t *style)
+{
+ os_error *error;
+ int sx, sy, ex, ey;
+ double t;
+
+ x = ro_plot_origin_x + x * 2;
+ y = ro_plot_origin_y - y * 2;
+ radius <<= 1;
+
+ error = xcolourtrans_set_gcol(style->fill_colour << 8, 0,
+ os_ACTION_OVERWRITE, 0, 0);
+
+ if (error) {
+ LOG("xcolourtrans_set_gcol: 0x%x: %s", error->errnum, error->errmess);
+ return false;
+ }
+
+ t = ((double)angle1 * M_PI) / 180.0;
+ sx = (x + (int)(radius * cos(t)));
+ sy = (y + (int)(radius * sin(t)));
+
+ t = ((double)angle2 * M_PI) / 180.0;
+ ex = (x + (int)(radius * cos(t)));
+ ey = (y + (int)(radius * sin(t)));
+
+ error = xos_plot(os_MOVE_TO, x, y); /* move to centre */
+ if (error) {
+ LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
+ return false;
+ }
+
+ error = xos_plot(os_MOVE_TO, sx, sy); /* move to start */
+ if (error) {
+ LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
+ return false;
+ }
+
+ error = xos_plot(os_PLOT_ARC | os_PLOT_TO, ex, ey); /* arc to end */
+ if (error) {
+ LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
+ return false;
+ }
+
+ return true;
+}
+
+
+
+bool ro_plot_bitmap(int x, int y, int width, int height,
+ struct bitmap *bitmap, colour bg,
+ bitmap_flags_t flags)
+{
+ const uint8_t *buffer;
+
+ buffer = riscos_bitmap_get_buffer(bitmap);
+ if (!buffer) {
+ LOG("bitmap_get_buffer failed");
+ return false;
+ }
+
+ return image_redraw(bitmap->sprite_area,
+ ro_plot_origin_x + x * 2,
+ ro_plot_origin_y - y * 2,
+ width, height,
+ bitmap->width,
+ bitmap->height,
+ bg,
+ flags & BITMAPF_REPEAT_X, flags & BITMAPF_REPEAT_Y,
+ flags & BITMAPF_REPEAT_X || flags & BITMAPF_REPEAT_Y,
+ riscos_bitmap_get_opaque(bitmap) ? IMAGE_PLOT_TINCT_OPAQUE :
+ IMAGE_PLOT_TINCT_ALPHA);
+}
diff --git a/frontends/riscos/print.c b/frontends/riscos/print.c
new file mode 100644
index 000000000..95730d6be
--- /dev/null
+++ b/frontends/riscos/print.c
@@ -0,0 +1,976 @@
+/*
+ * Copyright 2004 John M Bell <jmb202@ecs.soton.ac.uk>
+ * Copyright 2006 James Bursa <bursa@users.sourceforge.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "utils/config.h"
+
+#include <assert.h>
+#include <string.h>
+#include <swis.h>
+#include <oslib/font.h>
+#include <oslib/hourglass.h>
+#include <oslib/osfile.h>
+#include <oslib/osfind.h>
+#include <oslib/pdriver.h>
+#include <oslib/wimp.h>
+#include <rufl.h>
+#include <limits.h>
+
+#include "utils/config.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/utils.h"
+#include "utils/nsoption.h"
+#include "content/content.h"
+#include "content/hlcache.h"
+#include "desktop/browser.h"
+#include "desktop/plotters.h"
+
+#include "riscos/gui.h"
+#include "riscos/dialog.h"
+#include "riscos/menus.h"
+#include "riscos/print.h"
+#include "riscos/wimp.h"
+#include "riscos/wimp_event.h"
+#include "riscos/filetype.h"
+#include "riscos/font.h"
+
+
+#define ICON_PRINT_TO_BOTTOM 1
+#define ICON_PRINT_SHEETS 2
+#define ICON_PRINT_SHEETS_VALUE 3
+#define ICON_PRINT_SHEETS_DOWN 4
+#define ICON_PRINT_SHEETS_UP 5
+#define ICON_PRINT_SHEETS_TEXT 6
+#define ICON_PRINT_FG_IMAGES 7
+#define ICON_PRINT_BG_IMAGES 8
+#define ICON_PRINT_IN_BACKGROUND 9
+#define ICON_PRINT_UPRIGHT 10
+#define ICON_PRINT_SIDEWAYS 11
+#define ICON_PRINT_COPIES 12
+#define ICON_PRINT_COPIES_DOWN 13
+#define ICON_PRINT_COPIES_UP 14
+#define ICON_PRINT_CANCEL 15
+#define ICON_PRINT_PRINT 16
+#define ICON_PRINT_TEXT_BLACK 20
+
+
+/** \todo landscape format pages
+ * \todo be somewhat more intelligent and try not to crop pages
+ * half way up a line of text
+ * \todo make use of print stylesheets
+ */
+
+struct gui_window *ro_print_current_window = NULL;
+bool print_text_black = false;
+bool print_active = false;
+
+/* 1 millipoint == 1/400 OS unit == 1/800 browser units */
+
+static int print_prev_message = 0;
+static bool print_in_background = false;
+static float print_scale = 1.0;
+static int print_num_copies = 1;
+static bool print_bg_images = false;
+static int print_max_sheets = -1;
+static bool print_sideways = false;
+/** List of fonts in current print. */
+static char **print_fonts_list = 0;
+/** Number of entries in print_fonts_list. */
+static unsigned int print_fonts_count;
+/** Error in print_fonts_plot_text() or print_fonts_callback(). */
+static const char *print_fonts_error;
+
+void gui_window_redraw_window(struct gui_window *g);
+
+static bool ro_gui_print_click(wimp_pointer *pointer);
+static bool ro_gui_print_apply(wimp_w w);
+static void print_update_sheets_shaded_state(bool on);
+static void print_send_printsave(hlcache_handle *h);
+static bool print_send_printtypeknown(wimp_message *m);
+static bool print_document(struct gui_window *g, const char *filename);
+static const char *print_declare_fonts(hlcache_handle *h);
+static bool print_fonts_plot_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style);
+static bool print_fonts_plot_line(int x0, int y0, int x1, int y1, const plot_style_t *style);
+static bool print_fonts_plot_polygon(const int *p, unsigned int n, const plot_style_t *style);
+static bool print_fonts_plot_clip(const struct rect *clip);
+static bool print_fonts_plot_text(int x, int y, const char *text, size_t length,
+ const plot_font_style_t *fstyle);
+static bool print_fonts_plot_disc(int x, int y, int radius, const plot_style_t *style);
+static bool print_fonts_plot_arc(int x, int y, int radius, int angle1, int angle2, const plot_style_t *style);
+static bool print_fonts_plot_bitmap(int x, int y, int width, int height,
+ struct bitmap *bitmap, colour bg,
+ bitmap_flags_t flags);
+static bool print_fonts_plot_path(const float *p, unsigned int n, colour fill, float width,
+ colour c, const float transform[6]);
+static void print_fonts_callback(void *context,
+ const char *font_name, unsigned int font_size,
+ const char *s8, unsigned short *s16, unsigned int n,
+ int x, int y);
+
+
+/** Plotter for print_declare_fonts(). All the functions do nothing except for
+ * print_fonts_plot_text, which records the fonts used. */
+static const struct plotter_table print_fonts_plotters = {
+ .rectangle = print_fonts_plot_rectangle,
+ .line = print_fonts_plot_line,
+ .polygon = print_fonts_plot_polygon,
+ .clip = print_fonts_plot_clip,
+ .text = print_fonts_plot_text,
+ .disc = print_fonts_plot_disc,
+ .arc = print_fonts_plot_arc,
+ .bitmap = print_fonts_plot_bitmap,
+ .path = print_fonts_plot_path,
+ .option_knockout = false,
+};
+
+
+/**
+ * Initialise the print dialog.
+ */
+
+void ro_gui_print_init(void)
+{
+ wimp_i radio_print_type[] = {ICON_PRINT_TO_BOTTOM, ICON_PRINT_SHEETS,
+ -1};
+ wimp_i radio_print_orientation[] = {ICON_PRINT_UPRIGHT,
+ ICON_PRINT_SIDEWAYS, -1};
+
+ dialog_print = ro_gui_dialog_create("print");
+ ro_gui_wimp_event_register_radio(dialog_print, radio_print_type);
+ ro_gui_wimp_event_register_radio(dialog_print, radio_print_orientation);
+ ro_gui_wimp_event_register_checkbox(dialog_print, ICON_PRINT_FG_IMAGES);
+ ro_gui_wimp_event_register_checkbox(dialog_print, ICON_PRINT_BG_IMAGES);
+ ro_gui_wimp_event_register_checkbox(dialog_print,
+ ICON_PRINT_IN_BACKGROUND);
+ ro_gui_wimp_event_register_checkbox(dialog_print,
+ ICON_PRINT_TEXT_BLACK);
+ ro_gui_wimp_event_register_text_field(dialog_print,
+ ICON_PRINT_SHEETS_TEXT);
+ ro_gui_wimp_event_register_numeric_field(dialog_print,
+ ICON_PRINT_COPIES, ICON_PRINT_COPIES_UP,
+ ICON_PRINT_COPIES_DOWN, 1, 99, 1, 0);
+ ro_gui_wimp_event_register_numeric_field(dialog_print,
+ ICON_PRINT_SHEETS_VALUE, ICON_PRINT_SHEETS_UP,
+ ICON_PRINT_SHEETS_DOWN, 1, 99, 1, 0);
+ ro_gui_wimp_event_register_cancel(dialog_print, ICON_PRINT_CANCEL);
+ ro_gui_wimp_event_register_mouse_click(dialog_print,
+ ro_gui_print_click);
+ ro_gui_wimp_event_register_ok(dialog_print, ICON_PRINT_PRINT,
+ ro_gui_print_apply);
+ ro_gui_wimp_event_set_help_prefix(dialog_print, "HelpPrint");
+}
+
+
+/**
+ * Prepares all aspects of the print dialog prior to opening.
+ *
+ * \param g parent window
+ */
+
+void ro_gui_print_prepare(struct gui_window *g)
+{
+ char *desc;
+ bool printers_exists = true;
+ os_error *error;
+
+ assert(g);
+
+ ro_print_current_window = g;
+ print_prev_message = 0;
+
+ /* Read Printer Driver name */
+ error = xpdriver_info(0, 0, 0, 0, &desc, 0, 0, 0);
+ if (error) {
+ LOG("xpdriver_info: 0x%x: %s", error->errnum, error->errmess);
+ printers_exists = false;
+ }
+
+ ro_gui_set_icon_selected_state(dialog_print, ICON_PRINT_TO_BOTTOM,
+ true);
+
+ ro_gui_set_icon_selected_state(dialog_print, ICON_PRINT_SHEETS, false);
+ ro_gui_set_icon_integer(dialog_print, ICON_PRINT_SHEETS_VALUE, 1);
+ print_update_sheets_shaded_state(true);
+
+ ro_gui_set_icon_selected_state(dialog_print, ICON_PRINT_FG_IMAGES,
+ true);
+ ro_gui_set_icon_shaded_state(dialog_print, ICON_PRINT_FG_IMAGES, true);
+
+ ro_gui_set_icon_selected_state(dialog_print, ICON_PRINT_BG_IMAGES,
+ print_bg_images);
+
+ ro_gui_set_icon_selected_state(dialog_print, ICON_PRINT_IN_BACKGROUND,
+ false);
+
+ ro_gui_set_icon_selected_state(dialog_print, ICON_PRINT_UPRIGHT, true);
+ ro_gui_set_icon_selected_state(dialog_print, ICON_PRINT_SIDEWAYS,
+ false);
+
+ ro_gui_set_icon_selected_state(dialog_print, ICON_PRINT_TEXT_BLACK,
+ false);
+
+ ro_gui_set_icon_integer(dialog_print, ICON_PRINT_COPIES, 1);
+
+ ro_gui_set_icon_shaded_state(dialog_print, ICON_PRINT_PRINT,
+ !printers_exists);
+ if (printers_exists)
+ ro_gui_set_window_title(dialog_print, desc);
+
+ ro_gui_wimp_event_memorise(dialog_print);
+}
+
+
+/**
+ * Handle mouse clicks in print dialog
+ *
+ * \param pointer wimp_pointer block
+ */
+
+bool ro_gui_print_click(wimp_pointer *pointer)
+{
+ if (pointer->buttons == wimp_CLICK_MENU)
+ return true;
+
+ switch (pointer->i) {
+ case ICON_PRINT_TO_BOTTOM:
+ case ICON_PRINT_SHEETS:
+ print_update_sheets_shaded_state(pointer->i !=
+ ICON_PRINT_SHEETS);
+ break;
+ }
+ return false;
+}
+
+
+/**
+ * Handle click on the Print button in the print dialog.
+ */
+
+bool ro_gui_print_apply(wimp_w w)
+{
+ int copies = atoi(ro_gui_get_icon_string(dialog_print,
+ ICON_PRINT_COPIES));
+ int sheets = atoi(ro_gui_get_icon_string(dialog_print,
+ ICON_PRINT_SHEETS_VALUE));
+
+ print_in_background = ro_gui_get_icon_selected_state(dialog_print,
+ ICON_PRINT_IN_BACKGROUND);
+ print_text_black = ro_gui_get_icon_selected_state(dialog_print,
+ ICON_PRINT_TEXT_BLACK);
+ print_sideways = ro_gui_get_icon_selected_state(dialog_print,
+ ICON_PRINT_SIDEWAYS);
+ print_num_copies = copies;
+ if (ro_gui_get_icon_selected_state(dialog_print, ICON_PRINT_SHEETS))
+ print_max_sheets = sheets;
+ else
+ print_max_sheets = -1;
+ print_bg_images = ro_gui_get_icon_selected_state(dialog_print,
+ ICON_PRINT_BG_IMAGES);
+
+ print_send_printsave(browser_window_get_content(
+ ro_print_current_window->bw));
+
+ return true;
+}
+
+
+/**
+ * Set shaded state of sheets
+ *
+ * \param on whether to turn shading on or off
+ */
+
+void print_update_sheets_shaded_state(bool on)
+{
+ ro_gui_set_icon_shaded_state(dialog_print, ICON_PRINT_SHEETS_VALUE, on);
+ ro_gui_set_icon_shaded_state(dialog_print, ICON_PRINT_SHEETS_DOWN, on);
+ ro_gui_set_icon_shaded_state(dialog_print, ICON_PRINT_SHEETS_UP, on);
+ ro_gui_set_icon_shaded_state(dialog_print, ICON_PRINT_SHEETS_TEXT, on);
+ ro_gui_set_caret_first(dialog_print);
+}
+
+
+/**
+ * Send a message_PRINT_SAVE
+ *
+ * \param h handle to content to print.
+ */
+
+void print_send_printsave(hlcache_handle *h)
+{
+ wimp_full_message_data_xfer m;
+ os_error *e;
+ int len;
+
+ len = strlen(content_get_title(h)) + 1;
+ if (212 < len)
+ len = 212;
+
+ m.size = ((44+len+3) & ~3);
+ m.your_ref = 0;
+ m.action = message_PRINT_SAVE;
+ m.w = (wimp_w)0;
+ m.i = m.pos.x = m.pos.y = 0;
+ m.est_size = 1024; /* arbitrary value - it really doesn't matter */
+ m.file_type = ro_content_filetype(h);
+ strncpy(m.file_name, content_get_title(h), 211);
+ m.file_name[211] = 0;
+ e = xwimp_send_message(wimp_USER_MESSAGE_RECORDED,
+ (wimp_message *)&m, 0);
+ if (e) {
+ LOG("xwimp_send_message: 0x%x: %s", e->errnum, e->errmess);
+ ro_warn_user("WimpError", e->errmess);
+ ro_print_cleanup();
+ }
+ print_prev_message = m.my_ref;
+}
+
+
+/**
+ * Send a message_PRINT_TYPE_KNOWN
+ *
+ * \param m message to reply to
+ * \return true on success, false otherwise
+ */
+
+bool print_send_printtypeknown(wimp_message *m)
+{
+ os_error *e;
+
+ m->size = 20;
+ m->your_ref = m->my_ref;
+ m->action = message_PRINT_TYPE_KNOWN;
+ e = xwimp_send_message(wimp_USER_MESSAGE, m, m->sender);
+ if (e) {
+ LOG("xwimp_send_message: 0x%x: %s", e->errnum, e->errmess);
+ ro_warn_user("WimpError", e->errmess);
+ return false;
+ }
+
+ return true;
+}
+
+
+/**
+ * Handle a bounced message_PRINT_SAVE
+ *
+ * \param m the bounced message
+ */
+
+void ro_print_save_bounce(wimp_message *m)
+{
+ if (m->my_ref == 0 || m->my_ref != print_prev_message)
+ return;
+
+ /* try to print anyway (we're graphics printing) */
+ if (ro_print_current_window) {
+ print_document(ro_print_current_window, "printer:");
+ }
+ ro_print_cleanup();
+}
+
+
+/**
+ * Handle message_PRINT_ERROR
+ *
+ * \param m the message containing the error
+ */
+
+void ro_print_error(wimp_message *m)
+{
+ pdriver_message_print_error *p = (pdriver_message_print_error*)&m->data;
+ if (m->your_ref == 0 || m->your_ref != print_prev_message)
+ return;
+
+ if (m->size == 20)
+ ro_warn_user("PrintErrorRO2", 0);
+ else
+ ro_warn_user("PrintError", p->errmess);
+
+ ro_print_cleanup();
+}
+
+
+/**
+ * Handle message_PRINT_TYPE_ODD
+ *
+ * \param m the message to handle
+ */
+
+void ro_print_type_odd(wimp_message *m)
+{
+ if ((m->your_ref == 0 || m->your_ref == print_prev_message) &&
+ !print_in_background) {
+ /* reply to a previous message (ie printsave) */
+ if (ro_print_current_window && print_send_printtypeknown(m)) {
+ print_document(ro_print_current_window, "printer:");
+ }
+ ro_print_cleanup();
+ }
+ else {
+ /* broadcast message */
+ /* no need to do anything */
+ }
+
+}
+
+
+/**
+ * Handle message_DATASAVE_ACK for the printing protocol.
+ *
+ * \param m the message to handle
+ * \return true if message successfully handled, false otherwise
+ *
+ * We cheat here and, instead of giving Printers what it asked for (a copy of
+ * the file so it can poke us later via a broadcast of PrintTypeOdd), we give
+ * it a file that it can print itself without having to bother us further. For
+ * PostScript printers (type 0) we give it a PostScript file. Otherwise, we give
+ * it a PrintOut file.
+ *
+ * This method has a couple of advantages:
+ * - we can reuse this code for background printing (we simply ignore the
+ * PrintTypeOdd reply)
+ * - there's no need to ensure all components of a page queued to be printed
+ * still exist when it reaches the top of the queue. (which reduces complexity
+ * a fair bit)
+ */
+
+bool ro_print_ack(wimp_message *m)
+{
+ pdriver_info_type info_type;
+ pdriver_type type;
+ os_error *error;
+
+ if (m->your_ref == 0 || m->your_ref != print_prev_message ||
+ !ro_print_current_window)
+ return false;
+
+ /* read printer driver type */
+ error = xpdriver_info(&info_type, 0, 0, 0, 0, 0, 0, 0);
+ if (error) {
+ LOG("xpdriver_info: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("PrintError", error->errmess);
+ ro_print_cleanup();
+ return true;
+ }
+ type = info_type >> 16;
+
+ /* print to file */
+ if (!print_document(ro_print_current_window,
+ m->data.data_xfer.file_name)) {
+ ro_print_cleanup();
+ return true;
+ }
+
+ /* send dataload */
+ m->your_ref = m->my_ref;
+ m->action = message_DATA_LOAD;
+
+ if (type == pdriver_TYPE_PS)
+ m->data.data_xfer.file_type = osfile_TYPE_POSTSCRIPT;
+ else
+ m->data.data_xfer.file_type = osfile_TYPE_PRINTOUT;
+
+ error = xwimp_send_message(wimp_USER_MESSAGE_RECORDED, m, m->sender);
+ if (error) {
+ LOG("xwimp_send_message: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ /* and delete temporary file */
+ xosfile_delete(m->data.data_xfer.file_name,
+ 0, 0, 0, 0, 0);
+ }
+ print_prev_message = m->my_ref;
+
+ ro_print_cleanup();
+ return true;
+}
+
+
+/**
+ * Handle a bounced dataload message
+ *
+ * \param m the message to handle
+ */
+
+void ro_print_dataload_bounce(wimp_message *m)
+{
+ if (m->your_ref == 0 || m->your_ref != print_prev_message)
+ return;
+
+ xosfile_delete(m->data.data_xfer.file_name, 0, 0, 0, 0, 0);
+ ro_print_cleanup();
+}
+
+
+/**
+ * Cleanup after printing
+ */
+
+void ro_print_cleanup(void)
+{
+ ro_print_current_window = NULL;
+ print_text_black = false;
+ print_prev_message = 0;
+ print_max_sheets = -1;
+ ro_gui_menu_destroy();
+ ro_gui_dialog_close(dialog_print);
+}
+
+
+/**
+ * Print a document.
+ *
+ * \param g gui_window containing the document to print
+ * \param filename name of file to print to
+ * \return true on success, false on error and error reported
+ */
+
+bool print_document(struct gui_window *g, const char *filename)
+{
+ int left, right, top, bottom, width, height;
+ int saved_width, saved_height;
+ int yscroll = 0, sheets = print_max_sheets;
+ hlcache_handle *h = browser_window_get_content(g->bw);
+ const char *error_message;
+ pdriver_features features;
+ os_fw fhandle, old_job = 0;
+ os_error *error;
+
+ /* no point printing a blank page */
+ if (!h) {
+ ro_warn_user("PrintError", "nothing to print");
+ return false;
+ }
+
+ /* read printer driver features */
+ error = xpdriver_info(0, 0, 0, &features, 0, 0, 0, 0);
+ if (error) {
+ LOG("xpdriver_info: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("PrintError", error->errmess);
+ return false;
+ }
+
+ /* read page size */
+ error = xpdriver_page_size(0, 0, &left, &bottom, &right, &top);
+ if (error) {
+ LOG("xpdriver_page_size: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("PrintError", error->errmess);
+ return false;
+ }
+
+ if (print_sideways) {
+ width = (top - bottom) / 800;
+ height = (right - left) / 800;
+ } else {
+ width = (right - left) / 800;
+ height = (top - bottom) / 800;
+ }
+
+ /* layout the document to the correct width */
+ saved_width = content_get_width(h);
+ saved_height = content_get_height(h);
+ if (content_get_type(h) == CONTENT_HTML)
+ content_reformat(h, false, width, height);
+
+ /* open printer file */
+ error = xosfind_openoutw(osfind_NO_PATH | osfind_ERROR_IF_DIR |
+ osfind_ERROR_IF_ABSENT, filename, 0, &fhandle);
+ if (error) {
+ LOG("xosfind_openoutw: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("PrintError", error->errmess);
+ return false;
+ }
+
+ /* select print job */
+ error = xpdriver_select_jobw(fhandle, "NetSurf", &old_job);
+ if (error) {
+ LOG("xpdriver_select_jobw: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("PrintError", error->errmess);
+ xosfind_closew(fhandle);
+ return false;
+ }
+
+ rufl_invalidate_cache();
+
+ /* declare fonts, if necessary */
+ if (features & pdriver_FEATURE_DECLARE_FONT) {
+ if ((error_message = print_declare_fonts(h)))
+ goto error;
+ }
+
+ ro_gui_current_redraw_gui = g;
+
+ /* print is now active */
+ print_active = true;
+
+ do {
+ struct rect clip;
+ os_box b;
+ os_hom_trfm t;
+ os_coord p;
+ osbool more;
+
+ if (print_sideways) {
+ b.x0 = bottom / 400 -2;
+ b.y0 = left / 400 - 2;
+ b.x1 = top / 400 + 2;
+ b.y1 = right / 400 + 2;
+ t.entries[0][0] = 0;
+ t.entries[0][1] = 65536;
+ t.entries[1][0] = -65536;
+ t.entries[1][1] = 0;
+ p.x = right;
+ p.y = bottom;
+ ro_plot_origin_x = bottom / 400;
+ ro_plot_origin_y = right / 400 + yscroll * 2;
+ } else {
+ b.x0 = left / 400 -2;
+ b.y0 = bottom / 400 - 2;
+ b.x1 = right / 400 + 2;
+ b.y1 = top / 400 + 2;
+ t.entries[0][0] = 65536;
+ t.entries[0][1] = 0;
+ t.entries[1][0] = 0;
+ t.entries[1][1] = 65536;
+ p.x = left;
+ p.y = bottom;
+ ro_plot_origin_x = left / 400;
+ ro_plot_origin_y = top / 400 + yscroll * 2;
+ }
+
+ xhourglass_percentage((int) (yscroll * 100 /
+ content_get_height(h)));
+
+ /* give page rectangle */
+ error = xpdriver_give_rectangle(0, &b, &t, &p, os_COLOUR_WHITE);
+ if (error) {
+ LOG("xpdriver_give_rectangle: 0x%x: %s", error->errnum, error->errmess);
+ error_message = error->errmess;
+ goto error;
+ }
+
+ LOG("given rectangle: [(%d, %d), (%d, %d)]", b.x0, b.y0, b.x1, b.y1);
+
+ /* and redraw the document */
+ error = xpdriver_draw_page(print_num_copies, &b, 0, 0,
+ &more, 0);
+ if (error) {
+ LOG("xpdriver_draw_page: 0x%x: %s", error->errnum, error->errmess);
+ error_message = error->errmess;
+ goto error;
+ }
+
+ while (more) {
+ struct content_redraw_data data;
+ /* TODO: turn knockout off for print */
+ struct redraw_context ctx = {
+ .interactive = false,
+ .background_images = print_bg_images,
+ .plot = &ro_plotters
+ };
+
+ LOG("redrawing area: [(%d, %d), (%d, %d)]", b.x0, b.y0, b.x1, b.y1);
+ clip.x0 = (b.x0 - ro_plot_origin_x) / 2;
+ clip.y0 = (ro_plot_origin_y - b.y1) / 2;
+ clip.x1 = (b.x1 - ro_plot_origin_x) / 2;
+ clip.y1 = (ro_plot_origin_y - b.y0) / 2;
+
+ data.x = 0;
+ data.y = 0;
+ data.width = content_get_width(h);
+ data.height = content_get_height(h);
+ data.background_colour = 0xFFFFFF;
+ data.scale = print_scale;
+ data.repeat_x = false;
+ data.repeat_y = false;
+
+ if (!content_redraw(h, &data, &clip, &ctx)) {
+ error_message = "redraw error";
+ goto error;
+ }
+
+ error = xpdriver_get_rectangle(&b, &more, 0);
+ if (error) {
+ LOG("xpdriver_get_rectangle: 0x%x: %s", error->errnum, error->errmess);
+ error_message = error->errmess;
+ goto error;
+ }
+ }
+
+ yscroll += height;
+ } while (yscroll <= content_get_height(h) && --sheets != 0);
+
+ /* make print inactive */
+ print_active = false;
+ ro_gui_current_redraw_gui = 0;
+
+ /* clean up
+ *
+ * Call PDriver_EndJob via _swix() so that r9 is preserved. This
+ * prevents a crash if the SWI corrupts it on exit (as seems to
+ * happen on some versions of RISC OS 6).
+ */
+
+ error = (os_error *) _swix(PDriver_EndJob, _IN(0), (int) fhandle);
+ if (error) {
+ LOG("xpdriver_end_jobw: 0x%x: %s", error->errnum, error->errmess);
+ error_message = error->errmess;
+ goto error;
+ }
+
+ error = xosfind_closew(fhandle);
+ if (error) {
+ LOG("xosfind_closew: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("PrintError", error->errmess);
+ return false;
+ }
+
+ if (old_job) {
+ error = xpdriver_select_jobw(old_job, 0, 0);
+ if (error) {
+ LOG("xpdriver_select_jobw: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("PrintError", error->errmess);
+ /* the printing succeeded anyway */
+ return true;
+ }
+ }
+
+ rufl_invalidate_cache();
+
+ /* restore document layout and redraw browser window */
+ if (content_get_type(h) == CONTENT_HTML)
+ content_reformat(h, false, saved_width, saved_height);
+
+ gui_window_redraw_window(g);
+
+ return true;
+
+error:
+ xpdriver_abort_job(fhandle);
+ xosfind_closew(fhandle);
+ if (old_job)
+ xpdriver_select_jobw(old_job, 0, 0);
+ print_active = false;
+ ro_gui_current_redraw_gui = 0;
+
+ ro_warn_user("PrintError", error_message);
+
+ rufl_invalidate_cache();
+
+ /* restore document layout */
+ if (content_get_type(h) == CONTENT_HTML)
+ content_reformat(h, false, saved_width, saved_height);
+
+ return false;
+}
+
+
+/**
+ * Declare fonts to the printer driver.
+ *
+ * \param h handle to content being printed
+ * \return 0 on success, error message on error
+ */
+
+const char *print_declare_fonts(hlcache_handle *h)
+{
+ unsigned int i;
+ struct rect clip;
+ struct content_redraw_data data;
+ const char *error_message = 0;
+ os_error *error;
+ struct redraw_context ctx = {
+ .interactive = false,
+ .background_images = false,
+ .plot = &print_fonts_plotters
+ };
+
+ free(print_fonts_list);
+ print_fonts_list = 0;
+ print_fonts_count = 0;
+ print_fonts_error = 0;
+
+ clip.x0 = clip.y0 = INT_MIN;
+ clip.x1 = clip.y1 = INT_MAX;
+
+ data.x = 0;
+ data.y = 0;
+ data.width = content_get_width(h);
+ data.height = content_get_height(h);
+ data.background_colour = 0xFFFFFF;
+ data.scale = 1;
+ data.repeat_x = false;
+ data.repeat_y = false;
+
+ if (!content_redraw(h, &data, &clip, &ctx)) {
+ if (print_fonts_error)
+ return print_fonts_error;
+ return "Declaring fonts failed.";
+ }
+
+ for (i = 0; i != print_fonts_count; ++i) {
+ LOG("%u %s", i, print_fonts_list[i]);
+ error = xpdriver_declare_font(0, print_fonts_list[i],
+ pdriver_KERNED);
+ if (error) {
+ LOG("xpdriver_declare_font: 0x%x: %s", error->errnum, error->errmess);
+ error_message = error->errmess;
+ goto end;
+ }
+ }
+ error = xpdriver_declare_font(0, 0, 0);
+ if (error) {
+ LOG("xpdriver_declare_font: 0x%x: %s", error->errnum, error->errmess);
+ error_message = error->errmess;
+ goto end;
+ }
+
+end:
+ for (i = 0; i != print_fonts_count; i++)
+ free(print_fonts_list[i]);
+ free(print_fonts_list);
+ print_fonts_list = 0;
+
+ return error_message;
+}
+
+
+bool print_fonts_plot_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style)
+{
+ return true;
+}
+
+
+bool print_fonts_plot_line(int x0, int y0, int x1, int y1, const plot_style_t *style)
+{
+ return true;
+}
+
+bool print_fonts_plot_polygon(const int *p, unsigned int n, const plot_style_t *style)
+{
+ return true;
+}
+
+
+bool print_fonts_plot_clip(const struct rect *clip)
+{
+ return true;
+}
+
+bool print_fonts_plot_disc(int x, int y, int radius, const plot_style_t *style)
+{
+ return true;
+}
+
+bool print_fonts_plot_arc(int x, int y, int radius, int angle1, int angle2,
+ const plot_style_t *style)
+{
+ return true;
+}
+
+bool print_fonts_plot_bitmap(int x, int y, int width, int height,
+ struct bitmap *bitmap, colour bg, bitmap_flags_t flags)
+{
+ return true;
+}
+
+bool print_fonts_plot_path(const float *p, unsigned int n, colour fill, float width,
+ colour c, const float transform[6])
+{
+ return true;
+}
+
+
+/**
+ * Plotter for text plotting during font listing.
+ */
+
+bool print_fonts_plot_text(int x, int y, const char *text, size_t length,
+ const plot_font_style_t *fstyle)
+{
+ const char *font_family;
+ unsigned int font_size;
+ rufl_style font_style;
+ rufl_code code;
+
+ nsfont_read_style(fstyle, &font_family, &font_size, &font_style);
+
+ code = rufl_paint_callback(font_family, font_style, font_size,
+ text, length, 0, 0, print_fonts_callback, 0);
+ if (code != rufl_OK) {
+ if (code == rufl_FONT_MANAGER_ERROR) {
+ LOG("rufl_paint_callback: rufl_FONT_MANAGER_ERROR: ""0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess);
+ print_fonts_error = rufl_fm_error->errmess;
+ } else {
+ LOG("rufl_paint_callback: 0x%x", code);
+ }
+ return false;
+ }
+ if (print_fonts_error)
+ return false;
+
+ return true;
+}
+
+
+/**
+ * Callback for print_fonts_plot_text().
+ *
+ * The font name is added to print_fonts_list.
+ */
+
+void print_fonts_callback(void *context,
+ const char *font_name, unsigned int font_size,
+ const char *s8, unsigned short *s16, unsigned int n,
+ int x, int y)
+{
+ unsigned int i;
+ char **fonts_list;
+
+ (void) context; /* unused */
+ (void) font_size; /* unused */
+ (void) x; /* unused */
+ (void) y; /* unused */
+
+ assert(s8 || s16);
+
+ /* check if the font name is new */
+ for (i = 0; i != print_fonts_count &&
+ strcmp(print_fonts_list[i], font_name) != 0; i++)
+ ;
+ if (i != print_fonts_count)
+ return;
+
+ /* add to list of fonts */
+ fonts_list = realloc(print_fonts_list,
+ sizeof print_fonts_list[0] *
+ (print_fonts_count + 1));
+ if (!fonts_list) {
+ print_fonts_error = messages_get("NoMemory");
+ return;
+ }
+ fonts_list[print_fonts_count] = strdup(font_name);
+ if (!fonts_list[print_fonts_count]) {
+ print_fonts_error = messages_get("NoMemory");
+ return;
+ }
+ print_fonts_list = fonts_list;
+ print_fonts_count++;
+}
+
diff --git a/frontends/riscos/print.h b/frontends/riscos/print.h
new file mode 100644
index 000000000..d997dce99
--- /dev/null
+++ b/frontends/riscos/print.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2004 John M Bell <jmb202@ecs.soton.ac.uk>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _NETSURF_RISCOS_PRINT_H_
+#define _NETSURF_RISCOS_PRINT_H_
+
+struct gui_window;
+
+extern struct gui_window *ro_print_current_window;
+
+void ro_print_save_bounce(wimp_message *m);
+void ro_print_error(wimp_message *m);
+void ro_print_type_odd(wimp_message *m);
+bool ro_print_ack(wimp_message *m);
+void ro_print_dataload_bounce(wimp_message *m);
+void ro_print_cleanup(void);
+
+#endif
diff --git a/frontends/riscos/query.c b/frontends/riscos/query.c
new file mode 100644
index 000000000..1d7cf5120
--- /dev/null
+++ b/frontends/riscos/query.c
@@ -0,0 +1,381 @@
+/*
+ * Copyright 2005 Adrian Lees <adrianl@users.sourceforge.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/utf8.h"
+#include "utils/utils.h"
+
+#include "riscos/gui.h"
+#include "riscos/query.h"
+#include "riscos/wimp.h"
+#include "riscos/wimp_event.h"
+#include "riscos/ucstables.h"
+#include "riscos/dialog.h"
+
+#define ICON_QUERY_MESSAGE 0
+#define ICON_QUERY_YES 1
+#define ICON_QUERY_NO 2
+#define ICON_QUERY_HELP 3
+
+/** Data for a query window */
+struct gui_query_window
+{
+ struct gui_query_window *prev; /** Previous query in list */
+ struct gui_query_window *next; /** Next query in list */
+
+ query_id id; /** unique ID number for this query */
+ wimp_w window; /** RISC OS window handle */
+
+ const query_callback *cb; /** Table of callback functions */
+ void *pw; /** Handle passed to callback functions */
+
+ bool default_confirm; /** Default action is to confirm */
+};
+
+
+/** Next unallocated query id */
+static query_id next_id = (query_id)1;
+
+/** List of all query windows. */
+static struct gui_query_window *gui_query_window_list = 0;
+
+/** Template for a query window. */
+static struct wimp_window *query_template;
+
+/** Widths of Yes and No buttons */
+static int query_yes_width = 0;
+static int query_no_width = 0;
+
+static struct gui_query_window *ro_gui_query_window_lookup_id(query_id id);
+
+static bool ro_gui_query_click(wimp_pointer *pointer);
+static void ro_gui_query_close(wimp_w w);
+static bool ro_gui_query_apply(wimp_w w);
+
+
+void ro_gui_query_init(void)
+{
+ query_template = ro_gui_dialog_load_template("query");
+}
+
+
+/**
+ * Lookup a query window using its ID number
+ *
+ * \param id id to search for
+ * \return pointer to query window or NULL
+ */
+
+struct gui_query_window *ro_gui_query_window_lookup_id(query_id id)
+{
+ struct gui_query_window *qw = gui_query_window_list;
+ while (qw && qw->id != id)
+ qw = qw->next;
+ return qw;
+}
+
+
+/**
+ * Display a query to the user, requesting a response, near the current
+ * pointer position to keep the required mouse travel small, but also
+ * protecting against spurious mouse clicks.
+ *
+ * \param query message token of query
+ * \param detail parameter used in expanding tokenised message
+ * \param cb table of callback functions to be called when user responds
+ * \param pw handle to be passed to callback functions
+ * \param yes text to use for 'Yes' button' (or NULL for default)
+ * \param no text to use for 'No' button (or NULL for default)
+ * \return id number of the query (or QUERY_INVALID if it failed)
+ */
+
+query_id query_user(const char *query, const char *detail,
+ const query_callback *cb, void *pw,
+ const char *yes, const char *no)
+{
+ wimp_pointer pointer;
+ if (xwimp_get_pointer_info(&pointer))
+ pointer.pos.y = pointer.pos.x = -1;
+
+ return query_user_xy(query, detail, cb, pw, yes, no,
+ pointer.pos.x, pointer.pos.y);
+}
+
+
+/**
+ * Display a query to the user, requesting a response, at a specified
+ * screen position (x,y). The window is positioned relative to the given
+ * location such that the required mouse travel is small, but non-zero
+ * for protection spurious double-clicks.
+ *
+ * \param query message token of query
+ * \param detail parameter used in expanding tokenised message
+ * \param cb table of callback functions to be called when user responds
+ * \param pw handle to be passed to callback functions
+ * \param yes text to use for 'Yes' button' (or NULL for default)
+ * \param no text to use for 'No' button (or NULL for default)
+ * \param x x position in screen coordinates (-1 = centred on screen)
+ * \param y y position in screen coordinates (-1 = centred on screen)
+ * \return id number of the query (or QUERY_INVALID if it failed)
+ */
+
+query_id query_user_xy(const char *query, const char *detail,
+ const query_callback *cb, void *pw,
+ const char *yes, const char *no,
+ int x, int y)
+{
+ struct gui_query_window *qw;
+ char query_buffer[300];
+ os_error *error;
+ wimp_icon *icn;
+ int width;
+ int len;
+ int tx;
+ char *local_text = NULL;
+ nserror err;
+
+ qw = malloc(sizeof(struct gui_query_window));
+ if (!qw) {
+ ro_warn_user("NoMemory", NULL);
+ return QUERY_INVALID;
+ }
+
+ qw->cb = cb;
+ qw->pw = pw;
+ qw->id = next_id++;
+ qw->default_confirm = false;
+
+ if (next_id == QUERY_INVALID)
+ next_id++;
+
+ if (!yes) yes = messages_get("Yes");
+ if (!no) no = messages_get("No");
+
+ /* set the text of the 'Yes' button and size accordingly */
+ err = utf8_to_local_encoding(yes, 0, &local_text);
+ if (err != NSERROR_OK) {
+ assert(err != NSERROR_BAD_ENCODING);
+ LOG("utf8_to_local_encoding_failed");
+ local_text = NULL;
+ }
+
+ icn = &query_template->icons[ICON_QUERY_YES];
+ len = strlen(local_text ? local_text : yes);
+ len = max(len, icn->data.indirected_text.size - 1);
+ memcpy(icn->data.indirected_text.text,
+ local_text ? local_text: yes, len);
+ icn->data.indirected_text.text[len] = '\0';
+
+ free(local_text);
+ local_text = NULL;
+
+ error = xwimptextop_string_width(icn->data.indirected_text.text, len, &width);
+ if (error) {
+ LOG("xwimptextop_string_width: 0x%x:%s", error->errnum, error->errmess);
+ width = len * 16;
+ }
+ if (!query_yes_width) query_yes_width = icn->extent.x1 - icn->extent.x0;
+ width += 44;
+ if (width < query_yes_width)
+ width = query_yes_width;
+ icn->extent.x0 = tx = icn->extent.x1 - width;
+
+ /* set the text of the 'No' button and size accordingly */
+ err = utf8_to_local_encoding(no, 0, &local_text);
+ if (err != NSERROR_OK) {
+ assert(err != NSERROR_BAD_ENCODING);
+ LOG("utf8_to_local_encoding_failed");
+ local_text = NULL;
+ }
+
+ icn = &query_template->icons[ICON_QUERY_NO];
+ len = strlen(local_text ? local_text : no);
+ len = max(len, icn->data.indirected_text.size - 1);
+ memcpy(icn->data.indirected_text.text,
+ local_text ? local_text : no, len);
+ icn->data.indirected_text.text[len] = '\0';
+
+ free(local_text);
+ local_text = NULL;
+
+ if (!query_no_width) query_no_width = icn->extent.x1 - icn->extent.x0;
+ icn->extent.x1 = tx - 16;
+ error = xwimptextop_string_width(icn->data.indirected_text.text, len, &width);
+ if (error) {
+ LOG("xwimptextop_string_width: 0x%x:%s", error->errnum, error->errmess);
+ width = len * 16;
+ }
+ width += 28;
+ if (width < query_no_width)
+ width = query_no_width;
+ icn->extent.x0 = icn->extent.x1 - width;
+
+ error = xwimp_create_window(query_template, &qw->window);
+ if (error) {
+ ro_warn_user("WimpError", error->errmess);
+ free(qw);
+ return QUERY_INVALID;
+ }
+
+ snprintf(query_buffer, sizeof query_buffer, "%s %s",
+ messages_get(query), detail ? detail : "");
+ query_buffer[sizeof query_buffer - 1] = 0;
+
+ ro_gui_set_icon_string(qw->window, ICON_QUERY_MESSAGE,
+ query_buffer, true);
+
+ xwimp_set_icon_state(qw->window, ICON_QUERY_HELP,
+ wimp_ICON_DELETED, wimp_ICON_DELETED);
+
+ if (x >= 0 && y >= 0) {
+ x -= tx - 8;
+ y += (query_template->visible.y1 - query_template->visible.y0) / 2;
+ ro_gui_dialog_open_xy(qw->window, x, y);
+ }
+ else
+ ro_gui_dialog_open(qw->window);
+
+ ro_gui_wimp_event_set_user_data(qw->window, qw);
+ ro_gui_wimp_event_register_mouse_click(qw->window, ro_gui_query_click);
+ ro_gui_wimp_event_register_cancel(qw->window, ICON_QUERY_NO);
+ ro_gui_wimp_event_register_ok(qw->window, ICON_QUERY_YES, ro_gui_query_apply);
+ ro_gui_wimp_event_register_close_window(qw->window, ro_gui_query_close);
+
+ error = xwimp_set_caret_position(qw->window, (wimp_i)-1, 0, 0, 1 << 25, -1);
+ if (error) {
+ LOG("xwimp_get_caret_position: 0x%x : %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+
+ /* put this query window at the head of our list */
+ if (gui_query_window_list)
+ gui_query_window_list->prev = qw;
+
+ qw->prev = NULL;
+ qw->next = gui_query_window_list;
+ gui_query_window_list = qw;
+
+ return qw->id;
+}
+
+
+/**
+ * Close a query window without waiting for a response from the user.
+ * (should normally only be called if the user has responded in some other
+ * way of which the query window in unaware.)
+ *
+ * \param id id of query window to close
+ */
+
+void query_close(query_id id)
+{
+ struct gui_query_window *qw = ro_gui_query_window_lookup_id(id);
+ if (!qw)
+ return;
+ ro_gui_query_close(qw->window);
+
+}
+
+
+void ro_gui_query_window_bring_to_front(query_id id)
+{
+ struct gui_query_window *qw = ro_gui_query_window_lookup_id(id);
+ if (qw) {
+ os_error *error;
+
+ ro_gui_dialog_open(qw->window);
+
+ error = xwimp_set_caret_position(qw->window, (wimp_i)-1, 0, 0, 1 << 25, -1);
+ if (error) {
+ LOG("xwimp_get_caret_position: 0x%x : %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+ }
+}
+
+
+/**
+ * Handle closing of query dialog
+ */
+void ro_gui_query_close(wimp_w w)
+{
+ struct gui_query_window *qw;
+ os_error *error;
+
+ qw = (struct gui_query_window *)ro_gui_wimp_event_get_user_data(w);
+
+ ro_gui_dialog_close(w);
+ error = xwimp_delete_window(qw->window);
+ if (error) {
+ LOG("xwimp_delete_window: 0x%x:%s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+ ro_gui_wimp_event_finalise(w);
+
+ /* remove from linked-list of query windows and release memory */
+ if (qw->prev)
+ qw->prev->next = qw->next;
+ else
+ gui_query_window_list = qw->next;
+
+ if (qw->next)
+ qw->next->prev = qw->prev;
+ free(qw);
+}
+
+
+/**
+ * Handle acceptance of query dialog
+ */
+bool ro_gui_query_apply(wimp_w w)
+{
+ struct gui_query_window *qw;
+ const query_callback *cb;
+
+ qw = (struct gui_query_window *)ro_gui_wimp_event_get_user_data(w);
+ cb = qw->cb;
+ cb->confirm(qw->id, QUERY_YES, qw->pw);
+ return true;
+}
+
+
+/**
+ * Handle clicks in query dialog
+ */
+bool ro_gui_query_click(wimp_pointer *pointer)
+{
+ struct gui_query_window *qw;
+ const query_callback *cb;
+
+ qw = (struct gui_query_window *)ro_gui_wimp_event_get_user_data(pointer->w);
+ cb = qw->cb;
+
+ switch (pointer->i) {
+ case ICON_QUERY_NO:
+ cb->cancel(qw->id, QUERY_NO, qw->pw);
+ break;
+ default:
+ return false;
+ }
+ return false;
+}
diff --git a/frontends/riscos/query.h b/frontends/riscos/query.h
new file mode 100644
index 000000000..c60a8bbbb
--- /dev/null
+++ b/frontends/riscos/query.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2005 Adrian Lees <adrianl@users.sourceforge.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _NETSURF_RISCOS_QUERY_H
+#define _NETSURF_RISCOS_QUERY_H
+
+#include <stdbool.h>
+#include "oslib/wimp.h"
+
+enum query_response {
+ QUERY_CONTINUE,
+ QUERY_YES,
+ QUERY_NO,
+ QUERY_ESCAPE
+};
+
+typedef int query_id;
+
+#define QUERY_INVALID ((query_id)-1)
+
+typedef struct
+{
+ void (*confirm)(query_id id, enum query_response res, void *pw);
+ void (*cancel)(query_id, enum query_response res, void *pw);
+} query_callback;
+
+
+query_id query_user_xy(const char *query, const char *detail,
+ const query_callback *cb, void *pw, const char *yes, const char *no,
+ int x, int y);
+void ro_gui_query_init(void);
+void ro_gui_query_window_bring_to_front(query_id id);
+
+query_id query_user(const char *query, const char *detail,
+ const query_callback *cb, void *pw, const char *yes, const char *no);
+void query_close(query_id);
+
+#endif
diff --git a/frontends/riscos/save.c b/frontends/riscos/save.c
new file mode 100644
index 000000000..27330700c
--- /dev/null
+++ b/frontends/riscos/save.c
@@ -0,0 +1,1401 @@
+/*
+ * Copyright 2004-2007 James Bursa <bursa@users.sourceforge.net>
+ * Copyright 2005 Adrian Lees <adrianl@users.sourceforge.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Save dialog and drag and drop saving (implementation).
+ */
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "oslib/dragasprite.h"
+#include "oslib/osbyte.h"
+#include "oslib/osfile.h"
+#include "oslib/osmodule.h"
+#include "oslib/osspriteop.h"
+#include "oslib/wimp.h"
+#include "oslib/wimpspriteop.h"
+
+#include "utils/config.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/utf8.h"
+#include "content/content.h"
+#include "content/hlcache.h"
+#include "desktop/browser.h"
+#include "desktop/hotlist.h"
+#include "desktop/global_history.h"
+#include "desktop/version.h"
+#include "desktop/save_complete.h"
+#include "desktop/save_text.h"
+#include "desktop/gui_window.h"
+#include "image/bitmap.h"
+#include "render/form.h"
+
+#include "riscos/bitmap.h"
+#include "riscos/dialog.h"
+#include "riscos/gui.h"
+#include "riscos/menus.h"
+#include "riscos/message.h"
+#include "riscos/mouse.h"
+#include "utils/nsoption.h"
+#include "riscos/query.h"
+#include "riscos/save.h"
+#include "riscos/save_draw.h"
+#include "riscos/save_pdf.h"
+#include "riscos/textselection.h"
+#include "riscos/wimp.h"
+#include "riscos/wimp_event.h"
+#include "riscos/ucstables.h"
+#include "riscos/filetype.h"
+
+//typedef enum
+//{
+// QueryRsn_Quit,
+// QueryRsn_Abort,
+// QueryRsn_Overwrite
+//} query_reason;
+
+
+/**todo - much of the state information for a save should probably be moved into a structure
+ now since we could have multiple saves outstanding */
+
+static gui_save_type gui_save_current_type;
+static hlcache_handle *gui_save_content = NULL;
+static char *gui_save_selection = NULL;
+static const char *gui_save_url = NULL;
+static const char *gui_save_title = NULL;
+static int gui_save_filetype;
+static query_id gui_save_query;
+static bool gui_save_send_dataload;
+static wimp_message gui_save_message;
+static bool gui_save_close_after = true;
+
+static bool dragbox_active = false; /** in-progress Wimp_DragBox/DragASprite op */
+static bool using_dragasprite = true;
+static bool saving_from_dialog = true;
+static osspriteop_area *saveas_area = NULL;
+static wimp_w gui_save_sourcew = (wimp_w)-1;
+#define LEAFNAME_MAX 200
+static char save_leafname[LEAFNAME_MAX];
+
+/** Current save directory (updated by and used for dialog-based saving) */
+static char *save_dir = NULL;
+static size_t save_dir_len;
+
+typedef enum { LINK_ACORN, LINK_ANT, LINK_TEXT } link_format;
+
+static bool ro_gui_save_complete(hlcache_handle *h, char *path);
+static bool ro_gui_save_content(hlcache_handle *h, char *path, bool force_overwrite);
+static void ro_gui_save_done(void);
+static void ro_gui_save_bounced(wimp_message *message);
+static bool ro_gui_save_object_native(hlcache_handle *h, char *path);
+static bool ro_gui_save_link(const char *url, const char *title, link_format format, char *path);
+static void ro_gui_save_set_state(hlcache_handle *h, gui_save_type save_type,
+ const nsurl *url, char *leaf_buf, size_t leaf_len,
+ char *icon_buf, size_t icon_len);
+static void ro_gui_save_drag_end(wimp_dragged *drag, void *data);
+static bool ro_gui_save_create_thumbnail(hlcache_handle *h, const char *name);
+static void ro_gui_save_overwrite_confirmed(query_id, enum query_response res, void *p);
+static void ro_gui_save_overwrite_cancelled(query_id, enum query_response res, void *p);
+
+static const query_callback overwrite_funcs =
+{
+ ro_gui_save_overwrite_confirmed,
+ ro_gui_save_overwrite_cancelled
+};
+
+
+/** An entry in gui_save_table. */
+struct gui_save_table_entry {
+ int filetype;
+ const char *name;
+};
+
+/** Table of filetypes and default filenames. Must be in sync with
+ * gui_save_type (riscos/gui.h). A filetype of 0 indicates the content should
+ * be used.
+ */
+static const struct gui_save_table_entry gui_save_table[] = {
+ /* GUI_SAVE_SOURCE, */ { 0, "SaveSource" },
+ /* GUI_SAVE_DRAW, */ { 0xaff, "SaveDraw" },
+ /* GUI_SAVE_PDF, */ { 0xadf, "SavePDF" },
+ /* GUI_SAVE_TEXT, */ { 0xfff, "SaveText" },
+ /* GUI_SAVE_COMPLETE, */ { 0xfaf, "SaveComplete" },
+ /* GUI_SAVE_OBJECT_ORIG, */ { 0, "SaveObject" },
+ /* GUI_SAVE_OBJECT_NATIVE, */ { 0, "SaveObject" },
+ /* GUI_SAVE_LINK_URI, */ { 0xf91, "SaveLink" },
+ /* GUI_SAVE_LINK_URL, */ { 0xb28, "SaveLink" },
+ /* GUI_SAVE_LINK_TEXT, */ { 0xfff, "SaveLink" },
+ /* GUI_SAVE_HOTLIST_EXPORT_HTML, */ { 0xfaf, "Hotlist" },
+ /* GUI_SAVE_HISTORY_EXPORT_HTML, */ { 0xfaf, "History" },
+ /* GUI_SAVE_TEXT_SELECTION, */ { 0xfff, "SaveSelection" },
+};
+
+
+/**
+ * Create the saveas dialogue from the given template, and the sprite area
+ * necessary for our thumbnail (full page save)
+ *
+ * \param template_name name of template to be used
+ * \return window handle of created dialogue
+ */
+
+wimp_w ro_gui_saveas_create(const char *template_name)
+{
+ const int sprite_size = (68 * 68 * 4) + ((68 * 68) / 8); /* 32bpp with mask */
+ int area_size = sizeof(osspriteop_area) + sizeof(osspriteop_header) +
+ 256 * 8 + sprite_size;
+ void *area = NULL;
+ wimp_window *window;
+ os_error *error;
+ wimp_icon *icons;
+ wimp_w w;
+
+ window = ro_gui_dialog_load_template(template_name);
+ assert(window);
+
+ icons = window->icons;
+
+ error = xosmodule_alloc(area_size, (void **) &area);
+ if (error) {
+ LOG("xosmodule_alloc: 0x%x: %s", error->errnum, error->errmess);
+ xwimp_close_template();
+ die(error->errmess);
+ } else {
+ saveas_area = area;
+ saveas_area->size = area_size;
+ saveas_area->first = 16;
+
+ error = xosspriteop_clear_sprites(osspriteop_USER_AREA, saveas_area);
+ if (error) {
+ LOG("xosspriteop_clear_sprites: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("MiscError", error->errmess);
+
+ xosmodule_free(saveas_area);
+ saveas_area = NULL;
+ }
+ }
+
+ assert((icons[ICON_SAVE_ICON].flags &
+ (wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_INDIRECTED)) ==
+ (wimp_ICON_SPRITE | wimp_ICON_INDIRECTED));
+ icons[ICON_SAVE_ICON].data.indirected_sprite.area = saveas_area;
+
+ /* create window */
+ error = xwimp_create_window(window, &w);
+ if (error) {
+ LOG("xwimp_create_window: 0x%x: %s", error->errnum, error->errmess);
+ xwimp_close_template();
+ die(error->errmess);
+ }
+
+ /* the window definition is copied by the wimp and may be freed */
+ free(window);
+
+ return w;
+}
+
+
+/**
+ * Clean-up function that releases our sprite area and memory.
+ */
+
+void ro_gui_saveas_quit(void)
+{
+ if (saveas_area) {
+ os_error *error = xosmodule_free(saveas_area);
+ if (error) {
+ LOG("xosmodule_free: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("MiscError", error->errmess);
+ }
+ saveas_area = NULL;
+ }
+
+ free(save_dir);
+ save_dir = NULL;
+}
+
+/**
+ * Prepares the save box to reflect gui_save_type and a content, and
+ * opens it.
+ *
+ * \param save_type type of save
+ * \param h content to save
+ * \param s selection to save
+ * \param url url to be saved (link types)
+ * \param title title (if any), when saving links
+ */
+
+void ro_gui_save_prepare(gui_save_type save_type, hlcache_handle *h,
+ char *s, const nsurl *url, const char *title)
+{
+ char name_buf[FILENAME_MAX];
+ size_t leaf_offset = 0;
+ char icon_buf[20];
+
+ assert( (save_type == GUI_SAVE_LINK_URI) ||
+ (save_type == GUI_SAVE_LINK_URL) ||
+ (save_type == GUI_SAVE_LINK_TEXT) ||
+ (save_type == GUI_SAVE_HOTLIST_EXPORT_HTML) ||
+ (save_type == GUI_SAVE_HISTORY_EXPORT_HTML) ||
+ (save_type == GUI_SAVE_TEXT_SELECTION) || h);
+
+ if (gui_save_selection == NULL)
+ free(gui_save_selection);
+
+ gui_save_selection = s;
+ if (url != NULL) {
+ gui_save_url = nsurl_access(url);
+ } else {
+ gui_save_url = NULL;
+ }
+ gui_save_title = title;
+
+ if (save_dir) {
+ leaf_offset = save_dir_len;
+ memcpy(name_buf, save_dir, leaf_offset);
+ name_buf[leaf_offset++] = '.';
+ }
+
+ if (h != NULL) {
+ url = hlcache_handle_get_url(h);
+ }
+
+ ro_gui_save_set_state(h, save_type, url,
+ name_buf + leaf_offset, FILENAME_MAX - leaf_offset,
+ icon_buf, sizeof(icon_buf));
+
+ ro_gui_set_icon_sprite(dialog_saveas, ICON_SAVE_ICON, saveas_area,
+ icon_buf);
+
+ ro_gui_set_icon_string(dialog_saveas, ICON_SAVE_PATH, name_buf, true);
+ ro_gui_wimp_event_memorise(dialog_saveas);
+}
+
+/**
+ * Starts a drag for the save dialog
+ *
+ * \param pointer mouse position info from Wimp
+ */
+void ro_gui_save_start_drag(wimp_pointer *pointer)
+{
+ if (pointer->buttons & (wimp_DRAG_SELECT | wimp_DRAG_ADJUST)) {
+ const char *sprite = ro_gui_get_icon_string(pointer->w, pointer->i);
+ int x = pointer->pos.x, y = pointer->pos.y;
+ wimp_window_state wstate;
+ wimp_icon_state istate;
+ /* start the drag from the icon's exact location, rather than the pointer */
+ istate.w = wstate.w = pointer->w;
+ istate.i = pointer->i;
+ if (!xwimp_get_window_state(&wstate) && !xwimp_get_icon_state(&istate)) {
+ x = (istate.icon.extent.x1 + istate.icon.extent.x0)/2 +
+ wstate.visible.x0 - wstate.xscroll;
+ y = (istate.icon.extent.y1 + istate.icon.extent.y0)/2 +
+ wstate.visible.y1 - wstate.yscroll;
+ }
+ ro_mouse_drag_start(ro_gui_save_drag_end, NULL, NULL, NULL);
+ gui_save_sourcew = pointer->w;
+ saving_from_dialog = true;
+ gui_save_close_after = !(pointer->buttons & wimp_DRAG_ADJUST);
+ ro_gui_drag_icon(x, y, sprite);
+ }
+}
+
+
+/**
+ * Handle OK click/keypress in the save dialog.
+ *
+ * \param w window handle of save dialog
+ * \return true on success, false on failure
+ */
+bool ro_gui_save_ok(wimp_w w)
+{
+ const char *name = ro_gui_get_icon_string(w, ICON_SAVE_PATH);
+ wimp_pointer pointer;
+ char path[256];
+
+ if (!strrchr(name, '.')) {
+ ro_warn_user("NoPathError", NULL);
+ return false;
+ }
+
+ ro_gui_convert_save_path(path, sizeof path, name);
+ gui_save_sourcew = w;
+ saving_from_dialog = true;
+ gui_save_send_dataload = false;
+ gui_save_close_after = xwimp_get_pointer_info(&pointer)
+ || !(pointer.buttons & wimp_CLICK_ADJUST);
+ memcpy(&gui_save_message.data.data_xfer.file_name, path, 1 + strlen(path));
+
+ if (ro_gui_save_content(gui_save_content, path, !nsoption_bool(confirm_overwrite))) {
+ ro_gui_save_done();
+ return true;
+ }
+ return false;
+}
+
+
+/**
+ * Initiates drag saving of an object directly from a browser window
+ *
+ * \param save_type type of save
+ * \param c content to save
+ * \param g gui window
+ */
+
+void gui_drag_save_object(struct gui_window *g, hlcache_handle *c,
+ gui_save_type save_type)
+{
+ wimp_pointer pointer;
+ char icon_buf[20];
+ os_error *error;
+
+ /* Close the save window because otherwise we need two contexts
+ */
+ xwimp_create_menu(wimp_CLOSE_MENU, 0, 0);
+ ro_gui_dialog_close(dialog_saveas);
+
+ gui_save_sourcew = g->window;
+ saving_from_dialog = false;
+
+ error = xwimp_get_pointer_info(&pointer);
+ if (error) {
+ LOG("xwimp_get_pointer_info: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ ro_gui_save_set_state(c, save_type, hlcache_handle_get_url(c),
+ save_leafname, LEAFNAME_MAX,
+ icon_buf, sizeof(icon_buf));
+
+ ro_mouse_drag_start(ro_gui_save_drag_end, NULL, NULL, NULL);
+
+ ro_gui_drag_icon(pointer.pos.x, pointer.pos.y, icon_buf);
+}
+
+
+/**
+ * Initiates drag saving of a selection from a browser window
+ *
+ * \param g gui window
+ * \param selection selection object
+ */
+
+void gui_drag_save_selection(struct gui_window *g, const char *selection)
+{
+ wimp_pointer pointer;
+ char icon_buf[20];
+ os_error *error;
+
+ /* Close the save window because otherwise we need two contexts
+ */
+ xwimp_create_menu(wimp_CLOSE_MENU, 0, 0);
+ ro_gui_dialog_close(dialog_saveas);
+
+ gui_save_sourcew = g->window;
+ saving_from_dialog = false;
+
+ error = xwimp_get_pointer_info(&pointer);
+ if (error) {
+ LOG("xwimp_get_pointer_info: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+
+ if (gui_save_selection == NULL)
+ free(gui_save_selection);
+
+ if (selection == NULL)
+ gui_save_selection = strdup("");
+ else
+ gui_save_selection = strdup(selection);
+
+ ro_gui_save_set_state(NULL, GUI_SAVE_TEXT_SELECTION, NULL,
+ save_leafname, LEAFNAME_MAX,
+ icon_buf, sizeof(icon_buf));
+
+ ro_mouse_drag_start(ro_gui_save_drag_end, NULL, NULL, NULL);
+
+ ro_gui_drag_icon(pointer.pos.x, pointer.pos.y, icon_buf);
+}
+
+
+/**
+ * Initiates drag saving of a link/URL file
+ *
+ * \param save_type format in which URL should be saved
+ * \param url url to be saved
+ * \param title title to be included in URI format, if any
+ * \param g gui window to save from
+ * \
+ */
+
+void ro_gui_drag_save_link(gui_save_type save_type, const nsurl *url,
+ const char *title, struct gui_window *g)
+{
+ wimp_pointer pointer;
+ char icon_buf[20];
+ os_error *error;
+
+ /* Close the save window because otherwise we need two contexts
+ */
+ xwimp_create_menu(wimp_CLOSE_MENU, 0, 0);
+ ro_gui_dialog_close(dialog_saveas);
+
+ gui_save_url = nsurl_access(url);
+ gui_save_title = title;
+ gui_save_sourcew = g->window;
+ saving_from_dialog = false;
+
+ error = xwimp_get_pointer_info(&pointer);
+ if (error) {
+ LOG("xwimp_get_pointer_info: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ ro_gui_save_set_state(NULL, save_type, url, save_leafname,
+ LEAFNAME_MAX, icon_buf, sizeof(icon_buf));
+
+ ro_mouse_drag_start(ro_gui_save_drag_end, NULL, NULL, NULL);
+
+ ro_gui_drag_icon(pointer.pos.x, pointer.pos.y, icon_buf);
+}
+
+
+/**
+ * Start drag of icon under the pointer.
+ */
+
+void ro_gui_drag_icon(int x, int y, const char *sprite)
+{
+ os_error *error;
+ wimp_drag drag;
+ int r2;
+
+ drag.initial.x0 = x - 34;
+ drag.initial.y0 = y - 34;
+ drag.initial.x1 = x + 34;
+ drag.initial.y1 = y + 34;
+
+ if (sprite && (xosbyte2(osbyte_READ_CMOS, 28, 0, &r2) || (r2 & 2))) {
+ osspriteop_area *area = (osspriteop_area*)1;
+
+ /* first try our local sprite area in case it's a thumbnail sprite */
+ if (saveas_area) {
+ error = xosspriteop_select_sprite(osspriteop_USER_AREA,
+ saveas_area, (osspriteop_id)sprite, NULL);
+ if (error) {
+ if (error->errnum != error_SPRITE_OP_DOESNT_EXIST) {
+ LOG("xosspriteop_select_sprite: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("MiscError", error->errmess);
+ }
+ }
+ else
+ area = saveas_area;
+ }
+
+ error = xdragasprite_start(dragasprite_HPOS_CENTRE |
+ dragasprite_VPOS_CENTRE |
+ dragasprite_BOUND_POINTER |
+ dragasprite_DROP_SHADOW,
+ area, sprite, &drag.initial, 0);
+
+ if (!error) {
+ using_dragasprite = true;
+ dragbox_active = true;
+ return;
+ }
+
+ LOG("xdragasprite_start: 0x%x: %s", error->errnum, error->errmess);
+ }
+
+ drag.type = wimp_DRAG_USER_FIXED;
+ drag.bbox.x0 = -0x8000;
+ drag.bbox.y0 = -0x8000;
+ drag.bbox.x1 = 0x7fff;
+ drag.bbox.y1 = 0x7fff;
+
+ using_dragasprite = false;
+ error = xwimp_drag_box(&drag);
+
+ if (error) {
+ LOG("xwimp_drag_box: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("DragError", error->errmess);
+ }
+ else
+ dragbox_active = true;
+}
+
+
+/**
+ * Convert a ctrl-char terminated pathname possibly containing spaces
+ * to a NUL-terminated one containing only hard spaces.
+ *
+ * \param dp destination buffer to receive pathname
+ * \param len size of destination buffer
+ * \param p source pathname, ctrl-char terminated
+ */
+
+void ro_gui_convert_save_path(char *dp, size_t len, const char *p)
+{
+ char *ep = dp + len - 1; /* leave room for NUL */
+
+ assert(p <= dp || p > ep); /* in-situ conversion /is/ allowed */
+
+ while (dp < ep && *p >= ' ') /* ctrl-char terminated */
+ {
+ *dp++ = (*p == ' ') ? 160 : *p;
+ p++;
+ }
+ *dp = '\0';
+}
+
+
+void ro_gui_drag_box_cancel(void)
+{
+ if (dragbox_active) {
+ os_error *error;
+ if (using_dragasprite) {
+ error = xdragasprite_stop();
+ if (error) {
+ LOG("xdragasprite_stop: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+ }
+ else {
+ error = xwimp_drag_box(NULL);
+ if (error) {
+ LOG("xwimp_drag_box: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+ }
+ dragbox_active = false;
+ }
+}
+
+
+/**
+ * Handle User_Drag_Box event for a drag from the save dialog or browser window.
+ *
+ * \param *drag The Wimp_DragEnd data block.
+ * \param *data NULL, as function is used as a callback from ro_mouse.
+ */
+
+static void ro_gui_save_drag_end(wimp_dragged *drag, void *data)
+{
+ const char *name;
+ wimp_pointer pointer;
+ wimp_message message;
+ os_error *error;
+ char *dp, *ep;
+ char *local_name = NULL;
+
+ if (dragbox_active)
+ ro_gui_drag_box_cancel();
+
+ error = xwimp_get_pointer_info(&pointer);
+ if (error) {
+ LOG("xwimp_get_pointer_info: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ /* perform hit-test if the destination is the same as the source window;
+ we want to allow drag-saving from a page into the input fields within
+ the page, but avoid accidental replacements of the current page */
+ if (gui_save_sourcew != (wimp_w)-1 && pointer.w == gui_save_sourcew) {
+ int dx = (drag->final.x1 + drag->final.x0)/2;
+ int dy = (drag->final.y1 + drag->final.y0)/2;
+ struct gui_window *g;
+ bool dest_ok = false;
+ os_coord pos;
+
+ g = ro_gui_window_lookup(gui_save_sourcew);
+
+ if (g && ro_gui_window_to_window_pos(g, dx, dy, &pos)) {
+ dest_ok = browser_window_drop_file_at_point(g->bw,
+ pos.x, pos.y, NULL);
+ }
+ if (!dest_ok)
+ return;
+ }
+
+ if (!saving_from_dialog) {
+ /* saving directly from browser window, choose a
+ * name based upon the URL */
+ nserror err;
+ err = utf8_to_local_encoding(save_leafname, 0, &local_name);
+ if (err != NSERROR_OK) {
+ /* badenc should never happen */
+ assert(err != NSERROR_BAD_ENCODING);
+ local_name = NULL;
+ }
+ name = local_name ? local_name : save_leafname;
+ }
+ else {
+ char *dot;
+
+ /* saving from dialog, grab leafname from icon */
+ name = ro_gui_get_icon_string(gui_save_sourcew, ICON_SAVE_PATH);
+ dot = strrchr(name, '.');
+ if (dot)
+ name = dot + 1;
+ }
+
+ dp = message.data.data_xfer.file_name;
+ ep = dp + sizeof message.data.data_xfer.file_name;
+
+ if (gui_save_current_type == GUI_SAVE_COMPLETE) {
+ message.data.data_xfer.file_type = 0x2000;
+ if (*name != '!') *dp++ = '!';
+ } else
+ message.data.data_xfer.file_type = gui_save_filetype;
+
+ ro_gui_convert_save_path(dp, ep - dp, name);
+
+/* \todo - we're supposed to set this if drag-n-drop used */
+ message.your_ref = 0;
+
+ message.action = message_DATA_SAVE;
+ message.data.data_xfer.w = pointer.w;
+ message.data.data_xfer.i = pointer.i;
+ message.data.data_xfer.pos.x = pointer.pos.x;
+ message.data.data_xfer.pos.y = pointer.pos.y;
+ message.data.data_xfer.est_size = 1000;
+ message.size = 44 + ((strlen(message.data.data_xfer.file_name) + 4) &
+ (~3u));
+
+ ro_message_send_message_to_window(wimp_USER_MESSAGE_RECORDED, &message,
+ pointer.w, pointer.i, ro_gui_save_bounced, NULL);
+
+ gui_current_drag_type = GUI_DRAG_SAVE;
+
+ free(local_name);
+}
+
+
+
+/**
+ * Send DataSave message on behalf of clipboard code and remember that it's the
+ * clipboard contents we're being asked for when the DataSaveAck reply arrives
+ */
+
+void ro_gui_send_datasave(gui_save_type save_type,
+ wimp_full_message_data_xfer *message, wimp_t to)
+{
+ /* Close the save window because otherwise we need two contexts
+ */
+
+ ro_gui_dialog_close(dialog_saveas);
+
+ if (ro_message_send_message(wimp_USER_MESSAGE_RECORDED, (wimp_message*)message,
+ to, ro_gui_save_bounced)) {
+ gui_save_current_type = save_type;
+ gui_save_sourcew = (wimp_w)-1;
+ saving_from_dialog = false;
+
+ gui_current_drag_type = GUI_DRAG_SAVE;
+ }
+}
+
+
+/**
+ * Handle lack of Message_DataSaveAck for drags, saveas dialogs and clipboard code
+ */
+
+void ro_gui_save_bounced(wimp_message *message)
+{
+ gui_current_drag_type = GUI_DRAG_NONE;
+}
+
+
+/**
+ * Handle Message_DataSaveAck for a drag from the save dialog or browser window,
+ * or Clipboard protocol.
+ */
+
+void ro_gui_save_datasave_ack(wimp_message *message)
+{
+ char *path = message->data.data_xfer.file_name;
+ hlcache_handle *h = gui_save_content;
+ bool force_overwrite;
+
+ switch (gui_save_current_type) {
+ case GUI_SAVE_LINK_URI:
+ case GUI_SAVE_LINK_URL:
+ case GUI_SAVE_LINK_TEXT:
+ case GUI_SAVE_HOTLIST_EXPORT_HTML:
+ case GUI_SAVE_HISTORY_EXPORT_HTML:
+ case GUI_SAVE_TEXT_SELECTION:
+ case GUI_SAVE_CLIPBOARD_CONTENTS:
+ break;
+
+ default:
+ if (!gui_save_content) {
+ LOG("unexpected DataSaveAck: gui_save_content not set");
+ return;
+ }
+ break;
+ }
+
+ if (saving_from_dialog)
+ ro_gui_set_icon_string(gui_save_sourcew, ICON_SAVE_PATH,
+ path, true);
+
+ gui_save_send_dataload = true;
+ memcpy(&gui_save_message, message, sizeof(gui_save_message));
+
+ /* if saving/pasting to another application, don't request user
+ confirmation; a ScrapFile almost certainly exists already */
+ if (message->data.data_xfer.est_size == -1)
+ force_overwrite = true;
+ else
+ force_overwrite = !nsoption_bool(confirm_overwrite);
+
+ if (ro_gui_save_content(h, path, force_overwrite))
+ ro_gui_save_done();
+}
+
+
+
+/**
+ * Does the actual saving
+ *
+ * \param h handle to content to save (or NULL for other)
+ * \param path path to save as
+ * \param force_overwrite true iff required to overwrite without prompting
+ * \return true on success,
+ * false on (i) error and error reported
+ * or (ii) deferred awaiting user confirmation
+ */
+
+bool ro_gui_save_content(hlcache_handle *h, char *path, bool force_overwrite)
+{
+ os_error *error;
+ const char *source_data;
+ unsigned long source_size;
+
+ /* does the user want to check for collisions when saving? */
+ if (!force_overwrite) {
+ fileswitch_object_type obj_type;
+ /* check whether the destination file/dir already exists */
+ error = xosfile_read_stamped(path, &obj_type,
+ NULL, NULL, NULL, NULL, NULL);
+ if (error) {
+ LOG("xosfile_read_stamped: 0x%x:%s", error->errnum, error->errmess);
+ ro_warn_user("SaveError", error->errmess);
+ return false;
+ }
+
+ switch (obj_type) {
+ case osfile_NOT_FOUND:
+ break;
+
+ case osfile_IS_FILE:
+ gui_save_query = query_user("OverwriteFile", NULL, &overwrite_funcs, NULL,
+ messages_get("Replace"), messages_get("DontReplace"));
+// gui_save_query_rsn = QueryRsn_Overwrite;
+ return false;
+
+ default:
+ error = xosfile_make_error(path, obj_type);
+ assert(error);
+ ro_warn_user("SaveError", error->errmess);
+ return false;
+ }
+ }
+
+ switch (gui_save_current_type) {
+#ifdef WITH_DRAW_EXPORT
+ case GUI_SAVE_DRAW:
+ return save_as_draw(h, path);
+#endif
+#ifdef WITH_PDF_EXPORT
+ case GUI_SAVE_PDF:
+ return save_as_pdf(h, path);
+#endif
+ case GUI_SAVE_TEXT:
+ save_as_text(h, path);
+ xosfile_set_type(path, 0xfff);
+ break;
+ case GUI_SAVE_COMPLETE:
+ assert(h);
+ if (content_get_type(h) == CONTENT_HTML) {
+ if (strcmp(path, "<Wimp$Scrap>"))
+ return ro_gui_save_complete(h, path);
+
+ /* we can't send a whole directory to another
+ * application, so just send the HTML source */
+ gui_save_current_type = GUI_SAVE_SOURCE;
+ }
+ else
+ gui_save_current_type = GUI_SAVE_OBJECT_ORIG; /* \todo do this earlier? */
+ /* no break */
+ case GUI_SAVE_SOURCE:
+ case GUI_SAVE_OBJECT_ORIG:
+ source_data = content_get_source_data(h, &source_size);
+ error = xosfile_save_stamped(path,
+ ro_content_filetype(h),
+ (byte *) source_data,
+ (byte *) source_data + source_size);
+ if (error) {
+ LOG("xosfile_save_stamped: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("SaveError", error->errmess);
+ return false;
+ }
+ break;
+
+ case GUI_SAVE_OBJECT_NATIVE:
+ return ro_gui_save_object_native(h, path);
+
+ case GUI_SAVE_LINK_URI:
+ return ro_gui_save_link(gui_save_url, gui_save_title,
+ LINK_ACORN, path);
+
+ case GUI_SAVE_LINK_URL:
+ return ro_gui_save_link(gui_save_url, gui_save_title,
+ LINK_ANT, path);
+
+ case GUI_SAVE_LINK_TEXT:
+ return ro_gui_save_link(gui_save_url, gui_save_title,
+ LINK_TEXT, path);
+
+ case GUI_SAVE_HOTLIST_EXPORT_HTML:
+ if (hotlist_export(path, NULL) != NSERROR_OK)
+ return false;
+ error = xosfile_set_type(path, 0xfaf);
+ if (error)
+ LOG("xosfile_set_type: 0x%x: %s", error->errnum, error->errmess);
+ break;
+ case GUI_SAVE_HISTORY_EXPORT_HTML:
+ if (global_history_export(path, NULL) != NSERROR_OK)
+ return false;
+ error = xosfile_set_type(path, 0xfaf);
+ if (error)
+ LOG("xosfile_set_type: 0x%x: %s", error->errnum, error->errmess);
+ break;
+
+ case GUI_SAVE_TEXT_SELECTION:
+ if (gui_save_selection == NULL)
+ return false;
+ if (!utf8_save_text(gui_save_selection, path)) {
+ free(gui_save_selection);
+ gui_save_selection = NULL;
+ return false;
+ }
+ free(gui_save_selection);
+ gui_save_selection = NULL;
+ xosfile_set_type(path, 0xfff);
+ break;
+
+ case GUI_SAVE_CLIPBOARD_CONTENTS:
+ return ro_gui_save_clipboard(path);
+
+ default:
+ LOG("Unexpected content type: %d, path %s", gui_save_current_type, path);
+ return false;
+ }
+ return true;
+}
+
+
+/**
+ * Save completed, inform recipient and close our 'save as' dialog.
+ */
+
+void ro_gui_save_done(void)
+{
+ os_error *error;
+
+ if (gui_save_send_dataload) {
+ /* Ack successful save with message_DATA_LOAD */
+ wimp_message *message = &gui_save_message;
+ message->action = message_DATA_LOAD;
+ message->your_ref = message->my_ref;
+ error = xwimp_send_message(wimp_USER_MESSAGE, message,
+ message->sender);
+ if (error) {
+ LOG("xwimp_send_message: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("SaveError", error->errmess);
+ }
+ }
+
+ if (saving_from_dialog) {
+ /* remember the save directory if saving to the Filer */
+ if (!gui_save_send_dataload ||
+ gui_save_message.data.data_xfer.est_size != -1) {
+ char *sp = gui_save_message.data.data_xfer.file_name;
+ char *ep = sp + sizeof(gui_save_message.data.data_xfer.file_name);
+ char *lastdot = NULL;
+ char *p = sp;
+
+ while (p < ep && *p >= 0x20) {
+ if (*p == '.') {
+ /* don't remember the directory if it's a temporary file */
+ if (!lastdot && p == sp + 12 &&
+ !memcmp(sp, "<Wimp$Scrap>", 12)) break;
+ lastdot = p;
+ }
+ p++;
+ }
+ if (lastdot) {
+ /* remember the directory */
+ char *new_dir = realloc(save_dir, (lastdot+1)-sp);
+ if (new_dir) {
+ save_dir_len = lastdot - sp;
+ memcpy(new_dir, sp, save_dir_len);
+ new_dir[save_dir_len] = '\0';
+ save_dir = new_dir;
+ }
+ }
+ }
+
+ if (gui_save_close_after) {
+ /* Close the save window */
+ ro_gui_dialog_close(dialog_saveas);
+ error = xwimp_create_menu(wimp_CLOSE_MENU, 0, 0);
+ if (error) {
+ LOG("xwimp_create_menu: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("MenuError", error->errmess);
+ }
+ }
+ }
+
+ if (!saving_from_dialog || gui_save_close_after)
+ gui_save_content = 0;
+}
+
+static void ro_gui_save_set_file_type(const char *path, lwc_string *mime_type)
+{
+ int rotype = ro_content_filetype_from_mime_type(mime_type);
+ os_error *error;
+
+ error = xosfile_set_type(path, rotype);
+ if (error != NULL) {
+ LOG("xosfile_set_type: 0x%x: %s", error->errnum, error->errmess);
+ }
+}
+
+/**
+ * Prepare an application directory and save_complete() to it.
+ *
+ * \param h content of type CONTENT_HTML to save
+ * \param path path to save as
+ * \return true on success, false on error and error reported
+ */
+
+bool ro_gui_save_complete(hlcache_handle *h, char *path)
+{
+ void *spr = ((byte *) saveas_area) + saveas_area->first;
+ osspriteop_header *sprite = (osspriteop_header *) spr;
+ char name[12];
+ char buf[256];
+ FILE *fp;
+ os_error *error;
+ size_t len;
+ char *dot;
+ int i;
+
+ /* Create dir */
+ error = xosfile_create_dir(path, 0);
+ if (error) {
+ LOG("xosfile_create_dir: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("SaveError", error->errmess);
+ return false;
+ }
+
+ /* Save !Run file */
+ snprintf(buf, sizeof buf, "%s.!Run", path);
+ fp = fopen(buf, "w");
+ if (!fp) {
+ LOG("fopen(): errno = %i", errno);
+ ro_warn_user("SaveError", strerror(errno));
+ return false;
+ }
+ fprintf(fp, "IconSprites <Obey$Dir>.!Sprites\n");
+ fprintf(fp, "Filer_Run <Obey$Dir>.index\n");
+ fclose(fp);
+ error = xosfile_set_type(buf, 0xfeb);
+ if (error) {
+ LOG("xosfile_set_type: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("SaveError", error->errmess);
+ return false;
+ }
+
+ /* create an empty !Runimage so the date gets correctly set */
+ snprintf(buf, sizeof buf, "%s.!RunImage", path);
+ fp = fopen(buf, "w");
+ if (!fp) {
+ LOG("Creating !RunImage failed: errno = %i", errno);
+ } else {
+ fclose(fp);
+ }
+
+ /* Make sure the sprite name matches the directory name, because
+ the user may have renamed the directory since we created the
+ thumbnail sprite */
+
+ dot = strrchr(path, '.');
+ if (dot) dot++; else dot = path;
+ len = strlen(dot);
+ if (len >= 12) len = 12;
+
+ memcpy(name, sprite->name, 12); /* remember original name */
+ memcpy(sprite->name, dot, len);
+ memset(sprite->name + len, 0, 12 - len);
+ for (i = 0; i < 12; i++) /* convert to lower case */
+ if (sprite->name[i] != '\0')
+ sprite->name[i] = tolower(sprite->name[i]);
+
+ /* Create !Sprites */
+ snprintf(buf, sizeof buf, "%s.!Sprites", path);
+
+ error = xosspriteop_save_sprite_file(osspriteop_NAME, saveas_area, buf);
+ if (error) {
+ LOG("xosspriteop_save_sprite_file: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("SaveError", error->errmess);
+ return false;
+ }
+
+ /* restore sprite name in case the save fails and we need to try again */
+ memcpy(sprite->name, name, 12);
+
+ /* save URL file with original URL */
+ snprintf(buf, sizeof buf, "%s.URL", path);
+ if (!ro_gui_save_link(nsurl_access(hlcache_handle_get_url(h)),
+ content_get_title(h), LINK_ANT, buf))
+ return false;
+
+ return save_complete(h, path, ro_gui_save_set_file_type);
+}
+
+bool ro_gui_save_object_native(hlcache_handle *h, char *path)
+{
+ int file_type = ro_content_filetype(h);
+
+ if (file_type == osfile_TYPE_SPRITE || file_type == osfile_TYPE_DRAW) {
+ /* Native sprite or drawfile */
+ const char *source_data;
+ unsigned long source_size;
+ os_error *error;
+
+ source_data = content_get_source_data(h, &source_size);
+ error = xosfile_save_stamped(path, file_type,
+ (byte *) source_data,
+ (byte *) source_data + source_size);
+ if (error != NULL) {
+ LOG("xosfile_save_stamped: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("SaveError", error->errmess);
+ return false;
+ }
+ } else {
+ /* Non-native type: export */
+ switch (ro_content_native_type(h)) {
+ case osfile_TYPE_SPRITE:
+ {
+ unsigned flags = (os_version == 0xA9) ?
+ BITMAP_SAVE_FULL_ALPHA : 0;
+ riscos_bitmap_save(content_get_bitmap(h), path, flags);
+ }
+ break;
+ case osfile_TYPE_DRAW:
+ /* Must be SVG */
+ return save_as_draw(h, path);
+ default:
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+/**
+ * Save a link file.
+ *
+ * \param url url to be saved
+ * \param title corresponding title, if any
+ * \param format format of link file
+ * \param path pathname for link file
+ * \return true on success, false on failure and reports the error
+ */
+
+bool ro_gui_save_link(const char *url, const char *title, link_format format,
+ char *path)
+{
+ FILE *fp = fopen(path, "w");
+
+ if (!fp) {
+ ro_warn_user("SaveError", strerror(errno));
+ return false;
+ }
+
+ switch (format) {
+ case LINK_ACORN: /* URI */
+ fprintf(fp, "%s\t%s\n", "URI", "100");
+ fprintf(fp, "\t# NetSurf %s\n\n", netsurf_version);
+ fprintf(fp, "\t%s\n", url);
+ if (title)
+ fprintf(fp, "\t%s\n", title);
+ else
+ fprintf(fp, "\t*\n");
+ break;
+ case LINK_ANT: /* URL */
+ case LINK_TEXT: /* Text */
+ fprintf(fp, "%s\n", url);
+ break;
+ }
+
+ fclose(fp);
+
+ switch (format) {
+ case LINK_ACORN: /* URI */
+ xosfile_set_type(path, 0xf91);
+ break;
+ case LINK_ANT: /* URL */
+ xosfile_set_type(path, 0xb28);
+ break;
+ case LINK_TEXT: /* Text */
+ xosfile_set_type(path, 0xfff);
+ break;
+ }
+
+ return true;
+}
+
+
+/**
+ * Suggest a leafname and sprite name for the given content.
+ *
+ * \param h content being saved
+ * \param save_type type of save operation being performed
+ * \param url used to determine leafname
+ * \param leaf_buf buffer to receive suggested leafname.
+ * \param leaf_len size of buffer to receive suggested leafname.
+ * \param icon_buf buffer to receive sprite name.
+ * \param icon_len size of buffer to receive icon name.
+ */
+
+void ro_gui_save_set_state(hlcache_handle *h, gui_save_type save_type,
+ const nsurl *url, char *leaf_buf, size_t leaf_len,
+ char *icon_buf, size_t icon_len)
+{
+ /* filename */
+ const char *name = gui_save_table[save_type].name;
+ bool done = false;
+ char *nice = NULL;
+ nserror err;
+ char *local_name;
+
+ assert(icon_len >= 13);
+
+ /* parameters that we need to remember */
+ gui_save_current_type = save_type;
+ gui_save_content = h;
+
+ /* suggest a filetype based upon the content */
+ gui_save_filetype = gui_save_table[save_type].filetype;
+ if (!gui_save_filetype && h) {
+ if (save_type == GUI_SAVE_OBJECT_NATIVE) {
+ switch (ro_content_native_type(h)) {
+ case osfile_TYPE_SPRITE:
+ gui_save_filetype = osfile_TYPE_SPRITE;
+ break;
+ case osfile_TYPE_DRAW:
+ gui_save_filetype = osfile_TYPE_DRAW;
+ break;
+ default:
+ break;
+ }
+ }
+ if (!gui_save_filetype)
+ gui_save_filetype = ro_content_filetype(h);
+ }
+
+ /* leafname */
+ if ((url != NULL) &&
+ (nsurl_nice(url, &nice, nsoption_bool(strip_extensions)) ==
+ NSERROR_OK)) {
+ size_t i;
+ for (i = 0; nice[i]; i++) {
+ if (nice[i] == '.')
+ nice[i] = '/';
+ else if (nice[i] <= ' ' ||
+ strchr(":*#$&@^%\\", nice[i]))
+ nice[i] = '_';
+ }
+ name = nice;
+ } else {
+ name = messages_get(name);
+ }
+
+ /* filename is utf8 */
+ if (save_type == GUI_SAVE_COMPLETE && leaf_len > 0) {
+ leaf_buf[0] = '!';
+ leaf_buf++;
+ leaf_len--;
+ }
+ strncpy(leaf_buf, name, leaf_len);
+ leaf_buf[leaf_len - 1] = 0;
+
+ err = utf8_to_local_encoding(name, 0, &local_name);
+ if (err != NSERROR_OK) {
+ /* badenc should never happen */
+ assert(err != NSERROR_BAD_ENCODING);
+ local_name = NULL;
+ }
+
+ if (local_name != NULL)
+ name = local_name;
+
+ /* sprite name used for icon and dragging */
+ if (save_type == GUI_SAVE_COMPLETE) {
+ int index;
+
+ /* Paint gets confused with uppercase characters and we need to
+ convert spaces to hard spaces */
+ icon_buf[0] = '!';
+ for (index = 0; index < 11 && name[index]; ) {
+ char ch = name[index];
+ if (ch == ' ')
+ icon_buf[++index] = 0xa0;
+ else
+ icon_buf[++index] = tolower(ch);
+ }
+ memset(&icon_buf[index + 1], 0, 11 - index);
+ icon_buf[12] = '\0';
+
+ if (ro_gui_save_create_thumbnail(h, icon_buf))
+ done = true;
+ }
+
+ if (!done) {
+ osspriteop_header *sprite;
+ os_error *error;
+
+ sprintf(icon_buf, "file_%.3x", gui_save_filetype);
+
+ error = ro_gui_wimp_get_sprite(icon_buf, &sprite);
+ if (error && error->errnum == error_SPRITE_OP_DOESNT_EXIST) {
+ /* try the 'unknown' filetype sprite as a fallback */
+ memcpy(icon_buf, "file_xxx", 9);
+ error = ro_gui_wimp_get_sprite(icon_buf, &sprite);
+ }
+
+ if (error) {
+ LOG("ro_gui_wimp_get_sprite: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("MiscError", error->errmess);
+ } else {
+ /* the sprite area should always be large enough for
+ * file_xxx sprites */
+ assert(sprite->size <= saveas_area->size -
+ saveas_area->first);
+
+ memcpy((byte*)saveas_area + saveas_area->first,
+ sprite,
+ sprite->size);
+
+ saveas_area->sprite_count = 1;
+ saveas_area->used = saveas_area->first + sprite->size;
+ }
+ }
+
+ free(local_name);
+ free(nice);
+}
+
+
+
+/**
+ * Create a thumbnail sprite for the page being saved.
+ *
+ * \param h content to be converted
+ * \param name sprite name to use
+ * \return true iff successful
+ */
+
+bool ro_gui_save_create_thumbnail(hlcache_handle *h, const char *name)
+{
+ osspriteop_header *sprite_header;
+ struct bitmap *bitmap;
+ osspriteop_area *area;
+
+ bitmap = riscos_bitmap_create(34, 34, BITMAP_NEW | BITMAP_OPAQUE | BITMAP_CLEAR_MEMORY);
+ if (!bitmap) {
+ LOG("Thumbnail initialisation failed.");
+ return false;
+ }
+ riscos_bitmap_render(bitmap, h);
+ area = riscos_bitmap_convert_8bpp(bitmap);
+ riscos_bitmap_destroy(bitmap);
+ if (!area) {
+ LOG("Thumbnail conversion failed.");
+ return false;
+ }
+
+ sprite_header = (osspriteop_header *)(area + 1);
+ strncpy(sprite_header->name, name, 12);
+
+
+ /* we can't resize the saveas sprite area because it may move and we have
+ no elegant way to update the window definition on all OS versions */
+ assert(sprite_header->size <= saveas_area->size - saveas_area->first);
+
+ memcpy((byte*)saveas_area + saveas_area->first,
+ sprite_header, sprite_header->size);
+
+ saveas_area->sprite_count = 1;
+ saveas_area->used = saveas_area->first + sprite_header->size;
+
+ free(area);
+
+ return true;
+}
+
+
+/**
+ * User has opted not to overwrite the existing file.
+ */
+
+void ro_gui_save_overwrite_cancelled(query_id id, enum query_response res, void *p)
+{
+ if (!saving_from_dialog) {
+// ro_gui_save_prepare(gui_save_current_type, gui_save_content);
+// ro_gui_dialog_open_persistent(g->window, dialog_saveas, true);
+ }
+}
+
+
+/**
+ * Overwrite of existing file confirmed, proceed with the save.
+ */
+
+void ro_gui_save_overwrite_confirmed(query_id id, enum query_response res, void *p)
+{
+ if (ro_gui_save_content(gui_save_content, gui_save_message.data.data_xfer.file_name, true))
+ ro_gui_save_done();
+}
diff --git a/frontends/riscos/save.h b/frontends/riscos/save.h
new file mode 100644
index 000000000..dba09a984
--- /dev/null
+++ b/frontends/riscos/save.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2006 Adrian Lees <adrianl@users.sourceforge.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * File/object/selection saving (Interface).
+ */
+
+#ifndef _NETSURF_RISCOS_SAVE_H_
+#define _NETSURF_RISCOS_SAVE_H_
+
+#include <stdbool.h>
+#include "oslib/wimp.h"
+
+enum gui_save_type;
+struct nsurl;
+
+void gui_drag_save_object(struct gui_window *g, struct hlcache_handle *c, enum gui_save_type save_type);
+void gui_drag_save_selection(struct gui_window *g, const char *selection);
+
+wimp_w ro_gui_saveas_create(const char *template_name);
+void ro_gui_saveas_quit(void);
+void ro_gui_save_prepare(enum gui_save_type save_type, struct hlcache_handle *h,
+ char *s, const struct nsurl *url,
+ const char *title);
+void ro_gui_save_start_drag(wimp_pointer *pointer);
+void ro_gui_drag_save_link(enum gui_save_type save_type, const struct nsurl *url,
+ const char *title, struct gui_window *g);
+void ro_gui_drag_icon(int x, int y, const char *sprite);
+void ro_gui_drag_box_cancel(void);
+void ro_gui_send_datasave(enum gui_save_type save_type, wimp_full_message_data_xfer *message, wimp_t to);
+void ro_gui_save_datasave_ack(wimp_message *message);
+bool ro_gui_save_ok(wimp_w w);
+void ro_gui_convert_save_path(char *dp, size_t len, const char *p);
+
+#endif
diff --git a/frontends/riscos/save_draw.c b/frontends/riscos/save_draw.c
new file mode 100644
index 000000000..50febf3b2
--- /dev/null
+++ b/frontends/riscos/save_draw.c
@@ -0,0 +1,474 @@
+/*
+ * Copyright 2004 John M Bell <jmb202@ecs.soton.ac.uk>
+ * Copyright 2004-2008 John Tytgat <joty@netsurf-browser.org>
+ * Copyright 2007 James Bursa <bursa@users.sourceforge.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Export a content as a DrawFile (implementation).
+ */
+
+#ifdef WITH_DRAW_EXPORT
+
+#include <assert.h>
+#include <limits.h>
+#include <oslib/draw.h>
+#include <oslib/osfile.h>
+#include <pencil.h>
+
+#include "utils/log.h"
+#include "utils/utils.h"
+#include "content/content.h"
+#include "content/hlcache.h"
+#include "desktop/plotters.h"
+
+#include "riscos/bitmap.h"
+#include "riscos/gui.h"
+#include "riscos/save_draw.h"
+#include "riscos/font.h"
+
+static bool ro_save_draw_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style);
+static bool ro_save_draw_line(int x0, int y0, int x1, int y1, const plot_style_t *style);
+static bool ro_save_draw_polygon(const int *p, unsigned int n, const plot_style_t *style);
+static bool ro_save_draw_path(const float *p, unsigned int n, colour fill,
+ float width, colour c, const float transform[6]);
+static bool ro_save_draw_clip(const struct rect *clip);
+static bool ro_save_draw_text(int x, int y, const char *text, size_t length,
+ const plot_font_style_t *fstyle);
+static bool ro_save_draw_disc(int x, int y, int radius, const plot_style_t *style);
+static bool ro_save_draw_arc(int x, int y, int radius, int angle1, int angle2,
+ const plot_style_t *style);
+static bool ro_save_draw_bitmap(int x, int y, int width, int height,
+ struct bitmap *bitmap, colour bg, bitmap_flags_t flags);
+static bool ro_save_draw_group_start(const char *name);
+static bool ro_save_draw_group_end(void);
+static bool ro_save_draw_error(pencil_code code);
+
+
+static const struct plotter_table ro_save_draw_plotters = {
+ .rectangle = ro_save_draw_rectangle,
+ .line = ro_save_draw_line,
+ .polygon = ro_save_draw_polygon,
+ .clip = ro_save_draw_clip,
+ .text = ro_save_draw_text,
+ .disc = ro_save_draw_disc,
+ .arc = ro_save_draw_arc,
+ .bitmap = ro_save_draw_bitmap,
+ .group_start = ro_save_draw_group_start,
+ .group_end = ro_save_draw_group_end,
+ .path = ro_save_draw_path,
+ .option_knockout = false,
+};
+
+static struct pencil_diagram *ro_save_draw_diagram;
+static int ro_save_draw_width;
+static int ro_save_draw_height;
+
+
+/**
+ * Export a content as a DrawFile.
+ *
+ * \param h content to export
+ * \param path path to save DrawFile as
+ * \return true on success, false on error and error reported
+ */
+
+bool save_as_draw(hlcache_handle *h, const char *path)
+{
+ pencil_code code;
+ char *drawfile_buffer;
+ struct rect clip;
+ struct content_redraw_data data;
+ size_t drawfile_size;
+ os_error *error;
+ struct redraw_context ctx = {
+ .interactive = false,
+ .background_images = true,
+ .plot = &ro_save_draw_plotters
+ };
+
+ ro_save_draw_diagram = pencil_create();
+ if (!ro_save_draw_diagram) {
+ ro_warn_user("NoMemory", 0);
+ return false;
+ }
+
+ ro_save_draw_width = content_get_width(h);
+ ro_save_draw_height = content_get_height(h);
+
+ clip.x0 = clip.y0 = INT_MIN;
+ clip.x1 = clip.y1 = INT_MAX;
+
+ data.x = 0;
+ data.y = -ro_save_draw_height;
+ data.width = ro_save_draw_width;
+ data.height = ro_save_draw_height;
+ data.background_colour = 0xFFFFFF;
+ data.scale = 1;
+ data.repeat_x = false;
+ data.repeat_y = false;
+
+ if (!content_redraw(h, &data, &clip, &ctx)) {
+ pencil_free(ro_save_draw_diagram);
+ return false;
+ }
+
+ /*pencil_dump(ro_save_draw_diagram);*/
+
+ code = pencil_save_drawfile(ro_save_draw_diagram, "NetSurf",
+ &drawfile_buffer, &drawfile_size);
+ if (code != pencil_OK) {
+ ro_warn_user("SaveError", 0);
+ pencil_free(ro_save_draw_diagram);
+ return false;
+ }
+ assert(drawfile_buffer);
+
+ error = xosfile_save_stamped(path, osfile_TYPE_DRAW,
+ (byte *) drawfile_buffer,
+ (byte *) drawfile_buffer + drawfile_size);
+ if (error) {
+ LOG("xosfile_save_stamped failed: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("SaveError", error->errmess);
+ pencil_free(ro_save_draw_diagram);
+ return false;
+ }
+
+ pencil_free(ro_save_draw_diagram);
+
+ return true;
+}
+
+bool ro_save_draw_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style)
+{
+ pencil_code code;
+ const int path[] = { draw_MOVE_TO, x0 * 2, -y0 * 2 - 1,
+ draw_LINE_TO, x1 * 2, -y0 * 2 - 1,
+ draw_LINE_TO, x1 * 2, -y1 * 2 - 1,
+ draw_LINE_TO, x0 * 2, -y1 * 2 - 1,
+ draw_CLOSE_LINE,
+ draw_END_PATH };
+
+ if (style->fill_type != PLOT_OP_TYPE_NONE) {
+
+ code = pencil_path(ro_save_draw_diagram,
+ path,
+ sizeof path / sizeof path[0],
+ style->fill_colour << 8,
+ pencil_TRANSPARENT,
+ 0,
+ pencil_JOIN_MITRED,
+ pencil_CAP_BUTT,
+ pencil_CAP_BUTT,
+ 0,
+ 0,
+ false,
+ pencil_SOLID);
+ if (code != pencil_OK)
+ return ro_save_draw_error(code);
+ }
+
+ if (style->stroke_type != PLOT_OP_TYPE_NONE) {
+
+ code = pencil_path(ro_save_draw_diagram,
+ path,
+ sizeof path / sizeof path[0],
+ pencil_TRANSPARENT,
+ style->stroke_colour << 8,
+ style->stroke_width,
+ pencil_JOIN_MITRED,
+ pencil_CAP_BUTT,
+ pencil_CAP_BUTT,
+ 0,
+ 0,
+ false,
+ pencil_SOLID);
+
+ if (code != pencil_OK)
+ return ro_save_draw_error(code);
+ }
+ return true;
+}
+
+
+bool ro_save_draw_line(int x0, int y0, int x1, int y1, const plot_style_t *style)
+{
+ pencil_code code;
+ const int path[] = { draw_MOVE_TO, x0 * 2, -y0 * 2 - 1,
+ draw_LINE_TO, x1 * 2, -y1 * 2 - 1,
+ draw_END_PATH };
+
+ code = pencil_path(ro_save_draw_diagram,
+ path,
+ sizeof path / sizeof path[0],
+ pencil_TRANSPARENT,
+ style->stroke_colour << 8,
+ style->stroke_width,
+ pencil_JOIN_MITRED,
+ pencil_CAP_BUTT,
+ pencil_CAP_BUTT,
+ 0, 0, false,
+ pencil_SOLID);
+ if (code != pencil_OK)
+ return ro_save_draw_error(code);
+
+ return true;
+}
+
+
+bool ro_save_draw_polygon(const int *p, unsigned int n, const plot_style_t *style)
+{
+ pencil_code code;
+ int path[n * 3 + 1];
+ unsigned int i;
+
+ for (i = 0; i != n; i++) {
+ path[i * 3 + 0] = draw_LINE_TO;
+ path[i * 3 + 1] = p[i * 2 + 0] * 2;
+ path[i * 3 + 2] = -p[i * 2 + 1] * 2;
+ }
+ path[0] = draw_MOVE_TO;
+ path[n * 3] = draw_END_PATH;
+
+ code = pencil_path(ro_save_draw_diagram,
+ path, n * 3 + 1,
+ style->fill_colour << 8,
+ pencil_TRANSPARENT,
+ 0,
+ pencil_JOIN_MITRED,
+ pencil_CAP_BUTT,
+ pencil_CAP_BUTT,
+ 0,
+ 0,
+ false,
+ pencil_SOLID);
+ if (code != pencil_OK)
+ return ro_save_draw_error(code);
+
+ return true;
+}
+
+
+bool ro_save_draw_path(const float *p, unsigned int n, colour fill,
+ float width, colour c, const float transform[6])
+{
+ if (n == 0)
+ return true;
+
+ if (p[0] != PLOTTER_PATH_MOVE) {
+ LOG("path doesn't start with a move");
+ return false;
+ }
+
+ int *path = malloc(sizeof *path * (n + 10));
+ if (!path) {
+ LOG("out of memory");
+ return false;
+ }
+
+ unsigned int i;
+ bool empty_path = true;
+ for (i = 0; i < n; ) {
+ if (p[i] == PLOTTER_PATH_MOVE) {
+ path[i] = draw_MOVE_TO;
+ path[i + 1] = (transform[0] * p[i + 1] +
+ transform[2] * -p[i + 2] +
+ transform[4]) * 2;
+ path[i + 2] = (transform[1] * p[i + 1] +
+ transform[3] * -p[i + 2] +
+ -transform[5]) * 2;
+ i += 3;
+ } else if (p[i] == PLOTTER_PATH_CLOSE) {
+ path[i] = draw_CLOSE_LINE;
+ i++;
+ } else if (p[i] == PLOTTER_PATH_LINE) {
+ path[i] = draw_LINE_TO;
+ path[i + 1] = (transform[0] * p[i + 1] +
+ transform[2] * -p[i + 2] +
+ transform[4]) * 2;
+ path[i + 2] = (transform[1] * p[i + 1] +
+ transform[3] * -p[i + 2] +
+ -transform[5]) * 2;
+ i += 3;
+ empty_path = false;
+ } else if (p[i] == PLOTTER_PATH_BEZIER) {
+ path[i] = draw_BEZIER_TO;
+ path[i + 1] = (transform[0] * p[i + 1] +
+ transform[2] * -p[i + 2] +
+ transform[4]) * 2;
+ path[i + 2] = (transform[1] * p[i + 1] +
+ transform[3] * -p[i + 2] +
+ -transform[5]) * 2;
+ path[i + 3] = (transform[0] * p[i + 3] +
+ transform[2] * -p[i + 4] +
+ transform[4]) * 2;
+ path[i + 4] = (transform[1] * p[i + 3] +
+ transform[3] * -p[i + 4] +
+ -transform[5]) * 2;
+ path[i + 5] = (transform[0] * p[i + 5] +
+ transform[2] * -p[i + 6] +
+ transform[4]) * 2;
+ path[i + 6] = (transform[1] * p[i + 5] +
+ transform[3] * -p[i + 6] +
+ -transform[5]) * 2;
+ i += 7;
+ empty_path = false;
+ } else {
+ LOG("bad path command %f", p[i]);
+ free(path);
+ return false;
+ }
+ }
+ path[i] = draw_END_PATH;
+
+ if (empty_path) {
+ free(path);
+ return true;
+ }
+
+ pencil_code code = pencil_path(ro_save_draw_diagram, path, i + 1,
+ fill == NS_TRANSPARENT ? pencil_TRANSPARENT : fill << 8,
+ c == NS_TRANSPARENT ? pencil_TRANSPARENT : c << 8,
+ width, pencil_JOIN_MITRED,
+ pencil_CAP_BUTT, pencil_CAP_BUTT, 0, 0, false,
+ pencil_SOLID);
+ free(path);
+ if (code != pencil_OK)
+ return ro_save_draw_error(code);
+
+ return true;
+}
+
+
+
+
+bool ro_save_draw_clip(const struct rect *clip)
+{
+ return true;
+}
+
+
+bool ro_save_draw_text(int x, int y, const char *text, size_t length,
+ const plot_font_style_t *fstyle)
+{
+ pencil_code code;
+ const char *font_family;
+ unsigned int font_size;
+ rufl_style font_style;
+
+ nsfont_read_style(fstyle, &font_family, &font_size, &font_style);
+
+ code = pencil_text(ro_save_draw_diagram, x * 2, -y * 2, font_family,
+ font_style, font_size, text, length,
+ fstyle->foreground << 8);
+ if (code != pencil_OK)
+ return ro_save_draw_error(code);
+
+ return true;
+}
+
+
+bool ro_save_draw_disc(int x, int y, int radius, const plot_style_t *style)
+{
+ return true;
+}
+
+bool ro_save_draw_arc(int x, int y, int radius, int angle1, int angle2,
+ const plot_style_t *style)
+{
+ return true;
+}
+
+bool ro_save_draw_bitmap(int x, int y, int width, int height,
+ struct bitmap *bitmap, colour bg, bitmap_flags_t flags)
+{
+ pencil_code code;
+ const uint8_t *buffer;
+
+ buffer = riscos_bitmap_get_buffer(bitmap);
+ if (!buffer) {
+ ro_warn_user("NoMemory", 0);
+ return false;
+ }
+
+ code = pencil_sprite(ro_save_draw_diagram, x * 2, (-y - height) * 2,
+ width * 2, height * 2,
+ ((char *) bitmap->sprite_area) +
+ bitmap->sprite_area->first);
+ if (code != pencil_OK)
+ return ro_save_draw_error(code);
+
+ return true;
+}
+
+
+bool ro_save_draw_group_start(const char *name)
+{
+ pencil_code code;
+
+ code = pencil_group_start(ro_save_draw_diagram, name);
+ if (code != pencil_OK)
+ return ro_save_draw_error(code);
+
+ return true;
+}
+
+
+bool ro_save_draw_group_end(void)
+{
+ pencil_code code;
+
+ code = pencil_group_end(ro_save_draw_diagram);
+ if (code != pencil_OK)
+ return ro_save_draw_error(code);
+
+ return true;
+}
+
+
+/**
+ * Report an error from pencil.
+ *
+ * \param code error code
+ * \return false
+ */
+
+bool ro_save_draw_error(pencil_code code)
+{
+ LOG("code %i", code);
+
+ switch (code) {
+ case pencil_OK:
+ assert(0);
+ break;
+ case pencil_OUT_OF_MEMORY:
+ ro_warn_user("NoMemory", 0);
+ break;
+ case pencil_FONT_MANAGER_ERROR:
+ ro_warn_user("SaveError", rufl_fm_error->errmess);
+ break;
+ case pencil_FONT_NOT_FOUND:
+ case pencil_IO_ERROR:
+ case pencil_IO_EOF:
+ ro_warn_user("SaveError", "generating the DrawFile failed");
+ break;
+ }
+
+ return false;
+}
+
+#endif
diff --git a/frontends/riscos/save_draw.h b/frontends/riscos/save_draw.h
new file mode 100644
index 000000000..7ae447790
--- /dev/null
+++ b/frontends/riscos/save_draw.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2004 John M Bell <jmb202@ecs.soton.ac.uk>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _NETSURF_RISCOS_SAVE_DRAW_H_
+#define _NETSURF_RISCOS_SAVE_DRAW_H_
+
+#ifdef WITH_DRAW_EXPORT
+
+#include <stdbool.h>
+struct hlcache_handle;
+
+bool save_as_draw(struct hlcache_handle *h, const char *path);
+
+#endif
+
+#endif
diff --git a/frontends/riscos/save_pdf.c b/frontends/riscos/save_pdf.c
new file mode 100644
index 000000000..3d6395629
--- /dev/null
+++ b/frontends/riscos/save_pdf.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2008 John Tytgat <joty@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Export a content as a PDF file (implementation).
+ */
+
+#include "utils/config.h"
+#ifdef WITH_PDF_EXPORT
+
+#include <stdbool.h>
+#include "oslib/osfile.h"
+#include "content/content.h"
+#include "content/hlcache.h"
+#include "desktop/print.h"
+#include "desktop/save_pdf/font_haru.h"
+#include "desktop/save_pdf/pdf_plotters.h"
+#include "riscos/save_pdf.h"
+#include "utils/log.h"
+#include "utils/config.h"
+
+/**
+ * Export a content as a PDF file.
+ *
+ * \param h content to export
+ * \param path path to save PDF as
+ * \return true on success, false on error and error reported
+ */
+bool save_as_pdf(hlcache_handle *h, const char *path)
+{
+ struct print_settings *psettings;
+
+ psettings = print_make_settings(PRINT_DEFAULT, path, &haru_nsfont);
+ if (psettings == NULL)
+ return false;
+
+ if (!print_basic_run(h, &pdf_printer, psettings))
+ return false;
+
+ xosfile_set_type(path, 0xadf);
+
+ return true;
+}
+
+#endif
diff --git a/frontends/riscos/save_pdf.h b/frontends/riscos/save_pdf.h
new file mode 100644
index 000000000..ad4599dea
--- /dev/null
+++ b/frontends/riscos/save_pdf.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2008 John Tytgat <joty@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _NETSURF_RISCOS_SAVE_PDF_H_
+#define _NETSURF_RISCOS_SAVE_PDF_H_
+
+#include "utils/config.h"
+#ifdef WITH_PDF_EXPORT
+
+struct hlcache_handle;
+
+bool save_as_pdf(struct hlcache_handle *h, const char *path);
+
+#endif /* WITH_PDF_EXPORT */
+
+#endif
diff --git a/frontends/riscos/schedule.c b/frontends/riscos/schedule.c
new file mode 100644
index 000000000..54308b7a9
--- /dev/null
+++ b/frontends/riscos/schedule.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2004 James Bursa <bursa@users.sourceforge.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Scheduled callback queue (implementation).
+ *
+ * The queue is simply implemented as a linked list.
+ */
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include "oslib/os.h"
+#include "utils/log.h"
+
+#include "riscos/gui.h"
+
+
+/** Entry in the queue of scheduled callbacks. */
+struct sched_entry {
+ /** Preferred time for callback. */
+ os_t time;
+ /** Function to call at the specified time. */
+ void (*callback)(void *p);
+ /** User parameter for callback. */
+ void *p;
+ /** Next (later) entry in queue. */
+ struct sched_entry *next;
+};
+
+/** Queue of scheduled callbacks (sentinel at head). */
+static struct sched_entry sched_queue = { 0, 0, 0, 0 };
+
+/** Items have been scheduled. */
+bool sched_active = false;
+/** Time of soonest scheduled event (valid only if sched_active is true). */
+os_t sched_time;
+
+/**
+ * Unschedule a callback.
+ *
+ * \param callback callback function
+ * \param p user parameter, passed to callback function
+ *
+ * All scheduled callbacks matching both callback and p are removed.
+ */
+
+static nserror schedule_remove(void (*callback)(void *p), void *p)
+{
+ struct sched_entry *entry, *prev;
+
+ prev = &sched_queue;
+
+ for (entry = prev->next; entry; entry = prev->next) {
+ if (entry->callback != callback || entry->p != p) {
+ prev = entry;
+ continue;
+ }
+
+ prev->next = entry->next;
+ free(entry);
+
+ /* There can only ever be one match, and we've found it */
+ break;
+ }
+
+ if (sched_queue.next) {
+ sched_active = true;
+ sched_time = sched_queue.next->time;
+ } else {
+ sched_active = false;
+ }
+
+ return NSERROR_OK;
+}
+
+/* exported function documented in riscos/gui.h */
+nserror riscos_schedule(int t, void (*callback)(void *p), void *p)
+{
+ struct sched_entry *entry;
+ struct sched_entry *queue;
+ os_t time;
+ nserror ret;
+
+ ret = schedule_remove(callback, p);
+ if ((t < 0) || (ret != NSERROR_OK)) {
+ return ret;
+ }
+
+ t = t / 10; /* convert to centiseconds */
+
+ time = os_read_monotonic_time() + t;
+
+ entry = malloc(sizeof *entry);
+ if (!entry) {
+ LOG("malloc failed");
+ return NSERROR_NOMEM;
+ }
+
+ entry->time = time;
+ entry->callback = callback;
+ entry->p = p;
+
+ for (queue = &sched_queue;
+ queue->next && queue->next->time <= time;
+ queue = queue->next)
+ ;
+ entry->next = queue->next;
+ queue->next = entry;
+
+ sched_active = true;
+ sched_time = sched_queue.next->time;
+
+ return NSERROR_OK;
+}
+
+
+/* exported function documented in riscos/gui.h */
+bool schedule_run(void)
+{
+ struct sched_entry *entry;
+ os_t now;
+
+ now = os_read_monotonic_time();
+
+ while (sched_queue.next && sched_queue.next->time <= now) {
+ void (*callback)(void *p);
+ void *p;
+
+ entry = sched_queue.next;
+ callback = entry->callback;
+ p = entry->p;
+ sched_queue.next = entry->next;
+ free(entry);
+ /* The callback may call riscos_schedule(), so leave
+ * the queue in a safe state.
+ */
+ callback(p);
+ }
+
+ if (sched_queue.next) {
+ sched_active = true;
+ sched_time = sched_queue.next->time;
+ } else
+ sched_active = false;
+
+ return sched_active;
+}
diff --git a/frontends/riscos/scripts/Help b/frontends/riscos/scripts/Help
new file mode 100644
index 000000000..9116926a3
--- /dev/null
+++ b/frontends/riscos/scripts/Help
@@ -0,0 +1,12 @@
+| Help file for NetSurf. ( $Revision$ )
+
+| Set system variables and application sprites
+Set NetSurf$ForceVars 1
+/<Obey$Dir>.!Boot
+UnSet NetSurf$ForceVars
+
+| Resource Locations
+SetMacro NetSurf$Path Choices:WWW.NetSurf.,<NetSurf$Dir>.
+
+WimpSlot -min 8k -max 8k
+Run <NetSurf$Dir>.OpenHelp
diff --git a/frontends/riscos/scripts/Run b/frontends/riscos/scripts/Run
new file mode 100644
index 000000000..4a51d7838
--- /dev/null
+++ b/frontends/riscos/scripts/Run
@@ -0,0 +1,109 @@
+| Run file for NetSurf.
+|
+| This file ensures that the system resources required by NetSurf are
+| present. Additionally, it forces setting of system variables related
+| to NetSurf.
+
+| Set system variables and application sprites
+Set NetSurf$ForceVars 1
+/<Obey$Dir>.!Boot
+UnSet NetSurf$ForceVars
+
+| Configure logging. Set 1 to enable, or 0 to suppress.
+Set NetSurf$Logging 1
+
+| Detect if NetSurf is already running and, if so, force the
+| current instance to open a new window. Then stop this script.
+Set Alias$NetSurfRunning UnSet Alias$NetSurfRunning|mUnSet NetSurf$Running|mObey
+Set NetSurf$Running 0
+WimpSlot -min 64k -max 64k
+/<NetSurf$Dir>.KickNS
+| If not running, then unset system variables and continue
+If "<NetSurf$Running>" = "0" Then Set Alias$NetSurfRunning UnSet Alias$NetSurfRunning|mUnSet NetSurf$Running
+| Invoke our alias to clean up
+NetSurfRunning
+
+| Resource Locations
+| The following are read-only locations
+SetMacro NetSurf$Path Choices:WWW.NetSurf.,<NetSurf$Dir>.
+| The following are write-only locations
+SetMacro NetSurf$ChoicesSave <Choices$Write>.WWW.NetSurf.Choices
+
+| We need RISC OS 3
+RMEnsure UtilityModule 3.00 Error NetSurf needs RISC OS 3 or later
+
+| Ensure Nested WIMP is installed
+| http://acorn.riscos.com/ (in the universal boot archive)
+RMEnsure WindowManager 3.80 Error NetSurf requires the Nested Window Manager. This can be obtained by downloading the Universal Boot sequence from http://acorn.riscos.com/
+
+| Check for various key resources - can't do much if they don't exist
+If "<System$Path>" = "" Then Set System$Path_Message System resources not found.
+If "<Wimp$ScrapDir>" = "" Then Error Scrap resource not found.
+If "<InetDBase$Path>" = "" Then Error Internet resources can not be found
+If "<Unicode$Path>" = "" Then Error NetSurf requires the !Unicode resource. This can be found, along with the Iconv module, at http://www.netsurf-browser.org/projects/iconv/
+If "<Inet$MimeMappings>" = "" Then Set Inet$MimeMappings InetDBase:MimeMap
+
+| Define this alias for clarity
+| Syntax: NetSurfRMLoad <Path to module>
+Set Alias$NetSurfRMLoad IfThere %%*0 Then RMLoad %%*0
+
+| Ensure a 32bit SharedCLibrary is installed
+| (5.17 == first 32bit SCL, 5.43 == C99 features)
+RMEnsure SharedCLibrary 5.17 NetSurfRMLoad System:Modules.CLib
+RMEnsure SharedCLibrary 5.43 Error NetSurf requires SharedCLibrary 5.43 or later. This can be downloaded from https://www.riscosopen.org/content/downloads/common
+
+| Ensure CallASWI is installed
+RMEnsure UtilityModule 3.70 RMEnsure CallASWI 0.02 NetSurfRMLoad System:Modules.CallASWI
+RMEnsure UtilityModule 3.70 RMEnsure CallASWI 0.02 Error NetSurf requires the CallASWI module. This can be downloaded from https://www.riscosopen.org/content/downloads/common
+
+| Ensure DrawFile module is installed
+| Should be installed in !System.310.Modules
+RMEnsure DrawFile 1.30 NetSurfRMLoad System:Modules.DrawFile
+RMEnsure DrawFile 1.30 Error NetSurf requires the DrawFile module. This can be downloaded from https://www.riscosopen.org/content/downloads/common
+
+| Ensure SharedUnixLibrary is installed
+RMEnsure SharedUnixLibrary 1.07 NetSurfRMLoad System:Modules.SharedULib
+RMEnsure SharedUnixLibrary 1.07 Error NetSurf requires SharedUnixLibrary 1.07 or later. Please use the RISC OS Configure app to update the computer's !System directory from the NetSurf archive.
+
+| Load AcornURI if it isn't already
+Unset NetSurf$Start_URI_Handler
+RMEnsure AcornURI 0.12 Set NetSurf$Start_URI_Handler 1
+RMEnsure AcornURI 0.12 NetSurfRMLoad System:Modules.Network.URI
+RMEnsure AcornURI 0.12 Error NetSurf requires AcornURI 0.12 or later. Please use the RISC OS Configure app to update the computer's !System directory from the NetSurf archive.
+RMEnsure AcornURI 0.12 Unset NetSurf$Start_URI_Handler
+
+| Check for mime map module
+RMEnsure MimeMap 0.10 NetSurfRMLoad System:Modules.Network.MimeMap
+RMEnsure MimeMap 0.10 Error NetSurf requires MimeMap 0.10 or later
+
+| Ensure Tinct is loaded
+RMEnsure Tinct 0.13 NetSurfRMLoad System:Modules.Tinct
+RMEnsure Tinct 0.13 Error NetSurf requires Tinct 0.13 or later. Please use the RISC OS Configure app to update the computer's !System directory from the NetSurf archive.
+
+| Ensure Iconv
+RMEnsure Iconv 0.12 NetSurfRMLoad System:Modules.Iconv
+RMEnsure Iconv 0.12 Error NetSurf requires Iconv 0.12 or later. Please use the RISC OS Configure app to update the computer's !System directory from the NetSurf archive.
+
+| Ensure CryptRandom
+RMEnsure CryptRandom 0.13 NetSurfRMLoad System:Modules.CryptRand
+RMEnsure CryptRandom 0.13 Error NetSurf requires CryptRandom 0.13 or later. Please use the RISC OS Configure app to update the computer's !System directory from the NetSurf archive.
+
+| Disable SpecialFX, if present
+Set NetSurf$SpecialFX 1
+RMEnsure SpecialFX 1.00 Set NetSurf$SpecialFX 0
+If <NetSurf$SpecialFX> Then SpecialFX ~B~G~L NetSurf
+Unset NetSurf$SpecialFX
+
+| No longer need this alias
+Unset Alias$NetSurfRMLoad
+
+| Now attempt to create Scrap directories
+CDir <Wimp$ScrapDir>.WWW
+CDir <Wimp$ScrapDir>.WWW.NetSurf
+
+| Install NetSurf-specific fonts
+| NB: trailing dot is required
+FontInstall NetSurf:Resources.Fonts.
+
+WIMPSLOT
+Run <NetSurf$Dir>.!RunImage %*0 2><Wimp$ScrapDir>.WWW.NetSurf.Log
diff --git a/frontends/riscos/search.c b/frontends/riscos/search.c
new file mode 100644
index 000000000..989c9aa9e
--- /dev/null
+++ b/frontends/riscos/search.c
@@ -0,0 +1,475 @@
+/*
+ * Copyright 2004 John M Bell <jmb202@ecs.soton.ac.uk>
+ * Copyright 2005 Adrian Lees <adrianl@users.sourceforge.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Free text search implementation
+ */
+
+#include "utils/config.h"
+
+#include <ctype.h>
+#include <string.h>
+#include "oslib/hourglass.h"
+#include "oslib/wimp.h"
+
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "content/content.h"
+#include "content/hlcache.h"
+#include "desktop/browser.h"
+#include "desktop/gui_search.h"
+#include "desktop/browser.h"
+#include "desktop/search.h"
+
+#include "riscos/gui.h"
+#include "riscos/dialog.h"
+#include "riscos/menus.h"
+#include "riscos/wimp.h"
+#include "riscos/wimp_event.h"
+
+#define RECENT_SEARCHES 8
+
+struct search_static_data {
+ char *recent_searches[RECENT_SEARCHES];
+ bool search_insert;
+ struct browser_window *search_window;
+};
+
+static struct search_static_data search_data =
+ { { NULL }, false, NULL };
+
+static wimp_MENU(RECENT_SEARCHES) menu_recent;
+wimp_menu *recent_search_menu = (wimp_menu *)&menu_recent;
+#define DEFAULT_FLAGS (wimp_ICON_TEXT | wimp_ICON_FILLED | \
+ (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) | \
+ (wimp_COLOUR_WHITE << wimp_ICON_BG_COLOUR_SHIFT))
+
+
+static void ro_gui_search_end(wimp_w w);
+static bool ro_gui_search_next(wimp_w w);
+static bool ro_gui_search_menu_prepare(wimp_w w, wimp_i i, wimp_menu *menu,
+ wimp_pointer *pointer);
+static bool ro_gui_search_prepare_menu(void);
+static bool ro_gui_search_click(wimp_pointer *pointer);
+static bool ro_gui_search_keypress(wimp_key *key);
+static search_flags_t ro_gui_search_update_flags(void);
+static void ro_gui_search_set_forward_state(bool active, void *p);
+static void ro_gui_search_set_back_state(bool active, void *p);
+static void ro_gui_search_set_status(bool found, void *p);
+static void ro_gui_search_set_hourglass(bool active, void *p);
+static void ro_gui_search_add_recent(const char *string, void *p);
+
+static struct gui_search_table search_table = {
+ ro_gui_search_set_status,
+ ro_gui_search_set_hourglass,
+ ro_gui_search_add_recent,
+ ro_gui_search_set_forward_state,
+ ro_gui_search_set_back_state,
+};
+
+struct gui_search_table *riscos_search_table = &search_table;
+
+void ro_gui_search_init(void)
+{
+ dialog_search = ro_gui_dialog_create("search");
+ ro_gui_wimp_event_register_keypress(dialog_search,
+ ro_gui_search_keypress);
+ ro_gui_wimp_event_register_close_window(dialog_search,
+ ro_gui_search_end);
+ ro_gui_wimp_event_register_menu_prepare(dialog_search,
+ ro_gui_search_menu_prepare);
+ ro_gui_wimp_event_register_menu_gright(dialog_search,
+ ICON_SEARCH_TEXT, ICON_SEARCH_MENU,
+ recent_search_menu);
+ ro_gui_wimp_event_register_text_field(dialog_search,
+ ICON_SEARCH_STATUS);
+ ro_gui_wimp_event_register_checkbox(dialog_search,
+ ICON_SEARCH_CASE_SENSITIVE);
+ ro_gui_wimp_event_register_mouse_click(dialog_search,
+ ro_gui_search_click);
+ ro_gui_wimp_event_register_ok(dialog_search, ICON_SEARCH_FIND_NEXT,
+ ro_gui_search_next);
+ ro_gui_wimp_event_register_cancel(dialog_search, ICON_SEARCH_CANCEL);
+ ro_gui_wimp_event_set_help_prefix(dialog_search, "HelpSearch");
+
+ recent_search_menu->title_data.indirected_text.text =
+ (char*)messages_get("Search");
+ ro_gui_menu_init_structure(recent_search_menu, RECENT_SEARCHES);
+}
+
+/**
+ * Wrapper for the pressing of an OK button for wimp_event.
+ *
+ * \return false, to indicate the window should not be closed
+ */
+bool ro_gui_search_next(wimp_w w)
+{
+ search_data.search_insert = true;
+ search_flags_t flags = SEARCH_FLAG_FORWARDS |
+ ro_gui_search_update_flags();
+ browser_window_search(search_data.search_window, NULL, flags,
+ ro_gui_get_icon_string(dialog_search,
+ ICON_SEARCH_TEXT));
+ return false;
+}
+
+
+/**
+ * Callback to prepare menus in the Search dialog. At present, this
+ * only has to handle the previous search pop-up.
+ *
+ * \param w The window handle owning the menu.
+ * \param i The icon handle owning the menu.
+ * \param *menu The menu to be prepared.
+ * \param *pointer The associated mouse click event block, or NULL
+ * on an Adjust-click re-opening.
+ * \return true if the event was handled; false if not.
+ */
+
+bool ro_gui_search_menu_prepare(wimp_w w, wimp_i i, wimp_menu *menu,
+ wimp_pointer *pointer)
+{
+ if (menu != recent_search_menu || i != ICON_SEARCH_MENU)
+ return false;
+
+ if (pointer != NULL)
+ return ro_gui_search_prepare_menu();
+
+ return true;
+}
+
+
+bool ro_gui_search_click(wimp_pointer *pointer)
+{
+ search_flags_t flags;
+ switch (pointer->i) {
+ case ICON_SEARCH_FIND_PREV:
+ search_data.search_insert = true;
+ flags = ~SEARCH_FLAG_FORWARDS &
+ ro_gui_search_update_flags();
+ browser_window_search(search_data.search_window, NULL,
+ flags,
+ ro_gui_get_icon_string(dialog_search,
+ ICON_SEARCH_TEXT));
+ return true;
+ case ICON_SEARCH_CASE_SENSITIVE:
+ flags = SEARCH_FLAG_FORWARDS |
+ ro_gui_search_update_flags();
+ browser_window_search_clear(
+ search_data.search_window);
+ browser_window_search(search_data.search_window, NULL,
+ flags,
+ ro_gui_get_icon_string(dialog_search,
+ ICON_SEARCH_TEXT));
+ return true;
+ case ICON_SEARCH_SHOW_ALL:
+ flags = ro_gui_get_icon_selected_state(
+ pointer->w, pointer->i) ?
+ SEARCH_FLAG_SHOWALL : SEARCH_FLAG_NONE;
+ browser_window_search(search_data.search_window, NULL,
+ flags,
+ ro_gui_get_icon_string(dialog_search,
+ ICON_SEARCH_TEXT));
+ return true;
+ }
+ return false;
+}
+
+/**
+ * add search string to recent searches list
+ *
+ * front is at liberty how to implement the bare notification
+ * should normally store a strdup() of the string in
+ * search_global_data.recent[];
+ * core gives no guarantee of the integrity of the const char *
+ *
+ * \param search string search pattern
+ * \param p the pointer sent to search_verify_new()
+ */
+
+void ro_gui_search_add_recent(const char *search, void *p)
+{
+ char *tmp;
+ int i;
+
+ if ((search == NULL) || (search[0] == '\0'))
+ return;
+
+ if (!search_data.search_insert) {
+ free(search_data.recent_searches[0]);
+ search_data.recent_searches[0] = strdup(search);
+ ro_gui_search_prepare_menu();
+ return;
+ }
+
+ if ((search_data.recent_searches[0] != NULL) &&
+ (!strcmp(search_data.recent_searches[0], search)))
+ return;
+
+ tmp = strdup(search);
+ if (!tmp) {
+ ro_warn_user("NoMemory", 0);
+ return;
+ }
+ free(search_data.recent_searches[RECENT_SEARCHES - 1]);
+ for (i = RECENT_SEARCHES - 1; i > 0; i--)
+ search_data.recent_searches[i] = search_data.recent_searches[i - 1];
+ search_data.recent_searches[0] = tmp;
+ search_data.search_insert = false;
+
+ ro_gui_set_icon_shaded_state(dialog_search, ICON_SEARCH_MENU, false);
+ ro_gui_search_prepare_menu();
+}
+
+bool ro_gui_search_prepare_menu(void)
+{
+ int i;
+ int suggestions = 0;
+
+ for (i = 0; i < RECENT_SEARCHES; i++)
+ if (search_data.recent_searches[i] != NULL)
+ suggestions++;
+
+ if (suggestions == 0)
+ return false;
+
+ for (i = 0; i < suggestions; i++) {
+ recent_search_menu->entries[i].menu_flags &= ~wimp_MENU_LAST;
+ recent_search_menu->entries[i].data.indirected_text.text =
+ search_data.recent_searches[i];
+ recent_search_menu->entries[i].data.indirected_text.size =
+ strlen(search_data.recent_searches[i]) + 1;
+ }
+ recent_search_menu->entries[suggestions - 1].menu_flags |=
+ wimp_MENU_LAST;
+
+ return true;
+}
+
+/**
+ * Determine of the browser window is searchable.
+ *
+ * \param bw The browser window to check.
+ */
+static bool ro_gui_search_bw_searchable(struct browser_window *bw)
+{
+ hlcache_handle *h;
+
+ assert(bw != NULL);
+
+ h = browser_window_get_content(bw);
+
+ /* only handle html/textplain contents */
+ /** \todo Should have content_is_searchable() api */
+ if ((!h) || (content_get_type(h) != CONTENT_HTML &&
+ content_get_type(h) != CONTENT_TEXTPLAIN))
+ return false;
+
+ return true;
+}
+
+
+/**
+ * Open the search dialog
+ *
+ * \param bw the browser window to search
+ */
+void ro_gui_search_prepare(struct browser_window *bw)
+{
+ /* only handle searchable contents */
+ if (!ro_gui_search_bw_searchable(bw))
+ return;
+
+ /* if the search dialogue is reopened over a new window, we may
+ need to cancel the previous search */
+ ro_gui_search_set_forward_state(true, bw);
+ ro_gui_search_set_back_state(true, bw);
+
+ search_data.search_window = bw;
+
+ ro_gui_set_icon_string(dialog_search, ICON_SEARCH_TEXT, "", true);
+ ro_gui_set_icon_selected_state(dialog_search,
+ ICON_SEARCH_CASE_SENSITIVE, false);
+ ro_gui_set_icon_selected_state(dialog_search,
+ ICON_SEARCH_SHOW_ALL, false);
+
+ ro_gui_search_set_status(true, NULL);
+
+ ro_gui_wimp_event_memorise(dialog_search);
+ search_data.search_insert = true;
+}
+
+/**
+ * Handle keypresses in the search dialog
+ *
+ * \param key wimp_key block
+ * \return true if keypress handled, false otherwise
+ */
+bool ro_gui_search_keypress(wimp_key *key)
+{
+ bool state;
+ search_flags_t flags;
+
+ switch (key->c) {
+ case 1: {
+ flags = ro_gui_search_update_flags()
+ ^ SEARCH_FLAG_SHOWALL;
+ browser_window_search(search_data.search_window, NULL,
+ flags,
+ ro_gui_get_icon_string(dialog_search,
+ ICON_SEARCH_TEXT));
+ }
+ break;
+ case 9: /* ctrl i */
+ state = ro_gui_get_icon_selected_state(dialog_search,
+ ICON_SEARCH_CASE_SENSITIVE);
+ ro_gui_set_icon_selected_state(dialog_search,
+ ICON_SEARCH_CASE_SENSITIVE, !state);
+ flags = SEARCH_FLAG_FORWARDS |
+ ro_gui_search_update_flags();
+ browser_window_search(search_data.search_window, NULL,
+ flags,
+ ro_gui_get_icon_string(dialog_search,
+ ICON_SEARCH_TEXT));
+ return true;
+ case IS_WIMP_KEY | wimp_KEY_UP:
+ search_data.search_insert = true;
+ flags = ~SEARCH_FLAG_FORWARDS &
+ ro_gui_search_update_flags();
+ browser_window_search(search_data.search_window, NULL,
+ flags,
+ ro_gui_get_icon_string(dialog_search,
+ ICON_SEARCH_TEXT));
+ return true;
+ case IS_WIMP_KEY | wimp_KEY_DOWN:
+ search_data.search_insert = true;
+ flags = SEARCH_FLAG_FORWARDS |
+ ro_gui_search_update_flags();
+ browser_window_search(search_data.search_window, NULL,
+ flags,
+ ro_gui_get_icon_string(dialog_search,
+ ICON_SEARCH_TEXT));
+ return true;
+
+ default:
+ if (key->c == 21) {
+ /* ctrl+u means the user's starting
+ * a new search */
+ browser_window_search_clear(
+ search_data.search_window);
+ search_data.search_insert = true;
+ }
+ if (key->c == 8 || /* backspace */
+ key->c == 21 || /* ctrl u */
+ (key->c >= 0x20 && key->c <= 0x7f)) {
+ flags = SEARCH_FLAG_FORWARDS |
+ ro_gui_search_update_flags();
+ ro_gui_search_set_forward_state(true,
+ search_data.search_window);
+ ro_gui_search_set_back_state(true,
+ search_data.search_window);
+ browser_window_search(search_data.search_window,
+ NULL,
+ flags,
+ ro_gui_get_icon_string(
+ dialog_search,
+ ICON_SEARCH_TEXT));
+ return true;
+ }
+ break;
+ }
+
+ return false;
+}
+
+/**
+ * Ends the search
+ * \param w the search window handle (not used)
+ */
+void ro_gui_search_end(wimp_w w)
+{
+ browser_window_search_clear(search_data.search_window);
+}
+
+/**
+* Change the displayed search status.
+* \param found search pattern matched in text
+* \param p the pointer sent to search_verify_new() / search_create_context()
+*/
+
+void ro_gui_search_set_status(bool found, void *p)
+{
+ ro_gui_set_icon_string(dialog_search, ICON_SEARCH_STATUS, found ? "" :
+ messages_get("NotFound"), true);
+}
+
+/**
+* display hourglass while searching
+* \param active start/stop indicator
+* \param p the pointer sent to search_verify_new() / search_create_context()
+*/
+
+void ro_gui_search_set_hourglass(bool active, void *p)
+{
+ if (active)
+ xhourglass_on();
+
+ else
+ xhourglass_off();
+}
+
+/**
+* activate search forwards button in gui
+* \param active activate/inactivate
+* \param p the pointer sent to search_verify_new() / search_create_context()
+*/
+
+void ro_gui_search_set_forward_state(bool active, void *p)
+{
+ ro_gui_set_icon_shaded_state(dialog_search, ICON_SEARCH_FIND_NEXT,
+ !active);
+}
+
+/**
+* activate search forwards button in gui
+* \param active activate/inactivate
+* \param p the pointer sent to search_verify_new() / search_create_context()
+*/
+
+void ro_gui_search_set_back_state(bool active, void *p)
+{
+ ro_gui_set_icon_shaded_state(dialog_search, ICON_SEARCH_FIND_PREV,
+ !active);
+}
+
+/**
+* retrieve state of 'case sensitive', 'show all' checks in gui
+*/
+search_flags_t ro_gui_search_update_flags(void)
+{
+ search_flags_t flags;
+ flags = 0 | (ro_gui_get_icon_selected_state(dialog_search,
+ ICON_SEARCH_CASE_SENSITIVE) ?
+ SEARCH_FLAG_CASE_SENSITIVE : 0) |
+ (ro_gui_get_icon_selected_state(dialog_search,
+ ICON_SEARCH_SHOW_ALL) ? SEARCH_FLAG_SHOWALL : 0);
+ return flags;
+}
+
diff --git a/frontends/riscos/searchweb.c b/frontends/riscos/searchweb.c
new file mode 100644
index 000000000..14246d228
--- /dev/null
+++ b/frontends/riscos/searchweb.c
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
diff --git a/frontends/riscos/sslcert.c b/frontends/riscos/sslcert.c
new file mode 100644
index 000000000..9e43f2db1
--- /dev/null
+++ b/frontends/riscos/sslcert.c
@@ -0,0 +1,348 @@
+/*
+ * Copyright 2006 John M Bell <jmb202@ecs.soton.ac.uk>
+ * Copyright 2010 Stephen Fryatt <stevef@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * SSL Certificate verification UI (implementation)
+ */
+
+#include "utils/config.h"
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include "oslib/wimp.h"
+
+#include "utils/log.h"
+#include "content/content.h"
+#include "content/hlcache.h"
+#include "content/fetch.h"
+#include "content/urldb.h"
+#include "desktop/browser.h"
+#include "desktop/sslcert_viewer.h"
+#include "desktop/tree.h"
+
+#include "riscos/dialog.h"
+#include "riscos/sslcert.h"
+#include "riscos/textarea.h"
+#include "riscos/treeview.h"
+#include "riscos/wimp.h"
+#include "riscos/wimp_event.h"
+#include "riscos/wimputils.h"
+#include "riscos/gui.h"
+
+#define ICON_SSL_PANE 1
+#define ICON_SSL_REJECT 3
+#define ICON_SSL_ACCEPT 4
+
+static wimp_window *ro_gui_cert_dialog_template;
+static wimp_window *ro_gui_cert_tree_template;
+
+struct ro_sslcert
+{
+ wimp_w window;
+ wimp_w pane;
+ ro_treeview *tv;
+ struct sslcert_session_data *data;
+};
+
+static void ro_gui_cert_accept(wimp_pointer *pointer);
+static void ro_gui_cert_reject(wimp_pointer *pointer);
+static void ro_gui_cert_close_window(wimp_w w);
+static void ro_gui_cert_release_window(struct ro_sslcert *s);
+
+/**
+ * Load and initialise the certificate window template
+ */
+
+void ro_gui_cert_preinitialise(void)
+{
+ /* Load templates for the SSL windows and adjust the tree window
+ * flags to suit.
+ */
+
+ ro_gui_cert_dialog_template = ro_gui_dialog_load_template("sslcert");
+ ro_gui_cert_tree_template = ro_gui_dialog_load_template("tree");
+
+ ro_gui_cert_tree_template->flags &= ~(wimp_WINDOW_MOVEABLE |
+ wimp_WINDOW_BACK_ICON |
+ wimp_WINDOW_CLOSE_ICON |
+ wimp_WINDOW_TITLE_ICON |
+ wimp_WINDOW_SIZE_ICON |
+ wimp_WINDOW_TOGGLE_ICON);
+}
+
+/**
+ * Load and initialise the certificate window template
+ */
+
+void ro_gui_cert_postinitialise(void)
+{
+ /* Initialise the SSL module. */
+}
+
+/**
+ * Prompt the user to verify a certificate with issuse.
+ *
+ * \param url The URL being verified.
+ * \param certs The certificate to be verified
+ * \param num The number of certificates to be verified.
+ * \param cb Callback upon user decision.
+ * \param cbpw Context pointer passed to cb
+ */
+void gui_cert_verify(nsurl *url,
+ const struct ssl_cert_info *certs, unsigned long num,
+ nserror (*cb)(bool proceed, void *pw), void *cbpw)
+{
+ struct ro_sslcert *sslcert_window;
+ wimp_window_state state;
+ wimp_icon_state istate;
+ wimp_window_info info;
+ os_error *error;
+ bool set_extent;
+
+ assert(certs);
+
+ sslcert_window = malloc(sizeof(struct ro_sslcert));
+ if (sslcert_window == NULL) {
+ LOG("Failed to allocate memory for SSL Cert Dialog");
+ return;
+ }
+
+ /* Create the SSL window and its pane. */
+
+ error = xwimp_create_window(ro_gui_cert_dialog_template,
+ &(sslcert_window->window));
+ if (error) {
+ LOG("xwimp_create_window: 0x%x: %s", error->errnum, error->errmess);
+ free(sslcert_window);
+ return;
+ }
+
+ error = xwimp_create_window(ro_gui_cert_tree_template,
+ &(sslcert_window->pane));
+ if (error) {
+ LOG("xwimp_create_window: 0x%x: %s", error->errnum, error->errmess);
+ free(sslcert_window);
+ return;
+ }
+
+ /* Create the SSL data and build a tree from it. */
+ sslcert_viewer_create_session_data(num, url,
+ cb, cbpw, certs, &sslcert_window->data);
+ ssl_current_session = sslcert_window->data;
+
+ sslcert_window->tv = ro_treeview_create(sslcert_window->pane,
+ NULL, NULL, TREE_SSLCERT);
+ if (sslcert_window->tv == NULL) {
+ LOG("Failed to allocate treeview");
+ free(sslcert_window);
+ return;
+ }
+
+ /* Set up the certificate window event handling.
+ *
+ * (The action buttons are registered as button events, not OK and
+ * Cancel, as both need to carry out actions.)
+ */
+
+ ro_gui_wimp_event_set_user_data(sslcert_window->window, sslcert_window);
+ ro_gui_wimp_event_register_close_window(sslcert_window->window,
+ ro_gui_cert_close_window);
+ ro_gui_wimp_event_register_button(sslcert_window->window,
+ ICON_SSL_REJECT, ro_gui_cert_reject);
+ ro_gui_wimp_event_register_button(sslcert_window->window,
+ ICON_SSL_ACCEPT, ro_gui_cert_accept);
+
+ ro_gui_dialog_open_persistent(NULL, sslcert_window->window, false);
+
+ /* Nest the tree window inside the pane window. To do this, we:
+ * - Get the current pane extent,
+ * - Get the parent window position and the location of the pane-
+ * locating icon inside it,
+ * - Set the visible area of the pane to suit,
+ * - Check that the pane extents are OK for this visible area, and
+ * increase them if necessary,
+ * - Before finally opening the pane as a nested part of the parent.
+ */
+
+ info.w = sslcert_window->pane;
+ error = xwimp_get_window_info_header_only(&info);
+ if (error) {
+ ro_gui_cert_release_window(sslcert_window);
+ LOG("xwimp_get_window_info: 0x%x: %s", error->errnum, error->errmess);
+ return;
+ }
+
+ state.w = sslcert_window->window;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ ro_gui_cert_release_window(sslcert_window);
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ return;
+ }
+
+ istate.w = sslcert_window->window;
+ istate.i = ICON_SSL_PANE;
+ error = xwimp_get_icon_state(&istate);
+ if (error) {
+ ro_gui_cert_release_window(sslcert_window);
+ LOG("xwimp_get_icon_state: 0x%x: %s", error->errnum, error->errmess);
+ return;
+ }
+
+ state.w = sslcert_window->pane;
+ state.visible.x1 = state.visible.x0 + istate.icon.extent.x1 - 20 -
+ ro_get_vscroll_width(sslcert_window->pane);
+ state.visible.x0 += istate.icon.extent.x0 + 20;
+ state.visible.y0 = state.visible.y1 + istate.icon.extent.y0 + 20 +
+ ro_get_hscroll_height(sslcert_window->pane);
+ state.visible.y1 += istate.icon.extent.y1 - 32;
+
+ set_extent = false;
+
+ if ((info.extent.x1 - info.extent.x0) <
+ (state.visible.x1 - state.visible.x0)) {
+ info.extent.x0 = 0;
+ info.extent.x1 = state.visible.x1 - state.visible.x0;
+ set_extent = true;
+ }
+ if ((info.extent.y1 - info.extent.y0) <
+ (state.visible.y1 - state.visible.y0)) {
+ info.extent.y1 = 0;
+ info.extent.x1 = state.visible.y0 - state.visible.y1;
+ set_extent = true;
+ }
+
+ if (set_extent) {
+ error = xwimp_set_extent(sslcert_window->pane, &(info.extent));
+ if (error) {
+ ro_gui_cert_release_window(sslcert_window);
+ LOG("xwimp_set_extent: 0x%x: %s", error->errnum, error->errmess);
+ return;
+ }
+ }
+
+ error = xwimp_open_window_nested(PTR_WIMP_OPEN(&state),
+ sslcert_window->window,
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_XORIGIN_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_TOP_OR_RIGHT
+ << wimp_CHILD_YORIGIN_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_LS_EDGE_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_RS_EDGE_SHIFT);
+ if (error) {
+ ro_gui_cert_release_window(sslcert_window);
+ LOG("xwimp_open_window_nested: 0x%x: %s", error->errnum, error->errmess);
+ ro_gui_cert_release_window(sslcert_window);
+ return;
+ }
+
+ ro_treeview_set_origin(sslcert_window->tv, 0, 0);
+}
+
+/**
+ * Handle acceptance of certificate via event callback.
+ *
+ * \param *pointer The wimp pointer block.
+ */
+
+void ro_gui_cert_accept(wimp_pointer *pointer)
+{
+ struct ro_sslcert *s;
+
+ s = (struct ro_sslcert *) ro_gui_wimp_event_get_user_data(pointer->w);
+
+ if (s != NULL) {
+ sslcert_viewer_accept(s->data);
+ ro_gui_dialog_close(s->window);
+ ro_gui_cert_release_window(s);
+ }
+}
+
+/**
+ * Handle rejection of certificate via event callback.
+ *
+ * \param pointer The wimp pointer block.
+ */
+
+void ro_gui_cert_reject(wimp_pointer *pointer)
+{
+ struct ro_sslcert *s;
+
+ s = (struct ro_sslcert *) ro_gui_wimp_event_get_user_data(pointer->w);
+
+ if (s != NULL) {
+ sslcert_viewer_reject(s->data);
+ ro_gui_dialog_close(s->window);
+ ro_gui_cert_release_window(s);
+ }
+}
+
+/**
+ * Callback to handle the closure of the SSL dialogue by other means.
+ *
+ * \param w The window being closed.
+ */
+
+static void ro_gui_cert_close_window(wimp_w w)
+{
+ struct ro_sslcert *s;
+
+ s = (struct ro_sslcert *) ro_gui_wimp_event_get_user_data(w);
+
+ if (s != NULL)
+ ro_gui_cert_release_window(s);
+}
+
+/**
+ * Handle closing of the RISC OS certificate verification dialog, deleting
+ * the windows and freeing up the treeview and data block.
+ *
+ * \param *s The data block associated with the dialogue.
+ */
+
+void ro_gui_cert_release_window(struct ro_sslcert *s)
+{
+ os_error *error;
+
+ if (s == NULL)
+ return;
+
+ LOG("Releasing SSL data: 0x%x", (unsigned)s);
+
+ ro_gui_wimp_event_finalise(s->window);
+ ro_treeview_destroy(s->tv);
+
+ error = xwimp_delete_window(s->window);
+ if (error) {
+ LOG("xwimp_delete_window: 0x%x:%s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+ error = xwimp_delete_window(s->pane);
+ if (error) {
+ LOG("xwimp_delete_window: 0x%x:%s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+
+ free(s);
+}
+
diff --git a/frontends/riscos/sslcert.h b/frontends/riscos/sslcert.h
new file mode 100644
index 000000000..17fce5552
--- /dev/null
+++ b/frontends/riscos/sslcert.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2006 Richard Wilson <info@tinct.net>
+ * Copyright 2010 Stephen Fryatt <stevef@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * SSL certificate viewer (interface).
+ */
+
+#ifndef _NETSURF_RISCOS_SSLCERT_H_
+#define _NETSURF_RISCOS_SSLCERT_H_
+
+struct node;
+
+void ro_gui_cert_preinitialise(void);
+void ro_gui_cert_postinitialise(void);
+void ro_gui_cert_open(struct tree *tree, struct node *node);
+
+#endif
+
diff --git a/frontends/riscos/templates/de b/frontends/riscos/templates/de
new file mode 100644
index 000000000..0fb4a9de7
--- /dev/null
+++ b/frontends/riscos/templates/de
@@ -0,0 +1,3845 @@
+Template:
+
+wimp_window {
+ template_name:"configure"
+ visible:378,820,1046,1126
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BACK_ICON | wimp_WINDOW_CLOSE_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_TOGGLE_ICON | wimp_WINDOW_VSCROLL | wimp_WINDOW_SIZE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_LIGHT_GREY
+ extra_flags:
+ extent:0,-880,1236,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:4
+ ymin:156
+ text.text:"NetSurf Konfiguration"
+ text.size:*
+ text.validation:""
+}
+
+wimp_window {
+ template_name:"con_cache"
+ visible:500,672,1088,1100
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_FULL_SIZE | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-428,588,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED
+ work_flags:
+ sprite_area:&1
+ xmin:588
+ ymin:240
+ text_only:"Cache"
+ wimp_icon {
+ extent:16,-124,568,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-52,268,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Memory cache "
+ text_and_sprite.size:*
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:44,-100,164,-56
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Größe"
+ text.size:13
+ text.validation:""
+ }
+ wimp_icon {
+ extent:168,-104,336,-52
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"512.0"
+ text.size:10
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:352,-96,384,-64
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:384,-96,416,-64
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:424,-100,480,-56
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"MB"
+ }
+ wimp_icon {
+ extent:16,-312,568,-152
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-180,268,-136
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Disc cache "
+ text_and_sprite.size:*
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:44,-232,164,-188
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Größe"
+ text.size:13
+ text.validation:""
+ }
+ wimp_icon {
+ extent:168,-236,336,-184
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"512"
+ text.size:10
+ text.validation:"Pptr_write;Kta;A0-9"
+ }
+ wimp_icon {
+ extent:352,-228,384,-196
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:384,-228,416,-196
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:424,-232,480,-192
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"MB"
+ }
+ wimp_icon {
+ extent:44,-292,164,-248
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Expiry"
+ text.size:13
+ text.validation:""
+ }
+ wimp_icon {
+ extent:168,-296,336,-244
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"512"
+ text.size:10
+ text.validation:"Pptr_write;Kta;A0-9"
+ }
+ wimp_icon {
+ extent:352,-288,384,-256
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:384,-288,416,-256
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:424,-292,500,-252
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"days"
+ }
+ wimp_icon {
+ extent:24,-396,188,-344
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Standard"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:204,-396,368,-344
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Abbruch"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:384,-404,568,-336
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"OK"
+ text.size:4
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"con_fonts"
+ visible:744,374,1456,1098
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_FULL_SIZE | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-724,712,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:712
+ ymin:724
+ text.text:"Schriftarten"
+ text.size:*
+ text.validation:""
+ wimp_icon {
+ extent:16,-424,696,-28
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-52,236,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Font faces "
+ text_and_sprite.size:*
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:26,-104,198,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Sans-serif"
+ }
+ wimp_icon {
+ extent:200,-108,624,-56
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:256
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:632,-104,676,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:106,-164,198,-120
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Serif"
+ }
+ wimp_icon {
+ extent:200,-168,624,-116
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:256
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:632,-164,676,-120
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:34,-224,198,-180
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Monospace"
+ }
+ wimp_icon {
+ extent:200,-228,624,-176
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:256
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:632,-224,676,-180
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:13
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:74,-284,198,-240
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Cursive"
+ }
+ wimp_icon {
+ extent:200,-288,624,-236
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:256
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:632,-284,676,-240
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:74,-344,198,-300
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Fantasy"
+ }
+ wimp_icon {
+ extent:200,-348,624,-296
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:256
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:632,-344,676,-300
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:42,-404,198,-360
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Standard"
+ }
+ wimp_icon {
+ extent:200,-408,624,-356
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:256
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:632,-404,676,-360
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:16,-616,696,-456
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-480,220,-436
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Font size "
+ text_and_sprite.size:*
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:64,-532,192,-488
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Normal"
+ }
+ wimp_icon {
+ extent:200,-536,368,-484
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"12.3"
+ text.size:10
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:380,-528,412,-496
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:412,-528,444,-496
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:452,-532,492,-488
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"pt"
+ }
+ wimp_icon {
+ extent:60,-592,192,-548
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Minimum"
+ }
+ wimp_icon {
+ extent:200,-596,368,-544
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"12.3"
+ text.size:10
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:380,-588,412,-556
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:412,-588,444,-556
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:452,-592,492,-548
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"pt"
+ }
+ wimp_icon {
+ extent:24,-696,188,-644
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Standard"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:332,-696,496,-644
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Abbruch"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:512,-704,696,-636
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"OK"
+ text.size:4
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"con_home"
+ visible:400,304,1200,600
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_FULL_SIZE | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-296,800,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:800
+ ymin:296
+ text_only:"Homepage"
+ wimp_icon {
+ extent:16,-184,784,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-52,284,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Home page "
+ text_and_sprite.size:16
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:48,-108,120,-64
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"URL"
+ }
+ wimp_icon {
+ extent:124,-112,712,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:""
+ text.size:128
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:720,-108,764,-64
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:13
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:124,-164,676,-120
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Fenster beim Start öffnen"
+ text_and_sprite.size:32
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:24,-264,188,-212
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Standard"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:416,-264,580,-212
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Abbruch"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:596,-272,780,-204
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"OK"
+ text.size:4
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"con_image"
+ visible:828,926,1504,1514
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_FULL_SIZE | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-588,676,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:676
+ ymin:588
+ text_only:"Bilder"
+ wimp_icon {
+ extent:16,-292,660,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-52,284,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Image quality "
+ text_and_sprite.size:*
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:32,-108,224,-64
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Vordergrund"
+ }
+ wimp_icon {
+ extent:232,-112,592,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Error diffused"
+ text.size:256
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:600,-108,644,-64
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:13
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:32,-168,224,-124
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Hintergrund"
+ }
+ wimp_icon {
+ extent:232,-172,592,-120
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Error diffused"
+ text.size:256
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:600,-168,644,-124
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:13
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:32,-276,644,-180
+ icon_flags:wimp_ICON_BORDER
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ }
+ wimp_icon {
+ extent:16,-476,660,-320
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-348,284,-304
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Animations "
+ text_and_sprite.size:16
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:20,-404,208,-360
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Speedlimit"
+ text.size:12
+ text.validation:""
+ }
+ wimp_icon {
+ extent:212,-408,380,-356
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"12.34"
+ text.size:*
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:396,-400,428,-368
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:428,-400,460,-368
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:468,-404,612,-360
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Sekunden"
+ text.size:*
+ text.validation:""
+ }
+ wimp_icon {
+ extent:212,-460,640,-416
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Animationen abschalten"
+ text_and_sprite.size:*
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:24,-560,188,-508
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Standard"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:296,-560,460,-508
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Abbruch"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:476,-568,660,-500
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"OK"
+ text.size:4
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"con_lang"
+ visible:770,1102,1514,1402
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_FULL_SIZE | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-300,744,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:744
+ ymin:300
+ text.text:"Spracheinstellungen"
+ text.size:*
+ text.validation:""
+ wimp_icon {
+ extent:16,-188,728,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-52,284,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Language "
+ text_and_sprite.size:16
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:32,-108,204,-64
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Oberfläche"
+ }
+ wimp_icon {
+ extent:208,-112,660,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"1337"
+ text.size:256
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:668,-108,712,-64
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:13
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:40,-168,204,-124
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Webseiten"
+ }
+ wimp_icon {
+ extent:208,-172,660,-120
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"8008135"
+ text.size:256
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:668,-168,712,-124
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:13
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:24,-268,188,-216
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Standard"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:360,-268,524,-216
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Abbruch"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:540,-276,724,-208
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"OK"
+ text.size:4
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"con_theme"
+ visible:408,370,1316,974
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_FULL_SIZE | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-604,908,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:640
+ ymin:604
+ text_only:"Themen"
+ wimp_icon {
+ extent:16,-492,892,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-52,332,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Available themes "
+ text_and_sprite.size:*
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:24,-576,188,-524
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Standard"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:524,-576,688,-524
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Abbruch"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:704,-584,888,-516
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"OK"
+ text.size:4
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"download"
+ visible:486,610,1394,890
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_FULL_SIZE | wimp_WINDOW_BACK_ICON | wimp_WINDOW_CLOSE_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-280,908,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:796
+ ymin:280
+ text.text:"NetSurf Download"
+ text.size:*
+ text.validation:""
+ wimp_icon {
+ extent:420,-84,488,-16
+ icon_flags:wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK_DRAG
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ sprite.id:"file_ddc"
+ sprite.size:*
+ sprite.area:&1
+ }
+ wimp_icon {
+ extent:204,-152,900,-100
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"http://netsurf.sourceforge.net/netsurf.zip"
+ text.size:*
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:204,-212,900,-160
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"netsurf"
+ text.size:*
+ text.validation:"Pptr_write"
+ }
+ wimp_icon {
+ extent:204,-212,900,-160
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"ADFS::A7000+.$.netsurf"
+ text.size:*
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:8,-272,900,-220
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:12,-268,296,-224
+ icon_flags:wimp_ICON_FILLED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_CREAM
+ }
+ wimp_icon {
+ extent:12,-268,896,-224
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"84.4KB of 1.1MB 26.6KB/s 0:39 remaining"
+ text.size:*
+ text.validation:""
+ }
+ wimp_icon {
+ extent:92,-148,200,-104
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Quelle"
+ }
+ wimp_icon {
+ extent:12,-208,200,-164
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Zielort"
+ }
+}
+
+wimp_window {
+ template_name:"history"
+ visible:252,388,1152,808
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_SCROLL_REPEAT | wimp_WINDOW_BACK_ICON | wimp_WINDOW_CLOSE_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_TOGGLE_ICON | wimp_WINDOW_VSCROLL | wimp_WINDOW_SIZE_ICON | wimp_WINDOW_HSCROLL | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_WHITE
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-880,1236,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:wimp_BUTTON_CLICK
+ sprite_area:&1
+ xmin:0
+ ymin:0
+ text.text:"History"
+ text.size:*
+ text.validation:""
+}
+
+wimp_window {
+ template_name:"info"
+ visible:268,838,888,1086
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_FULL_SIZE | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_CREAM
+ scroll_inner:wimp_COLOUR_ORANGE
+ highlight_bg:wimp_COLOUR_LIGHT_GREY
+ extra_flags:
+ extent:0,-248,620,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:wimp_BUTTON_CLICK
+ sprite_area:&1
+ xmin:0
+ ymin:0
+ text.text:"Über dieses Programm"
+ text.size:*
+ text.validation:""
+ wimp_icon {
+ extent:676,-204,852,-156
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_RED
+ text_only:"OK"
+ }
+ wimp_icon {
+ extent:152,-60,612,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK_DRAG
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"NetSurf"
+ text.size:*
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:152,-120,612,-68
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK_DRAG
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Open source web browser"
+ text.size:*
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:152,-180,612,-128
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK_DRAG
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"© NetSurf developers"
+ text.size:40
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:152,-240,612,-188
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK_DRAG
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"CVS test build"
+ text.size:40
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:60,-56,148,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Name"
+ }
+ wimp_icon {
+ extent:48,-116,148,-72
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Zweck"
+ }
+ wimp_icon {
+ extent:56,-176,148,-132
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Autor"
+ }
+ wimp_icon {
+ extent:24,-236,148,-192
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Version"
+ }
+}
+
+wimp_window {
+ template_name:"login"
+ visible:710,422,1386,758
+ xscroll:0
+ yscroll:-8
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_FULL_SIZE | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-344,676,-8
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:676
+ ymin:336
+ text.text:"Authentifizierung"
+ text.size:20
+ text.validation:""
+ wimp_icon {
+ extent:532,-332,664,-264
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Login"
+ text.size:8
+ text.validation:"R6,3;Nok"
+ }
+ wimp_icon {
+ extent:376,-324,508,-272
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Abbruch"
+ text.size:*
+ text.validation:"R5,3;Ncancel"
+ }
+ wimp_icon {
+ extent:168,-68,668,-16
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"moo.yoo.com"
+ text.size:255
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:168,-128,668,-76
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"my sekr3t area"
+ text.size:255
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:168,-188,668,-136
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:""
+ text.size:255
+ text.validation:"Pptr_write;Kta;N401username"
+ }
+ wimp_icon {
+ extent:168,-248,668,-196
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:""
+ text.size:255
+ text.validation:"Pptr_write;Kta;D*"
+ }
+ wimp_icon {
+ extent:88,-64,164,-20
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Host"
+ }
+ wimp_icon {
+ extent:16,-184,164,-140
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Username"
+ }
+ wimp_icon {
+ extent:24,-244,164,-200
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Passwort"
+ }
+ wimp_icon {
+ extent:68,-124,164,-80
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Realm"
+ }
+}
+
+wimp_window {
+ template_name:"new_entry"
+ visible:1120,590,1720,810
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_FULL_SIZE | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-220,600,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:600
+ ymin:220
+ text.text:""
+ text.size:32
+ text.validation:""
+ wimp_icon {
+ extent:12,-56,108,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Name"
+ }
+ wimp_icon {
+ extent:112,-60,588,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:""
+ text.size:128
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:12,-116,108,-72
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"URL"
+ }
+ wimp_icon {
+ extent:112,-120,532,-68
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:""
+ text.size:1024
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:304,-200,436,-148
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Abbruch"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:456,-208,588,-140
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"OK"
+ text.size:8
+ text.validation:"R6,3"
+ }
+ wimp_icon {
+ extent:540,-116,584,-72
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:13
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+}
+
+wimp_window {
+ template_name:"new_folder"
+ visible:480,954,1080,1114
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_FULL_SIZE | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-160,600,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:600
+ ymin:160
+ text.text:""
+ text.size:21
+ text.validation:""
+ wimp_icon {
+ extent:12,-56,108,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Name"
+ }
+ wimp_icon {
+ extent:112,-60,588,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:""
+ text.size:128
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:304,-140,436,-88
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Abbruch"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:456,-148,588,-80
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"OK"
+ text.size:8
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"objectinfo"
+ visible:272,900,1060,1088
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_FULL_SIZE | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-188,788,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:wimp_BUTTON_CLICK
+ sprite_area:&1
+ xmin:788
+ ymin:188
+ text.text:"Über das Objekt"
+ text.size:20
+ text.validation:""
+ wimp_icon {
+ extent:204,-60,780,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:64
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:204,-120,780,-68
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:64
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:204,-180,780,-128
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:64
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:12,-80,84,-12
+ icon_flags:wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ sprite.id:"file_faf"
+ sprite.size:*
+ sprite.area:&1
+ }
+ wimp_icon {
+ extent:124,-116,200,-72
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Ziel"
+ }
+ wimp_icon {
+ extent:136,-176,200,-132
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Typ"
+ }
+ wimp_icon {
+ extent:128,-56,200,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"URL"
+ }
+}
+
+wimp_window {
+ template_name:"open_url"
+ visible:438,126,1238,282
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_FULL_SIZE | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-156,800,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:0
+ ymin:0
+ text.text:"Webseite öffnen"
+ text.size:25
+ text.validation:""
+ wimp_icon {
+ extent:20,-56,92,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"URL"
+ }
+ wimp_icon {
+ extent:96,-60,736,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:""
+ text.size:1
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:504,-136,632,-84
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Abbruch"
+ text.size:21
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:656,-144,788,-76
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Öffnen"
+ text.size:8
+ text.validation:"R6,3"
+ }
+ wimp_icon {
+ extent:744,-56,788,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:13
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+}
+
+wimp_window {
+ template_name:"pageinfo"
+ visible:576,224,1368,472
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_FULL_SIZE | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-248,792,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:wimp_BUTTON_CLICK
+ sprite_area:&1
+ xmin:792
+ ymin:248
+ text.text:"Über das Dokument"
+ text.size:20
+ text.validation:""
+ wimp_icon {
+ extent:208,-60,784,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:64
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:208,-120,784,-68
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:64
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:208,-180,784,-128
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:64
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:208,-240,784,-188
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:64
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:12,-80,84,-12
+ icon_flags:wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ sprite.id:"file_faf"
+ sprite.size:*
+ sprite.area:&1
+ }
+ wimp_icon {
+ extent:132,-116,204,-72
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"URL"
+ }
+ wimp_icon {
+ extent:48,-176,204,-132
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Kodierung"
+ }
+ wimp_icon {
+ extent:140,-236,204,-192
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Typ"
+ }
+ wimp_icon {
+ extent:112,-56,204,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Titel"
+ }
+}
+
+wimp_window {
+ template_name:"print"
+ visible:1204,134,1804,706
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_FULL_SIZE | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-572,600,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:600
+ ymin:572
+ text.text:"kein Drucker"
+ text.size:20
+ text.validation:""
+ wimp_icon {
+ extent:12,-176,588,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-100,504,-56
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:1
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Ende der Web-Seite"
+ text_and_sprite.size:27
+ text_and_sprite.validation:"Sradiooff,radioon"
+ }
+ wimp_icon {
+ extent:32,-152,492,-108
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:1
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:6
+ text_and_sprite.validation:"Sradiooff,radioon"
+ }
+ wimp_icon {
+ extent:84,-156,164,-104
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"1"
+ text.size:3
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:176,-148,208,-116
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:212,-148,244,-116
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:248,-152,476,-108
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Seiten"
+ text.size:18
+ text.validation:""
+ }
+ wimp_icon {
+ extent:12,-236,452,-192
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Vordergrundbilder zeigen"
+ text_and_sprite.size:*
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:12,-288,452,-244
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Hintergrundbilder zeigen"
+ text_and_sprite.size:*
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:12,-340,420,-296
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"im Hintergrund drucken"
+ text_and_sprite.size:*
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:12,-404,196,-360
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Portrait"
+ text_and_sprite.size:*
+ text_and_sprite.validation:"Sradiooff,radioon"
+ }
+ wimp_icon {
+ extent:12,-452,228,-408
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Landschaft"
+ text_and_sprite.size:*
+ text_and_sprite.validation:"Sradiooff,radioon"
+ }
+ wimp_icon {
+ extent:432,-456,512,-404
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"1"
+ text.size:3
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:524,-448,556,-416
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:556,-448,588,-416
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:284,-552,416,-500
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Abbruch"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:440,-560,588,-492
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Drucken"
+ text.size:*
+ text.validation:"R6,3"
+ }
+ wimp_icon {
+ extent:320,-452,428,-408
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Kopien"
+ }
+ wimp_icon {
+ extent:-4,-480,608,-472
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:32,-52,364,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Druck beenden nach "
+ text_and_sprite.size:*
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:252,-400,596,-356
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Text immer schwarz"
+ text_and_sprite.size:24
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+}
+
+wimp_window {
+ template_name:"query"
+ visible:426,1082,1226,1326
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_FULL_SIZE | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_LIGHT_GREY
+ extra_flags:
+ extent:0,-244,800,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:0
+ ymin:0
+ text.text:"Sicherheitsabfrage von NetSurf"
+ text.size:*
+ text.validation:""
+ wimp_icon {
+ extent:92,-148,792,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Message"
+ text.size:300
+ text.validation:"R2;L"
+ }
+ wimp_icon {
+ extent:636,-232,788,-164
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"012345678901234567"
+ text.size:*
+ text.validation:"R6,3"
+ }
+ wimp_icon {
+ extent:504,-224,620,-172
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"012345678901234567"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:16,-224,132,-172
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Hilfe"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:12,-80,80,-12
+ icon_flags:wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ sprite_only:"!netsurf"
+ }
+}
+
+wimp_window {
+ template_name:"saveas"
+ visible:618,322,950,570
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_FULL_SIZE | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-248,332,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:0
+ ymin:0
+ text_only:"Abspeichern"
+ wimp_icon {
+ extent:132,-84,200,-16
+ icon_flags:wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK_DRAG
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ sprite.id:"file_faf"
+ sprite.size:13
+ sprite.area:&1
+ }
+ wimp_icon {
+ extent:8,-152,324,-96
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:""
+ text.size:256
+ text.validation:"Pptr_write"
+ }
+ wimp_icon {
+ extent:172,-236,320,-168
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Sichern"
+ text.size:*
+ text.validation:"R6,3"
+ }
+ wimp_icon {
+ extent:20,-228,148,-176
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Abbruch"
+ text.size:*
+ text.validation:"R5,3"
+ }
+}
+
+wimp_window {
+ template_name:"search"
+ visible:384,780,1028,1024
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_FULL_SIZE | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-244,644,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:644
+ ymin:244
+ text.text:"Text suchen"
+ text.size:*
+ text.validation:""
+ wimp_icon {
+ extent:96,-60,580,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:""
+ text.size:32
+ text.validation:"KN;Pptr_write"
+ }
+ wimp_icon {
+ extent:96,-116,352,-72
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Groß/klein"
+ text_and_sprite.size:15
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:500,-228,632,-160
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"vor"
+ text.size:10
+ text.validation:"R6,3"
+ }
+ wimp_icon {
+ extent:348,-220,484,-168
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"zurück"
+ text.size:9
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:204,-220,332,-168
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Abbruch"
+ text.size:12
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:16,-216,196,-172
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Not found"
+ text.size:*
+ text.validation:""
+ }
+ wimp_icon {
+ extent:-8,-148,652,-140
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:16,-56,92,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Text"
+ }
+ wimp_icon {
+ extent:588,-56,632,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_ICON_SHADED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:13
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:352,-116,580,-72
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Alle zeigen"
+ text_and_sprite.size:*
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+}
+
+wimp_window {
+ template_name:"theme_inst"
+ visible:384,134,1184,378
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_FULL_SIZE | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-244,800,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:0
+ ymin:0
+ text.text:"NetSurf Themen-Installation"
+ text.size:*
+ text.validation:""
+ wimp_icon {
+ extent:92,-148,792,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Message"
+ text.size:300
+ text.validation:"R2;L"
+ }
+ wimp_icon {
+ extent:540,-232,788,-164
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Installieren"
+ text.size:*
+ text.validation:"R6,3"
+ }
+ wimp_icon {
+ extent:394,-224,522,-172
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Abbruch"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:12,-80,80,-12
+ icon_flags:wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ sprite_only:"!netsurf"
+ }
+}
+
+wimp_window {
+ template_name:"tooltip"
+ visible:884,620,1148,656
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-36,2000,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED
+ work_flags:
+ sprite_area:&1
+ xmin:0
+ ymin:0
+ text_only:"<Untitled>"
+ wimp_icon {
+ extent:0,-40,300,4
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_ICON_SELECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Kommentar"
+ text.size:256
+ text.validation:""
+ }
+}
+
+wimp_window {
+ template_name:"tree"
+ visible:530,654,1042,954
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_SCROLL_REPEAT | wimp_WINDOW_IGNORE_XEXTENT | wimp_WINDOW_IGNORE_YEXTENT | wimp_WINDOW_BACK_ICON | wimp_WINDOW_CLOSE_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_TOGGLE_ICON | wimp_WINDOW_VSCROLL | wimp_WINDOW_SIZE_ICON | wimp_WINDOW_HSCROLL | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_TRANSPARENT
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-880,1236,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:wimp_BUTTON_DOUBLE_CLICK_DRAG
+ sprite_area:&1
+ xmin:0
+ ymin:0
+ text.text:""
+ text.size:64
+ text.validation:""
+}
+
+wimp_window {
+ template_name:"url_suggest"
+ visible:320,390,1102,684
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_NO_BOUNDS | wimp_WINDOW_IGNORE_XEXTENT | wimp_WINDOW_IGNORE_YEXTENT | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_TRANSPARENT
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-65536,65536,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED
+ work_flags:wimp_BUTTON_CLICK
+ sprite_area:&1
+ xmin:0
+ ymin:0
+ text_only:"<Untitled>"
+}
+
+wimp_window {
+ template_name:"warning"
+ visible:320,524,1120,768
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_FULL_SIZE | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-244,800,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:0
+ ymin:0
+ text.text:"Warnung von NetSurf"
+ text.size:21
+ text.validation:""
+ wimp_icon {
+ extent:92,-148,792,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Message"
+ text.size:300
+ text.validation:"R2;L"
+ }
+ wimp_icon {
+ extent:624,-232,788,-164
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Weiter"
+ text.size:9
+ text.validation:"R6,3"
+ }
+ wimp_icon {
+ extent:480,-224,600,-172
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Hilfe"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:12,-80,80,-12
+ icon_flags:wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ sprite_only:"!netsurf"
+ }
+}
+
+wimp_window {
+ template_name:"zoom"
+ visible:694,830,1142,1054
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_FULL_SIZE | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-224,448,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:448
+ ymin:224
+ text.text:"Ansicht skalieren"
+ text.size:*
+ text.validation:""
+ wimp_icon {
+ extent:8,-56,104,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Größe"
+ }
+ wimp_icon {
+ extent:108,-60,208,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"100"
+ text.size:5
+ text.validation:"Pptr_write;KTA;A0-9."
+ }
+ wimp_icon {
+ extent:220,-52,252,-20
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"R5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:252,-52,284,-20
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"R5;sup,pup"
+ }
+ wimp_icon {
+ extent:288,-56,328,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_HCENTRED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"%"
+ }
+ wimp_icon {
+ extent:108,-112,420,-68
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Frames skalieren"
+ text_and_sprite.size:20
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:-4,-132,548,-124
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:84,-204,216,-152
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Abbruch"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:240,-212,436,-144
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Skalieren"
+ text.size:*
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"con_inter"
+ visible:1094,146,1838,918
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_FULL_SIZE | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-772,744,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:744
+ ymin:584
+ text_only:"Nützliches"
+ wimp_icon {
+ extent:16,-168,728,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-52,492,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Downloading / saving files "
+ text_and_sprite.size:*
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:32,-92,696,-48
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Erweiterungen beim Speichern entfernen"
+ text_and_sprite.size:*
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:32,-152,676,-108
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"vor Überschreiben von Dateien fragen"
+ text_and_sprite.size:46
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:16,-344,728,-200
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:36,-224,496,-180
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Interactive features "
+ text_and_sprite.size:*
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:32,-268,744,-224
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"aktuellste URLs beim Tippen anzeigen"
+ text_and_sprite.size:42
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:32,-328,872,-284
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"URLs in lokaler History einblenden"
+ text_and_sprite.size:44
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:16,-468,728,-372
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:36,-400,240,-356
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Thumbnails "
+ text_and_sprite.size:23
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:32,-452,648,-408
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Thumbnails zeigen beim Iconisieren"
+ text_and_sprite.size:42
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:24,-740,188,-688
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Standard"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:360,-740,524,-688
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Abbruch"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:540,-748,724,-680
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"OK"
+ text.size:4
+ text.validation:"R6,3"
+ }
+ wimp_icon {
+ extent:16,-660,728,-492
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:36,-520,240,-476
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Hotlist"
+ text_and_sprite.size:23
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:32,-572,728,-528
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Use external hotlist apps when available"
+ text_and_sprite.size:*
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:28,-640,232,-588
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Hotlist path"
+ text.size:*
+ text.validation:""
+ }
+ wimp_icon {
+ extent:232,-640,708,-588
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"Writable icon"
+ text.size:256
+ text.validation:"Pptr_write;Kta"
+ }
+}
+
+wimp_window {
+ template_name:"con_secure"
+ visible:440,540,1032,904
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_FULL_SIZE | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-364,592,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:592
+ ymin:364
+ text_only:"Sicherheit"
+ wimp_icon {
+ extent:16,-120,576,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-52,364,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Cross-site privacy "
+ text_and_sprite.size:*
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:32,-96,568,-52
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Seitenreferenzen senden"
+ text_and_sprite.size:31
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:16,-252,576,-148
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-176,316,-132
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Site history "
+ text_and_sprite.size:18
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:32,-224,172,-180
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"behalten"
+ }
+ wimp_icon {
+ extent:184,-228,344,-176
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"12"
+ text.size:4
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:358,-216,390,-184
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:390,-220,422,-188
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:434,-224,510,-180
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Tage"
+ }
+ wimp_icon {
+ extent:24,-336,188,-284
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Standard"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:208,-336,372,-284
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Abbruch"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:388,-344,572,-276
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"OK"
+ text.size:4
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"con_connect"
+ visible:902,402,1562,1070
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_FULL_SIZE | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-668,660,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:660
+ ymin:668
+ text_only:"Verbindung"
+ wimp_icon {
+ extent:16,-304,644,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:28,-52,264,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" HTTP Proxy "
+ text_and_sprite.size:15
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:12,-104,184,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Proxytyp"
+ }
+ wimp_icon {
+ extent:188,-108,572,-56
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:32
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:580,-104,624,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:108,-164,184,-120
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Host"
+ text.size:*
+ text.validation:""
+ }
+ wimp_icon {
+ extent:188,-168,504,-116
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"myhost.proxy"
+ text.size:255
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:500,-164,528,-120
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_HCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:":"
+ text.size:*
+ text.validation:""
+ }
+ wimp_icon {
+ extent:524,-168,628,-116
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"8080"
+ text.size:8
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:36,-224,184,-180
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Username"
+ text.size:*
+ text.validation:""
+ }
+ wimp_icon {
+ extent:188,-228,628,-176
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"k1dd13"
+ text.size:64
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:36,-284,184,-240
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Passwort"
+ text.size:*
+ text.validation:""
+ }
+ wimp_icon {
+ extent:188,-288,628,-236
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"1337"
+ text.size:64
+ text.validation:"Pptr_write;Kta;D*"
+ }
+ wimp_icon {
+ extent:16,-552,644,-332
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-360,268,-316
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Fetching "
+ text_and_sprite.size:15
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:52,-412,340,-368
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Fetches maximal"
+ text.size:18
+ text.validation:""
+ }
+ wimp_icon {
+ extent:344,-416,552,-364
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"99"
+ text.size:*
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:560,-408,592,-376
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:592,-408,624,-376
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:56,-472,340,-428
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Fetches pro Host"
+ text.size:18
+ text.validation:""
+ }
+ wimp_icon {
+ extent:344,-476,552,-424
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"99"
+ text.size:4
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:560,-468,596,-436
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:592,-468,624,-436
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:32,-532,340,-488
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Verbindungen cachen"
+ text.size:22
+ text.validation:""
+ }
+ wimp_icon {
+ extent:344,-536,552,-484
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"99"
+ text.size:4
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:560,-528,596,-496
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:592,-528,624,-496
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:24,-640,188,-588
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Standard"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:276,-640,440,-588
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Abbruch"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:456,-648,640,-580
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"OK"
+ text.size:4
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"ssldisplay"
+ visible:212,142,1172,682
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_FULL_SIZE | wimp_WINDOW_CLOSE_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-540,960,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:960
+ ymin:76
+ text.text:"SSL Zertifikat"
+ text.size:16
+ text.validation:""
+ wimp_icon {
+ extent:432,-168,928,-116
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:16,-520,944,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:24,-108,148,-64
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Version"
+ }
+ wimp_icon {
+ extent:152,-108,264,-56
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:260,-104,432,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"gültig von"
+ }
+ wimp_icon {
+ extent:432,-108,928,-56
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:68,-168,148,-124
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Typ"
+ }
+ wimp_icon {
+ extent:152,-168,264,-116
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:244,-164,432,-120
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"gültig bis"
+ }
+ wimp_icon {
+ extent:32,-52,380,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Certificate details "
+ text_and_sprite.size:*
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:40,-228,148,-184
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Serial"
+ }
+ wimp_icon {
+ extent:152,-228,928,-176
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:40,-288,148,-244
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Issuer"
+ }
+ wimp_icon {
+ extent:152,-376,928,-236
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R2;L"
+ }
+ wimp_icon {
+ extent:24,-432,148,-388
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Subject"
+ }
+ wimp_icon {
+ extent:152,-504,928,-384
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R2;L"
+ }
+}
+
+wimp_window {
+ template_name:"sslcert"
+ visible:348,306,1136,898
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_FULL_SIZE | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-592,788,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:788
+ ymin:592
+ text.text:"SSL Zertifizierungsproblem"
+ text.size:*
+ text.validation:""
+ wimp_icon {
+ extent:16,-108,772,-16
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"NetSurf konnte ein SSL Zertifikat nicht prüfen. Bitte die Details unten beachten."
+ text.size:150
+ text.validation:"R2;L"
+ }
+ wimp_icon {
+ extent:16,-484,772,-136
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-164,380,-120
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Certificate chain "
+ text_and_sprite.size:22
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:404,-564,568,-512
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Ablehnen"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:588,-572,772,-504
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Annehmen"
+ text.size:12
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"con_content"
+ visible:1404,424,2044,924
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_FULL_SIZE | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-500,640,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:640
+ ymin:452
+ text_only:"Content"
+ wimp_icon {
+ extent:16,-272,624,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-52,492,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Content blocking "
+ text_and_sprite.size:29
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:32,-100,436,-56
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Werbung unterdrücken"
+ text_and_sprite.size:39
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:32,-152,528,-108
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Pop-Up Fenster abschalten"
+ text_and_sprite.size:46
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:32,-256,496,-212
+#ifdef WITH_PLUGIN
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+#else
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_DELETED | wimp_BUTTON_RADIO
+#endif
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Plugins nicht benutzen"
+ text_and_sprite.size:42
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:16,-384,624,-292
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-320,492,-276
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Link targets "
+ text_and_sprite.size:29
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:32,-368,612,-324
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Links dürfen neue Fenster öffnen"
+ text_and_sprite.size:35
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:24,-468,188,-416
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Standard"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:256,-468,420,-416
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Abbruch"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:436,-476,620,-408
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"OK"
+ text.size:4
+ text.validation:"R6,3"
+ }
+ wimp_icon {
+ extent:32,-204,376,-160
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Disable JavaScript"
+ text_and_sprite.size:19
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+}
diff --git a/frontends/riscos/templates/en b/frontends/riscos/templates/en
new file mode 100644
index 000000000..7746b86cc
--- /dev/null
+++ b/frontends/riscos/templates/en
@@ -0,0 +1,3837 @@
+Template:
+
+wimp_window {
+ template_name:"configure"
+ visible:378,966,1050,1126
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BACK_ICON | wimp_WINDOW_CLOSE_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_TOGGLE_ICON | wimp_WINDOW_VSCROLL | wimp_WINDOW_SIZE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_LIGHT_GREY
+ extra_flags:
+ extent:0,-880,1236,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:4
+ ymin:160
+ text.text:"NetSurf configuration"
+ text.size:*
+ text.validation:""
+}
+
+wimp_window {
+ template_name:"con_cache"
+ visible:184,682,772,1110
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-428,588,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED
+ work_flags:
+ sprite_area:&1
+ xmin:588
+ ymin:240
+ text_only:"Cache"
+ wimp_icon {
+ extent:16,-124,568,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-52,268,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Memory cache "
+ text_and_sprite.size:*
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:44,-104,164,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Size"
+ text.size:13
+ text.validation:""
+ }
+ wimp_icon {
+ extent:168,-108,336,-56
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"512.0"
+ text.size:10
+ text.validation:"Pptr_write;Kta;A0-9."
+ }
+ wimp_icon {
+ extent:352,-100,384,-68
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:384,-100,416,-68
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:424,-104,480,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"MB"
+ }
+ wimp_icon {
+ extent:16,-312,568,-152
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-180,268,-136
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Disc cache "
+ text_and_sprite.size:*
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:44,-232,164,-188
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Size"
+ text.size:13
+ text.validation:""
+ }
+ wimp_icon {
+ extent:168,-236,336,-184
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"512"
+ text.size:10
+ text.validation:"Pptr_write;Kta;A0-9"
+ }
+ wimp_icon {
+ extent:352,-228,384,-196
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:384,-228,416,-196
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:424,-232,480,-192
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"MB"
+ }
+ wimp_icon {
+ extent:44,-292,164,-248
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Expiry"
+ text.size:13
+ text.validation:""
+ }
+ wimp_icon {
+ extent:168,-296,336,-244
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"512"
+ text.size:10
+ text.validation:"Pptr_write;Kta;A0-9"
+ }
+ wimp_icon {
+ extent:352,-288,384,-256
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:384,-288,416,-256
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:424,-292,500,-252
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"days"
+ }
+ wimp_icon {
+ extent:24,-396,188,-344
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Default"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:204,-396,368,-344
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Cancel"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:384,-404,568,-336
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Set"
+ text.size:*
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"con_fonts"
+ visible:558,802,1282,1526
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-724,724,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED
+ work_flags:
+ sprite_area:&1
+ xmin:712
+ ymin:724
+ text_only:"Fonts"
+ wimp_icon {
+ extent:16,-424,704,-28
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-52,236,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Font faces "
+ text_and_sprite.size:*
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:28,-104,200,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Sans-serif"
+ }
+ wimp_icon {
+ extent:204,-108,628,-56
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:256
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:640,-104,684,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:108,-164,200,-120
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Serif"
+ }
+ wimp_icon {
+ extent:204,-168,628,-116
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:256
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:640,-164,684,-120
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:36,-224,200,-180
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Monospace"
+ }
+ wimp_icon {
+ extent:204,-228,628,-176
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:256
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:640,-224,684,-180
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:13
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:76,-284,200,-240
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Cursive"
+ }
+ wimp_icon {
+ extent:204,-288,628,-236
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:256
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:640,-284,684,-240
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:72,-344,200,-300
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Fantasy"
+ }
+ wimp_icon {
+ extent:204,-348,628,-296
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:256
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:640,-344,684,-300
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:76,-404,200,-360
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Default"
+ }
+ wimp_icon {
+ extent:204,-408,628,-356
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:256
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:640,-404,684,-360
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:16,-612,704,-452
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-480,220,-436
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Font size "
+ text_and_sprite.size:*
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:76,-532,200,-488
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Default"
+ }
+ wimp_icon {
+ extent:204,-536,372,-484
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"12.3"
+ text.size:10
+ text.validation:"Pptr_write;Kta;A0-9."
+ }
+ wimp_icon {
+ extent:388,-528,420,-496
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:420,-528,452,-496
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:460,-532,500,-488
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"pt"
+ }
+ wimp_icon {
+ extent:52,-592,200,-548
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Minimum"
+ }
+ wimp_icon {
+ extent:204,-596,372,-544
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"12.3"
+ text.size:10
+ text.validation:"Pptr_write;Kta;A0-9."
+ }
+ wimp_icon {
+ extent:388,-588,420,-556
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:420,-588,452,-556
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:460,-592,500,-548
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"pt"
+ }
+ wimp_icon {
+ extent:24,-696,188,-644
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Default"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:340,-696,504,-644
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Cancel"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:520,-704,704,-636
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Set"
+ text.size:*
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"con_home"
+ visible:808,592,1608,888
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-296,800,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED
+ work_flags:
+ sprite_area:&1
+ xmin:800
+ ymin:296
+ text_only:"Home page"
+ wimp_icon {
+ extent:16,-184,784,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-52,284,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Home page "
+ text_and_sprite.size:16
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:40,-108,120,-64
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"URL"
+ }
+ wimp_icon {
+ extent:124,-112,712,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:""
+ text.size:128
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:720,-108,764,-64
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:13
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:124,-164,676,-120
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_SELECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Open browser window on start-up"
+ text_and_sprite.size:*
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:24,-264,188,-212
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Default"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:420,-264,584,-212
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Cancel"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:600,-272,784,-204
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Set"
+ text.size:*
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"con_image"
+ visible:1488,822,2164,1410
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-588,676,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED
+ work_flags:
+ sprite_area:&1
+ xmin:676
+ ymin:588
+ text_only:"Images"
+ wimp_icon {
+ extent:16,-292,660,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-52,284,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Image quality "
+ text_and_sprite.size:*
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:28,-108,204,-64
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Foreground"
+ }
+ wimp_icon {
+ extent:208,-112,592,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Error diffused"
+ text.size:256
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:600,-108,644,-64
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:13
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:24,-168,204,-124
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Background"
+ }
+ wimp_icon {
+ extent:208,-172,592,-120
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Error diffused"
+ text.size:256
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:600,-168,644,-124
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:13
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:32,-276,644,-180
+ icon_flags:wimp_ICON_BORDER
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ }
+ wimp_icon {
+ extent:16,-476,660,-320
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-348,236,-304
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Animations "
+ text_and_sprite.size:16
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:20,-404,208,-360
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Speed limit"
+ text.size:*
+ text.validation:""
+ }
+ wimp_icon {
+ extent:212,-408,380,-356
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"12.34"
+ text.size:*
+ text.validation:"Pptr_write;Kta;A0-9."
+ }
+ wimp_icon {
+ extent:396,-400,428,-368
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:428,-400,460,-368
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:468,-404,592,-360
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"seconds"
+ text.size:*
+ text.validation:""
+ }
+ wimp_icon {
+ extent:212,-460,556,-416
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Disable animations"
+ text_and_sprite.size:*
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:24,-560,188,-508
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Default"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:292,-560,456,-508
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Cancel"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:472,-568,656,-500
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Set"
+ text.size:*
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"con_inter"
+ visible:2320,436,3164,1220
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_FULL_SIZE | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-784,844,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:744
+ ymin:584
+ text_only:"Interface"
+ wimp_icon {
+ extent:16,-168,820,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-52,492,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Downloading / saving files "
+ text_and_sprite.size:*
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:32,-100,680,-56
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Strip filename extensions when saving"
+ text_and_sprite.size:39
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:32,-152,808,-108
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Request confirmation before overwriting files"
+ text_and_sprite.size:*
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:16,-344,820,-200
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:36,-224,496,-180
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Interactive features "
+ text_and_sprite.size:*
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:32,-276,744,-232
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Display recently visited URLs as you type"
+ text_and_sprite.size:*
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:32,-328,776,-284
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Hover URLs by the pointer for local history"
+ text_and_sprite.size:*
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:16,-468,820,-372
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:36,-400,240,-356
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Thumbnails "
+ text_and_sprite.size:23
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:32,-452,648,-408
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Use thumbnails for iconised windows"
+ text_and_sprite.size:42
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:24,-748,188,-696
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Default"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:456,-748,620,-696
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Cancel"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:636,-756,820,-688
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Set"
+ text.size:*
+ text.validation:"R6,3"
+ }
+ wimp_icon {
+ extent:16,-664,820,-496
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:36,-524,240,-480
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Hotlist"
+ text_and_sprite.size:23
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:32,-576,728,-532
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Use external hotlist apps when available"
+ text_and_sprite.size:*
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:28,-644,232,-592
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Hotlist path"
+ text.size:*
+ text.validation:""
+ }
+ wimp_icon {
+ extent:232,-644,800,-592
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"Writable icon"
+ text.size:256
+ text.validation:"Pptr_write;Kta"
+ }
+}
+
+wimp_window {
+ template_name:"con_lang"
+ visible:1574,956,2318,1256
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-300,744,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED
+ work_flags:
+ sprite_area:&1
+ xmin:744
+ ymin:300
+ text_only:"Language"
+ wimp_icon {
+ extent:16,-188,728,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-52,284,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Language "
+ text_and_sprite.size:16
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:48,-108,204,-64
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Interface"
+ }
+ wimp_icon {
+ extent:208,-112,660,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"1337"
+ text.size:256
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:668,-108,712,-64
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:13
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:44,-168,204,-124
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Web pages"
+ }
+ wimp_icon {
+ extent:208,-172,660,-120
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"8008135"
+ text.size:256
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:668,-168,712,-124
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:13
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:24,-272,188,-220
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Default"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:360,-272,524,-220
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Cancel"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:540,-280,724,-212
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Set"
+ text.size:*
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"con_theme"
+ visible:410,38,1318,642
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-604,908,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED
+ work_flags:
+ sprite_area:&1
+ xmin:640
+ ymin:604
+ text_only:"Themes"
+ wimp_icon {
+ extent:16,-492,892,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-52,332,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Available themes "
+ text_and_sprite.size:*
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:24,-576,188,-524
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Default"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:524,-576,688,-524
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Cancel"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:704,-584,888,-516
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Set"
+ text.size:*
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"download"
+ visible:486,610,1394,890
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BACK_ICON | wimp_WINDOW_CLOSE_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-280,908,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:80
+ ymin:28
+ text.text:"NetSurf Download"
+ text.size:*
+ text.validation:""
+ wimp_icon {
+ extent:420,-84,488,-16
+ icon_flags:wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK_DRAG
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ sprite.id:"file_ddc"
+ sprite.size:*
+ sprite.area:&1
+ }
+ wimp_icon {
+ extent:204,-152,900,-100
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"http://netsurf.sourceforge.net/netsurf.zip"
+ text.size:*
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:204,-212,900,-160
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"netsurf"
+ text.size:*
+ text.validation:"Pptr_write"
+ }
+ wimp_icon {
+ extent:204,-212,900,-160
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"ADFS::A7000+.$.netsurf"
+ text.size:*
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:8,-272,900,-220
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:12,-268,296,-224
+ icon_flags:wimp_ICON_FILLED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_CREAM
+ }
+ wimp_icon {
+ extent:12,-268,896,-224
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"84.4KB of 1.1MB 26.6KB/s 0:39 remaining"
+ text.size:*
+ text.validation:""
+ }
+ wimp_icon {
+ extent:92,-148,200,-104
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Source"
+ }
+ wimp_icon {
+ extent:12,-208,200,-164
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Destination"
+ }
+}
+
+wimp_window {
+ template_name:"history"
+ visible:252,388,1152,808
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_SCROLL_REPEAT | wimp_WINDOW_BACK_ICON | wimp_WINDOW_CLOSE_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_TOGGLE_ICON | wimp_WINDOW_VSCROLL | wimp_WINDOW_SIZE_ICON | wimp_WINDOW_HSCROLL | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_WHITE
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-880,1236,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:wimp_BUTTON_CLICK
+ sprite_area:&1
+ xmin:0
+ ymin:0
+ text.text:"History"
+ text.size:*
+ text.validation:""
+}
+
+wimp_window {
+ template_name:"info"
+ visible:752,452,1372,700
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_CREAM
+ scroll_inner:wimp_COLOUR_ORANGE
+ highlight_bg:wimp_COLOUR_LIGHT_GREY
+ extra_flags:
+ extent:0,-248,620,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ work_flags:wimp_BUTTON_CLICK
+ sprite_area:&1
+ xmin:620
+ ymin:248
+ text.text:"About this program"
+ text.size:*
+ text.validation:""
+ wimp_icon {
+ extent:672,-200,848,-152
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_RED
+ text_only:"OK"
+ }
+ wimp_icon {
+ extent:152,-60,612,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK_DRAG
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"NetSurf"
+ text.size:*
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:152,-120,612,-68
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK_DRAG
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Open source web browser"
+ text.size:*
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:152,-180,612,-128
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK_DRAG
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"© NetSurf developers"
+ text.size:40
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:152,-240,612,-188
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK_DRAG
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"CVS test build"
+ text.size:40
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:52,-56,148,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Name"
+ }
+ wimp_icon {
+ extent:24,-116,148,-72
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Purpose"
+ }
+ wimp_icon {
+ extent:24,-176,148,-132
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Authors"
+ }
+ wimp_icon {
+ extent:24,-236,148,-192
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Version"
+ }
+}
+
+wimp_window {
+ template_name:"login"
+ visible:582,400,1258,736
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-336,676,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:676
+ ymin:336
+ text.text:"Site Authentication"
+ text.size:*
+ text.validation:""
+ wimp_icon {
+ extent:532,-324,664,-256
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Login"
+ text.size:8
+ text.validation:"R6,3;Nok"
+ }
+ wimp_icon {
+ extent:380,-316,508,-264
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Cancel"
+ text.size:*
+ text.validation:"R5,3;Ncancel"
+ }
+ wimp_icon {
+ extent:168,-60,668,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"moo.yoo.com"
+ text.size:255
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:168,-120,668,-68
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"my sekr3t area"
+ text.size:255
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:168,-180,668,-128
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:""
+ text.size:255
+ text.validation:"Pptr_write;Kta;N401username"
+ }
+ wimp_icon {
+ extent:168,-240,668,-188
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:""
+ text.size:255
+ text.validation:"Pptr_write;Kta;D*"
+ }
+ wimp_icon {
+ extent:84,-56,164,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Host"
+ }
+ wimp_icon {
+ extent:8,-176,164,-132
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Username"
+ }
+ wimp_icon {
+ extent:20,-236,164,-192
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Password"
+ }
+ wimp_icon {
+ extent:64,-116,164,-72
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Realm"
+ }
+}
+
+wimp_window {
+ template_name:"new_entry"
+ visible:480,660,1080,880
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-220,600,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:600
+ ymin:220
+ text.text:""
+ text.size:32
+ text.validation:""
+ wimp_icon {
+ extent:12,-56,108,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Name"
+ }
+ wimp_icon {
+ extent:112,-60,588,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:""
+ text.size:128
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:12,-116,108,-72
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"URL"
+ }
+ wimp_icon {
+ extent:112,-120,532,-68
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:""
+ text.size:1024
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:304,-200,432,-148
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Cancel"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:456,-208,588,-140
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"OK"
+ text.size:8
+ text.validation:"R6,3"
+ }
+ wimp_icon {
+ extent:540,-116,584,-72
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:13
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+}
+
+wimp_window {
+ template_name:"new_folder"
+ visible:480,954,1080,1114
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-160,600,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:600
+ ymin:160
+ text.text:""
+ text.size:21
+ text.validation:""
+ wimp_icon {
+ extent:12,-56,108,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Name"
+ }
+ wimp_icon {
+ extent:112,-60,588,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:""
+ text.size:128
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:304,-140,432,-88
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Cancel"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:456,-148,588,-80
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"OK"
+ text.size:8
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"objectinfo"
+ visible:428,292,1216,480
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-188,788,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:wimp_BUTTON_CLICK
+ sprite_area:&1
+ xmin:788
+ ymin:188
+ text.text:"About this object"
+ text.size:20
+ text.validation:""
+ wimp_icon {
+ extent:204,-60,780,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:64
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:204,-120,780,-68
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:64
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:204,-180,780,-128
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:64
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:12,-80,84,-12
+ icon_flags:wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ sprite.id:"file_faf"
+ sprite.size:*
+ sprite.area:&1
+ }
+ wimp_icon {
+ extent:92,-116,200,-72
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Target"
+ }
+ wimp_icon {
+ extent:120,-176,200,-132
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Type"
+ }
+ wimp_icon {
+ extent:120,-56,200,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"URL"
+ }
+}
+
+wimp_window {
+ template_name:"open_url"
+ visible:248,266,1048,422
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-156,800,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:0
+ ymin:0
+ text_only:"Open URL"
+ wimp_icon {
+ extent:12,-56,92,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"URL"
+ }
+ wimp_icon {
+ extent:96,-60,736,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:""
+ text.size:1
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:504,-136,632,-84
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Cancel"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:656,-144,788,-76
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Open"
+ text.size:8
+ text.validation:"R6,3"
+ }
+ wimp_icon {
+ extent:744,-56,788,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:13
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+}
+
+wimp_window {
+ template_name:"pageinfo"
+ visible:310,528,1102,776
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-248,792,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:792
+ ymin:248
+ text.text:"About this document"
+ text.size:*
+ text.validation:""
+ wimp_icon {
+ extent:208,-60,784,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:64
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:208,-120,784,-68
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:64
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:208,-180,784,-128
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:64
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:208,-240,784,-188
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:64
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:12,-80,84,-12
+ icon_flags:wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ sprite.id:"file_faf"
+ sprite.size:*
+ sprite.area:&1
+ }
+ wimp_icon {
+ extent:124,-116,204,-72
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"URL"
+ }
+ wimp_icon {
+ extent:60,-176,204,-132
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Encoding"
+ }
+ wimp_icon {
+ extent:124,-236,204,-192
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Type"
+ }
+ wimp_icon {
+ extent:112,-56,204,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Title"
+ }
+}
+
+wimp_window {
+ template_name:"print"
+ visible:472,136,1132,708
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-572,700,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:600
+ ymin:572
+ text.text:"No Printer"
+ text.size:20
+ text.validation:""
+ wimp_icon {
+ extent:12,-176,652,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-100,504,-56
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:1
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"the bottom of the web page"
+ text_and_sprite.size:*
+ text_and_sprite.validation:"Sradiooff,radioon"
+ }
+ wimp_icon {
+ extent:32,-152,492,-108
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:1
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:6
+ text_and_sprite.validation:"Sradiooff,radioon"
+ }
+ wimp_icon {
+ extent:84,-156,164,-104
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"1"
+ text.size:3
+ text.validation:"Pptr_write;Kta;A0-9"
+ }
+ wimp_icon {
+ extent:176,-148,208,-116
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:208,-148,240,-116
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:244,-152,528,-108
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"sheets are filled"
+ text.size:*
+ text.validation:""
+ }
+ wimp_icon {
+ extent:12,-236,420,-192
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Show foreground images"
+ text_and_sprite.size:*
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:12,-288,420,-244
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Show background images"
+ text_and_sprite.size:*
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:12,-340,372,-296
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Print in background"
+ text_and_sprite.size:*
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:12,-404,180,-360
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_SELECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Upright"
+ text_and_sprite.size:*
+ text_and_sprite.validation:"Sradiooff,radioon"
+ }
+ wimp_icon {
+ extent:12,-452,196,-408
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Sideways"
+ text_and_sprite.size:*
+ text_and_sprite.validation:"Sradiooff,radioon"
+ }
+ wimp_icon {
+ extent:480,-456,560,-404
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"1"
+ text.size:3
+ text.validation:"Pptr_write;Kta;A0-9"
+ }
+ wimp_icon {
+ extent:572,-448,604,-416
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:604,-448,636,-416
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:364,-552,492,-500
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Cancel"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:516,-560,648,-492
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Print"
+ text.size:8
+ text.validation:"R6,3"
+ }
+ wimp_icon {
+ extent:368,-452,476,-408
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Copies"
+ }
+ wimp_icon {
+ extent:-16,-480,676,-472
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:32,-48,364,-4
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" End printing after "
+ text_and_sprite.size:*
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:232,-400,656,-356
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Print all text in black"
+ text_and_sprite.size:*
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+}
+
+wimp_window {
+ template_name:"query"
+ visible:142,562,942,806
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_LIGHT_GREY
+ extra_flags:
+ extent:0,-244,800,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:0
+ ymin:0
+ text.text:"Query from NetSurf"
+ text.size:21
+ text.validation:""
+ wimp_icon {
+ extent:92,-148,792,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Message"
+ text.size:300
+ text.validation:"R2;L"
+ }
+ wimp_icon {
+ extent:604,-232,788,-164
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"012345678901234567"
+ text.size:*
+ text.validation:"R6,3"
+ }
+ wimp_icon {
+ extent:424,-224,588,-172
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"012345678901234567"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:16,-224,132,-172
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Help"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:12,-80,80,-12
+ icon_flags:wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ sprite_only:"!netsurf"
+ }
+}
+
+wimp_window {
+ template_name:"saveas"
+ visible:824,676,1140,924
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BOUNDED_ONCE | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-248,316,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:308
+ ymin:244
+ text_only:"Save as"
+ wimp_icon {
+ extent:124,-84,192,-16
+ icon_flags:wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK_DRAG
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ sprite.id:"file_faf"
+ sprite.size:13
+ sprite.area:&1
+ }
+ wimp_icon {
+ extent:8,-152,308,-100
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:""
+ text.size:256
+ text.validation:"Pptr_write"
+ }
+ wimp_icon {
+ extent:172,-236,304,-168
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Save"
+ text.size:*
+ text.validation:"R6,3"
+ }
+ wimp_icon {
+ extent:20,-228,148,-176
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Cancel"
+ text.size:*
+ text.validation:"R5,3"
+ }
+}
+
+wimp_window {
+ template_name:"search"
+ visible:1036,684,1680,928
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-244,644,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:644
+ ymin:244
+ text.text:"Find text"
+ text.size:*
+ text.validation:""
+ wimp_icon {
+ extent:96,-60,580,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:""
+ text.size:32
+ text.validation:"KN;Pptr_write"
+ }
+ wimp_icon {
+ extent:96,-116,376,-72
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Case sensitive"
+ text_and_sprite.size:*
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:500,-228,632,-160
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Next"
+ text.size:10
+ text.validation:"R6,3"
+ }
+ wimp_icon {
+ extent:348,-220,484,-168
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Previous"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:204,-220,332,-168
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Cancel"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:16,-216,196,-172
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Not found"
+ text.size:*
+ text.validation:""
+ }
+ wimp_icon {
+ extent:-8,-148,652,-140
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:16,-56,92,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Find"
+ }
+ wimp_icon {
+ extent:588,-56,632,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_ICON_SHADED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:13
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:408,-116,592,-72
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Show all"
+ text_and_sprite.size:*
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+}
+
+wimp_window {
+ template_name:"theme_inst"
+ visible:374,590,1174,834
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-244,800,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:800
+ ymin:244
+ text.text:"NetSurf theme installer"
+ text.size:*
+ text.validation:""
+ wimp_icon {
+ extent:92,-148,792,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Message"
+ text.size:300
+ text.validation:"R2;L"
+ }
+ wimp_icon {
+ extent:640,-232,788,-164
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Install"
+ text.size:*
+ text.validation:"R6,3"
+ }
+ wimp_icon {
+ extent:488,-224,616,-172
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Cancel"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:12,-80,80,-12
+ icon_flags:wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ sprite_only:"!netsurf"
+ }
+}
+
+wimp_window {
+ template_name:"tooltip"
+ visible:884,620,1148,656
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BOUNDED_ONCE | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-36,2000,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED
+ work_flags:
+ sprite_area:&1
+ xmin:0
+ ymin:0
+ text_only:"<Untitled>"
+ wimp_icon {
+ extent:0,-40,300,4
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Comment"
+ text.size:256
+ text.validation:""
+ }
+}
+
+wimp_window {
+ template_name:"tree"
+ visible:530,654,1042,954
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_SCROLL_REPEAT | wimp_WINDOW_IGNORE_XEXTENT | wimp_WINDOW_IGNORE_YEXTENT | wimp_WINDOW_BOUNDED_ONCE | wimp_WINDOW_BACK_ICON | wimp_WINDOW_CLOSE_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_TOGGLE_ICON | wimp_WINDOW_VSCROLL | wimp_WINDOW_SIZE_ICON | wimp_WINDOW_HSCROLL | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_TRANSPARENT
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-880,1236,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:wimp_BUTTON_DOUBLE_CLICK_DRAG
+ sprite_area:&1
+ xmin:0
+ ymin:0
+ text.text:""
+ text.size:64
+ text.validation:""
+}
+
+wimp_window {
+ template_name:"url_suggest"
+ visible:320,390,1102,684
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_NO_BOUNDS | wimp_WINDOW_IGNORE_XEXTENT | wimp_WINDOW_IGNORE_YEXTENT | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_TRANSPARENT
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-65536,65536,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED
+ work_flags:wimp_BUTTON_CLICK
+ sprite_area:&1
+ xmin:0
+ ymin:0
+ text_only:"<Untitled>"
+}
+
+wimp_window {
+ template_name:"warning"
+ visible:320,850,1120,1094
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BOUNDED_ONCE | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-244,800,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:0
+ ymin:0
+ text.text:"Warning from NetSurf"
+ text.size:*
+ text.validation:""
+ wimp_icon {
+ extent:92,-148,792,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Message"
+ text.size:300
+ text.validation:"R2;L"
+ }
+ wimp_icon {
+ extent:608,-232,788,-164
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Continue"
+ text.size:*
+ text.validation:"R6,3"
+ }
+ wimp_icon {
+ extent:484,-224,584,-172
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Help"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:12,-80,80,-12
+ icon_flags:wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ sprite_only:"!netsurf"
+ }
+}
+
+wimp_window {
+ template_name:"zoom"
+ visible:182,356,630,578
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BOUNDED_ONCE | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-224,448,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED
+ work_flags:
+ sprite_area:&1
+ xmin:448
+ ymin:220
+ text_only:"Scale view"
+ wimp_icon {
+ extent:8,-56,100,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Scale"
+ }
+ wimp_icon {
+ extent:104,-60,204,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"100"
+ text.size:5
+ text.validation:"Pptr_write;KTA;A0-9."
+ }
+ wimp_icon {
+ extent:216,-52,248,-20
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"R5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:248,-52,280,-20
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"R5;sup,pup"
+ }
+ wimp_icon {
+ extent:284,-56,324,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_HCENTRED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"%"
+ }
+ wimp_icon {
+ extent:104,-112,416,-68
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Scale all frames"
+ text_and_sprite.size:20
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:-4,-132,716,-124
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:164,-204,292,-152
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Cancel"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:308,-212,440,-144
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Scale"
+ text.size:*
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"ssldisplay"
+ visible:862,768,1822,1308
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BOUNDED_ONCE | wimp_WINDOW_CLOSE_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-540,960,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:960
+ ymin:76
+ text.text:"SSL certificate"
+ text.size:*
+ text.validation:""
+ wimp_icon {
+ extent:16,-520,944,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-52,380,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Certificate details "
+ text_and_sprite.size:*
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:24,-108,148,-64
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Version"
+ }
+ wimp_icon {
+ extent:152,-108,264,-56
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:284,-104,456,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Valid from"
+ }
+ wimp_icon {
+ extent:460,-108,928,-56
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:68,-168,148,-124
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Type"
+ }
+ wimp_icon {
+ extent:152,-168,264,-116
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:268,-164,456,-120
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Valid until"
+ }
+ wimp_icon {
+ extent:460,-168,928,-116
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:40,-228,148,-184
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Serial"
+ }
+ wimp_icon {
+ extent:152,-228,928,-176
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:40,-288,148,-244
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Issuer"
+ }
+ wimp_icon {
+ extent:152,-376,928,-236
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R2;L"
+ }
+ wimp_icon {
+ extent:24,-432,148,-388
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Subject"
+ }
+ wimp_icon {
+ extent:152,-504,928,-384
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R2;L"
+ }
+}
+
+wimp_window {
+ template_name:"con_secure"
+ visible:1590,788,2182,1152
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-364,592,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED
+ work_flags:
+ sprite_area:&1
+ xmin:592
+ ymin:364
+ text_only:"Security"
+ wimp_icon {
+ extent:16,-120,576,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-52,364,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Cross-site privacy "
+ text_and_sprite.size:*
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:32,-104,568,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Send site referral information"
+ text_and_sprite.size:*
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:16,-252,576,-148
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-176,316,-132
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Site history "
+ text_and_sprite.size:18
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:24,-228,164,-184
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Duration"
+ }
+ wimp_icon {
+ extent:168,-232,336,-180
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"12"
+ text.size:4
+ text.validation:"Pptr_write;Kta;A0-9"
+ }
+ wimp_icon {
+ extent:352,-224,384,-192
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:384,-224,416,-192
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:424,-228,500,-184
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"days"
+ }
+ wimp_icon {
+ extent:24,-336,188,-284
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Default"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:208,-336,372,-284
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Cancel"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:388,-344,572,-276
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Set"
+ text.size:*
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"con_content"
+ visible:1248,854,1912,1354
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_FULL_SIZE | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-500,664,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:640
+ ymin:452
+ text_only:"Content"
+ wimp_icon {
+ extent:16,-272,644,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-52,492,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Content blocking "
+ text_and_sprite.size:29
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:32,-100,392,-56
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Hide advertisements"
+ text_and_sprite.size:39
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:32,-152,440,-108
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Disable pop-up windows"
+ text_and_sprite.size:46
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:32,-256,344,-212
+#ifdef WITH_PLUGIN
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+#else
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_DELETED | wimp_BUTTON_RADIO
+#endif
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Disable plug-ins"
+ text_and_sprite.size:42
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:16,-384,644,-292
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-320,492,-276
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Link targets "
+ text_and_sprite.size:29
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:32,-368,632,-324
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Allow links to open in new windows"
+ text_and_sprite.size:*
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:24,-468,188,-416
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Default"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:280,-468,444,-416
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Cancel"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:460,-476,644,-408
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Set"
+ text.size:*
+ text.validation:"R6,3"
+ }
+ wimp_icon {
+ extent:32,-204,376,-160
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Disable JavaScript"
+ text_and_sprite.size:19
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+}
+
+wimp_window {
+ template_name:"con_connect"
+ visible:1328,566,2008,1234
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-668,680,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED
+ work_flags:
+ sprite_area:&1
+ xmin:660
+ ymin:668
+ text_only:"Connection"
+ wimp_icon {
+ extent:16,-304,664,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:28,-52,232,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" HTTP Proxy "
+ text_and_sprite.size:15
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:32,-104,204,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Proxy type"
+ }
+ wimp_icon {
+ extent:208,-108,592,-56
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:32
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:600,-104,644,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:124,-164,204,-120
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Host"
+ text.size:*
+ text.validation:""
+ }
+ wimp_icon {
+ extent:208,-168,524,-116
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"myhost.proxy"
+ text.size:255
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:520,-164,548,-120
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_HCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:":"
+ text.size:*
+ text.validation:""
+ }
+ wimp_icon {
+ extent:544,-168,648,-116
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"8080"
+ text.size:8
+ text.validation:"Pptr_write;Kta;A0-9"
+ }
+ wimp_icon {
+ extent:48,-224,204,-180
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Username"
+ text.size:*
+ text.validation:""
+ }
+ wimp_icon {
+ extent:208,-228,648,-176
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"k1dd13"
+ text.size:64
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:60,-284,204,-240
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Password"
+ text.size:*
+ text.validation:""
+ }
+ wimp_icon {
+ extent:208,-288,648,-236
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"1337"
+ text.size:64
+ text.validation:"Pptr_write;Kta;D*"
+ }
+ wimp_icon {
+ extent:16,-552,664,-332
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-360,204,-316
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Fetching "
+ text_and_sprite.size:15
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:80,-412,340,-368
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Maximum fetches"
+ text.size:*
+ text.validation:""
+ }
+ wimp_icon {
+ extent:344,-416,552,-364
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"99"
+ text.size:*
+ text.validation:"Pptr_write;Kta;A0-9"
+ }
+ wimp_icon {
+ extent:568,-408,600,-376
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:600,-408,632,-376
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:72,-472,340,-428
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Fetches per host"
+ text.size:18
+ text.validation:""
+ }
+ wimp_icon {
+ extent:344,-476,552,-424
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"99"
+ text.size:4
+ text.validation:"Pptr_write;Kta;A0-9"
+ }
+ wimp_icon {
+ extent:568,-468,604,-436
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:600,-468,632,-436
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:40,-532,340,-488
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Cached connections"
+ text.size:*
+ text.validation:""
+ }
+ wimp_icon {
+ extent:344,-536,552,-484
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"99"
+ text.size:4
+ text.validation:"Pptr_write;Kta;A0-9"
+ }
+ wimp_icon {
+ extent:568,-528,604,-496
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:600,-528,632,-496
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:24,-640,188,-588
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Default"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:296,-640,460,-588
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Cancel"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:476,-648,660,-580
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Set"
+ text.size:*
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"sslcert"
+ visible:348,306,1136,898
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BOUNDED_ONCE | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-592,788,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:788
+ ymin:592
+ text.text:"SSL certificate problem"
+ text.size:*
+ text.validation:""
+ wimp_icon {
+ extent:16,-108,772,-16
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"NetSurf failed to verify the authenticity of an SSL certificate. Please verify the details presented below."
+ text.size:150
+ text.validation:"R2;L"
+ }
+ wimp_icon {
+ extent:16,-484,772,-136
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-164,380,-120
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Certificate chain "
+ text_and_sprite.size:22
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:404,-564,568,-512
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Reject"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:588,-572,772,-504
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Accept"
+ text.size:8
+ text.validation:"R6,3"
+ }
+}
diff --git a/frontends/riscos/templates/fr b/frontends/riscos/templates/fr
new file mode 100644
index 000000000..67792642c
--- /dev/null
+++ b/frontends/riscos/templates/fr
@@ -0,0 +1,3862 @@
+Template:
+
+wimp_window {
+ template_name:"configure"
+ visible:378,820,1046,1126
+ xscroll:0
+ yscroll:-574
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BACK_ICON | wimp_WINDOW_CLOSE_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_TOGGLE_ICON | wimp_WINDOW_VSCROLL | wimp_WINDOW_SIZE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_LIGHT_GREY
+ extra_flags:
+ extent:0,-880,1236,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:4
+ ymin:156
+ text.text:"NetSurf configuration"
+ text.size:*
+ text.validation:""
+}
+
+wimp_window {
+ template_name:"con_cache"
+ visible:564,536,1152,964
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-428,588,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED
+ work_flags:
+ sprite_area:&1
+ xmin:588
+ ymin:240
+ text_only:"Cache"
+ wimp_icon {
+ extent:16,-124,568,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-52,284,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Cache mémoire "
+ text_and_sprite.size:*
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:44,-104,164,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Taille"
+ text.size:13
+ text.validation:""
+ }
+ wimp_icon {
+ extent:168,-108,336,-56
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"512.0"
+ text.size:10
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:352,-100,384,-68
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:384,-100,416,-68
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:424,-104,480,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"MB"
+ }
+ wimp_icon {
+ extent:16,-312,568,-152
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-180,268,-136
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Disc cache "
+ text_and_sprite.size:*
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:44,-232,164,-188
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Taille"
+ text.size:13
+ text.validation:""
+ }
+ wimp_icon {
+ extent:168,-236,336,-184
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"512"
+ text.size:10
+ text.validation:"Pptr_write;Kta;A0-9"
+ }
+ wimp_icon {
+ extent:352,-228,384,-196
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:384,-228,416,-196
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:424,-232,480,-192
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"MB"
+ }
+ wimp_icon {
+ extent:44,-292,164,-248
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Expiry"
+ text.size:13
+ text.validation:""
+ }
+ wimp_icon {
+ extent:168,-296,336,-244
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"512"
+ text.size:10
+ text.validation:"Pptr_write;Kta;A0-9"
+ }
+ wimp_icon {
+ extent:352,-288,384,-256
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:384,-288,416,-256
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:424,-292,500,-252
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"days"
+ }
+ wimp_icon {
+ extent:24,-396,188,-344
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Par défaut"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:204,-396,368,-344
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Annuler"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:384,-404,568,-336
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Valider"
+ text.size:*
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"con_fonts"
+ visible:316,250,1028,974
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_FULL_SIZE | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-724,712,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:712
+ ymin:724
+ text_only:"Fontes"
+ wimp_icon {
+ extent:16,-424,696,-28
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-52,236,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Polices "
+ text_and_sprite.size:13
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:20,-104,192,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Sans-serif"
+ }
+ wimp_icon {
+ extent:196,-108,620,-56
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:256
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:632,-104,676,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:100,-164,192,-120
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Serif"
+ }
+ wimp_icon {
+ extent:196,-168,620,-116
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:256
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:632,-164,676,-120
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:28,-224,192,-180
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Monospace"
+ }
+ wimp_icon {
+ extent:196,-228,620,-176
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:256
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:632,-224,676,-180
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:13
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:68,-284,192,-240
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Cursive"
+ }
+ wimp_icon {
+ extent:196,-288,620,-236
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:256
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:632,-284,676,-240
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:28,-344,192,-300
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Fantaisiste"
+ }
+ wimp_icon {
+ extent:196,-348,620,-296
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:256
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:632,-344,676,-300
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:48,-404,192,-360
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Par défaut"
+ }
+ wimp_icon {
+ extent:196,-408,620,-356
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:256
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:632,-404,676,-360
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:16,-612,696,-452
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-480,316,-436
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Taille de fonte "
+ text_and_sprite.size:*
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:28,-532,192,-488
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Par défaut"
+ }
+ wimp_icon {
+ extent:196,-536,364,-484
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"12.3"
+ text.size:10
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:380,-528,412,-496
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:412,-528,444,-496
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:452,-532,492,-488
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"pt"
+ }
+ wimp_icon {
+ extent:60,-592,192,-548
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Minimum"
+ }
+ wimp_icon {
+ extent:196,-596,364,-544
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"12.3"
+ text.size:10
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:380,-588,412,-556
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:412,-588,444,-556
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:452,-592,492,-548
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"pt"
+ }
+ wimp_icon {
+ extent:24,-696,188,-644
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Par défaut"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:332,-696,496,-644
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Annuler"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:512,-704,696,-636
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Valider"
+ text.size:*
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"con_home"
+ visible:288,150,1088,446
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BOUNDED_ONCE | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-296,800,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:800
+ ymin:296
+ text.text:"Page d'accueil"
+ text.size:*
+ text.validation:""
+ wimp_icon {
+ extent:16,-184,784,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-52,300,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Page d'accueil "
+ text_and_sprite.size:*
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:48,-108,120,-64
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"URL"
+ }
+ wimp_icon {
+ extent:124,-112,712,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:""
+ text.size:128
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:720,-108,764,-64
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:13
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:124,-164,676,-120
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Ouvrir une fenêtre au démarrage"
+ text_and_sprite.size:*
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:24,-264,188,-212
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Par défaut"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:416,-264,580,-212
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Annuler"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:596,-272,780,-204
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Valider"
+ text.size:*
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"con_image"
+ visible:828,908,1504,1496
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-588,676,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED
+ work_flags:
+ sprite_area:&1
+ xmin:676
+ ymin:588
+ text_only:"Images"
+ wimp_icon {
+ extent:16,-292,660,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-52,332,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Qualité d'images "
+ text_and_sprite.size:*
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:24,-108,204,-64
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Premier plan"
+ text.size:*
+ text.validation:""
+ }
+ wimp_icon {
+ extent:208,-112,592,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Error diffused"
+ text.size:256
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:600,-108,644,-64
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:13
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:32,-168,204,-124
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Fond"
+ }
+ wimp_icon {
+ extent:208,-172,592,-120
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Error diffused"
+ text.size:256
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:600,-168,644,-124
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:13
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:32,-276,644,-180
+ icon_flags:wimp_ICON_BORDER
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ }
+ wimp_icon {
+ extent:16,-476,660,-320
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-348,284,-304
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Animations "
+ text_and_sprite.size:16
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:20,-404,208,-360
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Vitesse limite"
+ text.size:*
+ text.validation:""
+ }
+ wimp_icon {
+ extent:212,-408,380,-356
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"12.34"
+ text.size:*
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:396,-400,428,-368
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:428,-400,460,-368
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:468,-404,592,-360
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"secondes"
+ text.size:*
+ text.validation:""
+ }
+ wimp_icon {
+ extent:212,-460,628,-416
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Désactiver les animations"
+ text_and_sprite.size:*
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:24,-560,188,-508
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Par défaut"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:296,-560,460,-508
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Annuler"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:476,-568,660,-500
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Valider"
+ text.size:*
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"con_lang"
+ visible:770,1102,1514,1402
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BOUNDED_ONCE | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-300,744,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:744
+ ymin:300
+ text_only:"Langue"
+ wimp_icon {
+ extent:16,-188,728,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-52,284,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Langue "
+ text_and_sprite.size:*
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:48,-108,204,-64
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Interface"
+ }
+ wimp_icon {
+ extent:208,-112,660,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"1337"
+ text.size:256
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:668,-108,712,-64
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:13
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:40,-168,204,-124
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Pages web"
+ }
+ wimp_icon {
+ extent:208,-172,660,-120
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"8008135"
+ text.size:256
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:668,-168,712,-124
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:13
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:24,-268,188,-216
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Par défaut"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:360,-268,524,-216
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Annuler"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:540,-276,724,-208
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Valider"
+ text.size:*
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"con_theme"
+ visible:408,370,1316,974
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-604,908,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:640
+ ymin:604
+ text_only:"Thèmes"
+ wimp_icon {
+ extent:16,-492,892,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-52,364,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Thèmes disponibles "
+ text_and_sprite.size:*
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:24,-576,188,-524
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Par défaut"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:524,-576,688,-524
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Annuler"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:704,-584,888,-516
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Valider"
+ text.size:*
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"download"
+ visible:486,610,1394,890
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BOUNDED_ONCE | wimp_WINDOW_BACK_ICON | wimp_WINDOW_CLOSE_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-280,908,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:80
+ ymin:28
+ text.text:"Téléchargement de Netsurf"
+ text.size:*
+ text.validation:""
+ wimp_icon {
+ extent:420,-84,488,-16
+ icon_flags:wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK_DRAG
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ sprite.id:"file_ddc"
+ sprite.size:*
+ sprite.area:&1
+ }
+ wimp_icon {
+ extent:204,-152,900,-100
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"http://netsurf.sourceforge.net/netsurf.zip"
+ text.size:*
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:204,-212,900,-160
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"netsurf"
+ text.size:*
+ text.validation:"Pptr_write"
+ }
+ wimp_icon {
+ extent:204,-212,900,-160
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"ADFS::A7000+.$.netsurf"
+ text.size:*
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:8,-272,900,-220
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:12,-268,296,-224
+ icon_flags:wimp_ICON_FILLED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_CREAM
+ }
+ wimp_icon {
+ extent:12,-268,896,-224
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"84.4KB of 1.1MB 26.6KB/s 0:39 remaining"
+ text.size:*
+ text.validation:""
+ }
+ wimp_icon {
+ extent:92,-148,200,-104
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Source"
+ }
+ wimp_icon {
+ extent:12,-208,200,-164
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Destination"
+ }
+}
+
+wimp_window {
+ template_name:"history"
+ visible:252,388,1152,808
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_SCROLL_REPEAT | wimp_WINDOW_BOUNDED_ONCE | wimp_WINDOW_BACK_ICON | wimp_WINDOW_CLOSE_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_TOGGLE_ICON | wimp_WINDOW_VSCROLL | wimp_WINDOW_SIZE_ICON | wimp_WINDOW_HSCROLL | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_WHITE
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-880,1236,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:wimp_BUTTON_CLICK
+ sprite_area:&1
+ xmin:0
+ ymin:0
+ text.text:"Historique"
+ text.size:*
+ text.validation:""
+}
+
+wimp_window {
+ template_name:"info"
+ visible:506,58,1126,306
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BOUNDED_ONCE | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_CREAM
+ scroll_inner:wimp_COLOUR_ORANGE
+ highlight_bg:wimp_COLOUR_LIGHT_GREY
+ extra_flags:
+ extent:0,-248,620,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ work_flags:wimp_BUTTON_CLICK
+ sprite_area:&1
+ xmin:0
+ ymin:0
+ text.text:"A propos de ce programme"
+ text.size:*
+ text.validation:""
+ wimp_icon {
+ extent:676,-204,852,-156
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_RED
+ text_only:"OK"
+ }
+ wimp_icon {
+ extent:152,-60,612,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK_DRAG
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"NetSurf"
+ text.size:*
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:152,-120,612,-68
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK_DRAG
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Navigateur web libre"
+ text.size:*
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:152,-180,612,-128
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK_DRAG
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"© Développeurs NetSurf"
+ text.size:40
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:152,-240,612,-188
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK_DRAG
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"CVS test build"
+ text.size:40
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:76,-56,148,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Nom"
+ }
+ wimp_icon {
+ extent:20,-116,148,-72
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Fonction"
+ }
+ wimp_icon {
+ extent:24,-176,148,-132
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Auteurs"
+ }
+ wimp_icon {
+ extent:24,-236,148,-192
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Version"
+ }
+ wimp_icon {
+ extent:4,-8,4,262328
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_DELETED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text_only:"<Deleted>"
+ }
+}
+
+wimp_window {
+ template_name:"login"
+ visible:566,258,1242,594
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BOUNDED_ONCE | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-336,676,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:676
+ ymin:336
+ text.text:"Authentification du Site"
+ text.size:*
+ text.validation:""
+ wimp_icon {
+ extent:532,-324,664,-256
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Entrer"
+ text.size:8
+ text.validation:"R6,3;Nok"
+ }
+ wimp_icon {
+ extent:376,-316,508,-264
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Annuler"
+ text.size:*
+ text.validation:"R5,3;Ncancel"
+ }
+ wimp_icon {
+ extent:200,-60,668,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"moo.yoo.com"
+ text.size:255
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:200,-120,668,-68
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"my sekr3t area"
+ text.size:255
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:200,-180,668,-128
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:""
+ text.size:255
+ text.validation:"Pptr_write;Kta;N401username"
+ }
+ wimp_icon {
+ extent:200,-240,668,-188
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:""
+ text.size:255
+ text.validation:"Pptr_write;Kta;D*"
+ }
+ wimp_icon {
+ extent:120,-56,196,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Hôte"
+ }
+ wimp_icon {
+ extent:8,-176,196,-132
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Identifiant"
+ text.size:*
+ text.validation:""
+ }
+ wimp_icon {
+ extent:8,-236,196,-192
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Code secret"
+ text.size:*
+ text.validation:""
+ }
+ wimp_icon {
+ extent:68,-116,196,-72
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Domaine"
+ }
+}
+
+wimp_window {
+ template_name:"new_entry"
+ visible:1120,590,1720,810
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-220,600,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:600
+ ymin:220
+ text.text:""
+ text.size:32
+ text.validation:""
+ wimp_icon {
+ extent:12,-56,108,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Nom"
+ }
+ wimp_icon {
+ extent:112,-60,588,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:""
+ text.size:128
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:12,-116,108,-72
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"URL"
+ }
+ wimp_icon {
+ extent:112,-120,532,-68
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:""
+ text.size:1024
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:304,-200,436,-148
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Annuler"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:456,-208,588,-140
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"OK"
+ text.size:8
+ text.validation:"R6,3"
+ }
+ wimp_icon {
+ extent:540,-116,584,-72
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:13
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+}
+
+wimp_window {
+ template_name:"new_folder"
+ visible:596,278,1196,438
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-160,600,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:600
+ ymin:160
+ text.text:""
+ text.size:25
+ text.validation:""
+ wimp_icon {
+ extent:12,-56,108,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Nom"
+ }
+ wimp_icon {
+ extent:112,-60,588,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:""
+ text.size:128
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:304,-140,436,-88
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Annuler"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:456,-148,588,-80
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"OK"
+ text.size:8
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"objectinfo"
+ visible:276,892,1064,1084
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-192,788,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:wimp_BUTTON_CLICK
+ sprite_area:&1
+ xmin:0
+ ymin:0
+ text.text:"À propos de cet objet"
+ text.size:*
+ text.validation:""
+ wimp_icon {
+ extent:208,-60,784,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:64
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:208,-120,784,-68
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:64
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:208,-180,784,-128
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:64
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:12,-80,84,-12
+ icon_flags:wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ sprite.id:"file_faf"
+ sprite.size:*
+ sprite.area:&1
+ }
+ wimp_icon {
+ extent:112,-116,204,-72
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Cible"
+ }
+ wimp_icon {
+ extent:124,-176,204,-132
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Type"
+ }
+ wimp_icon {
+ extent:132,-56,204,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"URL"
+ }
+}
+
+wimp_window {
+ template_name:"open_url"
+ visible:440,134,1240,290
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-156,800,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:0
+ ymin:0
+ text.text:"Ouvrir l'URL"
+ text.size:*
+ text.validation:""
+ wimp_icon {
+ extent:20,-56,92,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"URL"
+ }
+ wimp_icon {
+ extent:96,-60,736,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:""
+ text.size:1
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:504,-136,632,-84
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Annuler"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:656,-144,788,-76
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Ouvrir"
+ text.size:8
+ text.validation:"R6,3"
+ }
+ wimp_icon {
+ extent:744,-56,788,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:13
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+}
+
+wimp_window {
+ template_name:"pageinfo"
+ visible:348,298,1140,546
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-248,792,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:wimp_BUTTON_CLICK
+ sprite_area:&1
+ xmin:792
+ ymin:248
+ text.text:"À propos de ce document"
+ text.size:*
+ text.validation:""
+ wimp_icon {
+ extent:208,-60,784,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:64
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:208,-120,784,-68
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:64
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:208,-180,784,-128
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:64
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:208,-240,784,-188
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:64
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:12,-80,84,-12
+ icon_flags:wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ sprite.id:"file_faf"
+ sprite.size:*
+ sprite.area:&1
+ }
+ wimp_icon {
+ extent:132,-116,204,-72
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"URL"
+ }
+ wimp_icon {
+ extent:60,-176,204,-132
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Encodage"
+ }
+ wimp_icon {
+ extent:124,-236,204,-192
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Type"
+ }
+ wimp_icon {
+ extent:112,-56,204,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Titre"
+ }
+}
+
+wimp_window {
+ template_name:"print"
+ visible:464,144,1064,716
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-572,600,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:0
+ ymin:0
+ text.text:"Pas d'imprimante"
+ text.size:20
+ text.validation:""
+ wimp_icon {
+ extent:12,-176,588,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:1
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-100,504,-56
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:1
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"le bas de la page web"
+ text_and_sprite.size:27
+ text_and_sprite.validation:"Sradiooff,radioon"
+ }
+ wimp_icon {
+ extent:32,-152,492,-108
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:1
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:6
+ text_and_sprite.validation:"Sradiooff,radioon"
+ }
+ wimp_icon {
+ extent:84,-156,164,-104
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"1"
+ text.size:3
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:176,-148,208,-116
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:208,-148,240,-116
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:244,-152,528,-108
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"feuilles remplies"
+ text.size:*
+ text.validation:""
+ }
+ wimp_icon {
+ extent:12,-236,580,-192
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Imprimer les images d'avant-plan"
+ text_and_sprite.size:*
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:12,-288,500,-244
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Imprimer les images de fond"
+ text_and_sprite.size:*
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:12,-340,468,-296
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Imprimer en tâche de fond"
+ text_and_sprite.size:*
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:12,-404,180,-360
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Portrait"
+ text_and_sprite.size:*
+ text_and_sprite.validation:"Sradiooff,radioon"
+ }
+ wimp_icon {
+ extent:12,-452,196,-408
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Paysage"
+ text_and_sprite.size:9
+ text_and_sprite.validation:"Sradiooff,radioon"
+ }
+ wimp_icon {
+ extent:428,-456,508,-404
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"1"
+ text.size:3
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:524,-448,556,-416
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:556,-448,588,-416
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:268,-552,400,-500
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Annuler"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:424,-560,588,-492
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Imprimer"
+ text.size:*
+ text.validation:"R6,3"
+ }
+ wimp_icon {
+ extent:284,-452,424,-408
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Copies"
+ }
+ wimp_icon {
+ extent:-12,-480,604,-472
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:32,-52,460,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Finir l'impression après "
+ text_and_sprite.size:*
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:252,-400,676,-356
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Tout le texte en noir"
+ text_and_sprite.size:24
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+}
+
+wimp_window {
+ template_name:"query"
+ visible:426,1082,1226,1326
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_LIGHT_GREY
+ extra_flags:
+ extent:0,-244,800,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:0
+ ymin:0
+ text.text:"Question de NetSurf"
+ text.size:21
+ text.validation:""
+ wimp_icon {
+ extent:92,-148,792,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Message"
+ text.size:300
+ text.validation:"R2;L"
+ }
+ wimp_icon {
+ extent:636,-232,788,-164
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"012345678901234567"
+ text.size:*
+ text.validation:"R6,3"
+ }
+ wimp_icon {
+ extent:504,-224,620,-172
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"012345678901234567"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:8,-224,124,-172
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Aide"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:12,-80,80,-12
+ icon_flags:wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ sprite_only:"!netsurf"
+ }
+}
+
+wimp_window {
+ template_name:"saveas"
+ visible:682,168,998,416
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-248,316,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:0
+ ymin:0
+ text_only:"Sauver sous"
+ wimp_icon {
+ extent:124,-84,192,-16
+ icon_flags:wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK_DRAG
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ sprite.id:"file_faf"
+ sprite.size:13
+ sprite.area:&1
+ }
+ wimp_icon {
+ extent:8,-152,308,-100
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:""
+ text.size:256
+ text.validation:"Pptr_write"
+ }
+ wimp_icon {
+ extent:172,-236,304,-168
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Sauver"
+ text.size:*
+ text.validation:"R6,3"
+ }
+ wimp_icon {
+ extent:20,-228,148,-176
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Annuler"
+ text.size:*
+ text.validation:"R5,3"
+ }
+}
+
+wimp_window {
+ template_name:"search"
+ visible:170,720,814,964
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BOUNDED_ONCE | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-244,644,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:644
+ ymin:244
+ text.text:"Recherche de texte"
+ text.size:*
+ text.validation:""
+ wimp_icon {
+ extent:192,-60,580,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:""
+ text.size:32
+ text.validation:"KN;Pptr_write"
+ }
+ wimp_icon {
+ extent:32,-116,364,-72
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Sensible à la casse"
+ text_and_sprite.size:*
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:500,-228,632,-160
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Suivant"
+ text.size:10
+ text.validation:"R6,3"
+ }
+ wimp_icon {
+ extent:340,-220,492,-168
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Précédent"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:204,-220,332,-168
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Annuler"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:16,-216,196,-172
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Non trouvé"
+ text.size:*
+ text.validation:""
+ }
+ wimp_icon {
+ extent:-8,-148,652,-140
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:16,-56,184,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Chercher"
+ }
+ wimp_icon {
+ extent:588,-56,632,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_ICON_SHADED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:13
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:400,-116,628,-72
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Tout montrer"
+ text_and_sprite.size:*
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+}
+
+wimp_window {
+ template_name:"theme_inst"
+ visible:458,234,1258,478
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BOUNDED_ONCE | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-244,800,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:0
+ ymin:0
+ text.text:"Installateur de Thèmes de NetSurf"
+ text.size:*
+ text.validation:""
+ wimp_icon {
+ extent:92,-148,792,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Message"
+ text.size:300
+ text.validation:"R2;L"
+ }
+ wimp_icon {
+ extent:608,-232,788,-164
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Installer"
+ text.size:*
+ text.validation:"R6,3"
+ }
+ wimp_icon {
+ extent:452,-224,584,-172
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Annuler"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:12,-80,80,-12
+ icon_flags:wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ sprite_only:"!netsurf"
+ }
+}
+
+wimp_window {
+ template_name:"tooltip"
+ visible:884,620,1148,656
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BOUNDED_ONCE | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-36,2000,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED
+ work_flags:
+ sprite_area:&1
+ xmin:0
+ ymin:0
+ text_only:"<Untitled>"
+ wimp_icon {
+ extent:0,-40,300,4
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Comment"
+ text.size:256
+ text.validation:""
+ }
+}
+
+wimp_window {
+ template_name:"tree"
+ visible:530,654,1042,954
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_SCROLL_REPEAT | wimp_WINDOW_IGNORE_XEXTENT | wimp_WINDOW_IGNORE_YEXTENT | wimp_WINDOW_BOUNDED_ONCE | wimp_WINDOW_BACK_ICON | wimp_WINDOW_CLOSE_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_TOGGLE_ICON | wimp_WINDOW_VSCROLL | wimp_WINDOW_SIZE_ICON | wimp_WINDOW_HSCROLL | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_TRANSPARENT
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-880,1236,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:wimp_BUTTON_DOUBLE_CLICK_DRAG
+ sprite_area:&1
+ xmin:0
+ ymin:0
+ text.text:""
+ text.size:64
+ text.validation:""
+}
+
+wimp_window {
+ template_name:"url_suggest"
+ visible:320,390,1102,684
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_NO_BOUNDS | wimp_WINDOW_IGNORE_XEXTENT | wimp_WINDOW_IGNORE_YEXTENT | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_TRANSPARENT
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-65536,65536,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED
+ work_flags:wimp_BUTTON_CLICK
+ sprite_area:&1
+ xmin:0
+ ymin:0
+ text_only:"<Untitled>"
+}
+
+wimp_window {
+ template_name:"warning"
+ visible:320,524,1120,768
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-244,800,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:0
+ ymin:0
+ text.text:"Alerte de NetSurf"
+ text.size:21
+ text.validation:""
+ wimp_icon {
+ extent:92,-148,792,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Message"
+ text.size:300
+ text.validation:"R2;L"
+ }
+ wimp_icon {
+ extent:624,-232,788,-164
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Continuer"
+ text.size:*
+ text.validation:"R6,3"
+ }
+ wimp_icon {
+ extent:480,-224,600,-172
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Aide"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:12,-80,80,-12
+ icon_flags:wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ sprite_only:"!netsurf"
+ }
+}
+
+wimp_window {
+ template_name:"zoom"
+ visible:828,402,1276,626
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-224,448,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ work_flags:
+ sprite_area:&1
+ xmin:448
+ ymin:224
+ text.text:"Ajuster la vue"
+ text.size:*
+ text.validation:""
+ wimp_icon {
+ extent:8,-56,132,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Echelle"
+ }
+ wimp_icon {
+ extent:136,-60,236,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"100"
+ text.size:5
+ text.validation:"Pptr_write;KTA;A0-9."
+ }
+ wimp_icon {
+ extent:248,-52,280,-20
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"R5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:280,-52,312,-20
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"R5;sup,pup"
+ }
+ wimp_icon {
+ extent:316,-56,356,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_HCENTRED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"%"
+ }
+ wimp_icon {
+ extent:136,-112,448,-68
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Scale all frames"
+ text_and_sprite.size:20
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:-12,-132,564,-124
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:20,-204,152,-152
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Annuler"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:176,-212,436,-144
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Redimensionner"
+ text.size:*
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"con_secure"
+ visible:872,490,1464,854
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_FULL_SIZE | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-364,592,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:592
+ ymin:364
+ text_only:"Sécurité"
+ wimp_icon {
+ extent:16,-120,576,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-52,492,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Confidentialité inter-site "
+ text_and_sprite.size:*
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:32,-104,568,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Envoyer l'info de renvoi de site"
+ text_and_sprite.size:40
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:16,-252,576,-148
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-176,380,-132
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Historique de sites "
+ text_and_sprite.size:*
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:24,-228,164,-184
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Durée"
+ }
+ wimp_icon {
+ extent:168,-232,336,-180
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"12"
+ text.size:4
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:352,-224,384,-192
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:384,-224,416,-192
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:424,-228,500,-184
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"jours"
+ }
+ wimp_icon {
+ extent:24,-336,188,-284
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Par défaut"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:208,-336,372,-284
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Annuler"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:388,-344,572,-276
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Valider"
+ text.size:*
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"con_content"
+ visible:598,836,1350,1336
+ xscroll:0
+ yscroll:0
+ next:
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_OPEN | wimp_WINDOW_HAS_FOCUS | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-500,752,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:640
+ ymin:448
+ text_only:"Contenu"
+ wimp_icon {
+ extent:16,-272,732,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-52,492,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Blocage de contenu "
+ text_and_sprite.size:*
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:32,-100,392,-56
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Cacher les pubs"
+ text_and_sprite.size:39
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:32,-152,516,-108
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Désactiver les fenêtres pop-up"
+ text_and_sprite.size:46
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:32,-256,404,-212
+#ifdef WITH_PLUGIN
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+#else
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_DELETED | wimp_BUTTON_RADIO
+#endif
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Désactiver les plug-ins"
+ text_and_sprite.size:42
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:16,-384,732,-292
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-320,492,-276
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Cibles de liens "
+ text_and_sprite.size:*
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:32,-372,716,-324
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Autoriser les liens à ouvrir une nouvelle fenêtre"
+ text_and_sprite.size:*
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:24,-468,188,-416
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Par défaut"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:372,-468,536,-416
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Annuler"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:544,-476,728,-408
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Valider"
+ text.size:*
+ text.validation:"R6,3"
+ }
+ wimp_icon {
+ extent:32,-204,376,-160
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Disable JavaScript"
+ text_and_sprite.size:19
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+}
+
+wimp_window {
+ template_name:"con_connect"
+ visible:446,482,1106,1150
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-668,660,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED
+ work_flags:
+ sprite_area:&1
+ xmin:660
+ ymin:668
+ text_only:"Connection"
+ wimp_icon {
+ extent:16,-304,644,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:28,-52,264,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Proxy HTTP "
+ text_and_sprite.size:*
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:32,-104,240,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Type de proxy"
+ text.size:*
+ text.validation:""
+ }
+ wimp_icon {
+ extent:244,-108,572,-56
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Display field"
+ text.size:32
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:580,-104,624,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:164,-164,240,-120
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Hôte"
+ text.size:*
+ text.validation:""
+ }
+ wimp_icon {
+ extent:244,-168,504,-116
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"myhost.proxy"
+ text.size:255
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:500,-164,528,-120
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_HCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:":"
+ text.size:*
+ text.validation:""
+ }
+ wimp_icon {
+ extent:524,-168,628,-116
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"8080"
+ text.size:8
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:92,-224,240,-180
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Identifiant"
+ text.size:*
+ text.validation:""
+ }
+ wimp_icon {
+ extent:244,-228,628,-176
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"k1dd13"
+ text.size:64
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:52,-284,240,-240
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Mot de passe"
+ text.size:*
+ text.validation:""
+ }
+ wimp_icon {
+ extent:244,-288,628,-236
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"1337"
+ text.size:64
+ text.validation:"Pptr_write;Kta;D*"
+ }
+ wimp_icon {
+ extent:16,-552,644,-332
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-360,316,-316
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Téléchargements "
+ text_and_sprite.size:*
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:68,-412,320,-368
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Nombre maximum"
+ text.size:16
+ text.validation:""
+ }
+ wimp_icon {
+ extent:324,-416,532,-364
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"99"
+ text.size:*
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:548,-408,580,-376
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:580,-408,612,-376
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:36,-472,320,-428
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Nombre par hôte"
+ text.size:18
+ text.validation:""
+ }
+ wimp_icon {
+ extent:324,-476,532,-424
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"99"
+ text.size:4
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:548,-468,584,-436
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:580,-468,612,-436
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:20,-532,320,-488
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Connexions en cache"
+ text.size:*
+ text.validation:""
+ }
+ wimp_icon {
+ extent:324,-536,532,-484
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"99"
+ text.size:4
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:548,-528,584,-496
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:580,-528,612,-496
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:*
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:24,-640,188,-588
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Par défaut"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:276,-640,440,-588
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Annuler"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:456,-648,640,-580
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Valider"
+ text.size:*
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"con_inter"
+ visible:264,290,1008,1066
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-844,744,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:744
+ ymin:704
+ text_only:"Interface"
+ wimp_icon {
+ extent:16,-168,728,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-52,732,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Téléchargements / sauvegardes de fichiers "
+ text_and_sprite.size:*
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:32,-100,676,-56
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Supprimer l'extension lors des sauvegardes"
+ text_and_sprite.size:*
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:32,-152,676,-108
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Demander confirmation avant écrasement"
+ text_and_sprite.size:46
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:16,-344,728,-200
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:36,-224,496,-180
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Fonctions interactives "
+ text_and_sprite.size:*
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:32,-276,744,-232
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Afficher les URLs visitées récemment"
+ text_and_sprite.size:42
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:32,-328,872,-284
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"URLs flottantes dans l'historique local"
+ text_and_sprite.size:44
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:16,-468,728,-372
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:36,-400,240,-356
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Vignettes "
+ text_and_sprite.size:23
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:32,-452,716,-408
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Utiliser les vignettes pour les fenêtres iconisées"
+ text_and_sprite.size:*
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:24,-744,188,-692
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Par défaut"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:360,-744,524,-692
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Annuler"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:540,-752,724,-684
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Valider"
+ text.size:*
+ text.validation:"R6,3"
+ }
+ wimp_icon {
+ extent:16,-660,728,-492
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:36,-520,240,-476
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Hotlist"
+ text_and_sprite.size:23
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:32,-572,728,-528
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Use external hotlist apps when available"
+ text_and_sprite.size:*
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:28,-640,232,-588
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Hotlist path"
+ text.size:*
+ text.validation:""
+ }
+ wimp_icon {
+ extent:232,-640,708,-588
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"Writable icon"
+ text.size:256
+ text.validation:"Pptr_write;Kta"
+ }
+
+}
+
+wimp_window {
+ template_name:"ssldisplay"
+ visible:282,178,1242,718
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_CLOSE_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-540,960,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:960
+ ymin:76
+ text.text:"Certificat SSL"
+ text.size:16
+ text.validation:""
+ wimp_icon {
+ extent:16,-520,944,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-52,412,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Détails de certificat "
+ text_and_sprite.size:*
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:68,-108,192,-64
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Version"
+ }
+ wimp_icon {
+ extent:200,-108,312,-56
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:384,-104,524,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Valide de"
+ }
+ wimp_icon {
+ extent:524,-108,928,-56
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:112,-168,192,-124
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Type"
+ }
+ wimp_icon {
+ extent:200,-168,312,-116
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:328,-164,524,-120
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Valide jusqu'à"
+ text.size:*
+ text.validation:""
+ }
+ wimp_icon {
+ extent:524,-168,928,-116
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:84,-228,192,-184
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Série"
+ }
+ wimp_icon {
+ extent:200,-228,928,-176
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:32,-288,200,-244
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Fournisseur"
+ }
+ wimp_icon {
+ extent:200,-376,928,-236
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R2;L"
+ }
+ wimp_icon {
+ extent:68,-432,192,-388
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Sujet"
+ }
+ wimp_icon {
+ extent:200,-504,928,-384
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R2;L"
+ }
+}
+
+wimp_window {
+ template_name:"sslcert"
+ visible:348,306,1136,898
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-592,788,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:788
+ ymin:592
+ text.text:"Problème de certificat SSL"
+ text.size:*
+ text.validation:""
+ wimp_icon {
+ extent:16,-108,772,-16
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"NetSurf n'a pas pu vérifier l'authenticité d'un certificat SSL. Vérifiez SVP les détails présentés ci-dessous."
+ text.size:150
+ text.validation:"R2;L"
+ }
+ wimp_icon {
+ extent:16,-484,772,-136
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:*
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-164,380,-120
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Chaîne de certificat "
+ text_and_sprite.size:*
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:404,-564,568,-512
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Rejeter"
+ text.size:*
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:588,-572,772,-504
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Accepter"
+ text.size:*
+ text.validation:"R6,3"
+ }
+}
diff --git a/frontends/riscos/templates/nl b/frontends/riscos/templates/nl
new file mode 100644
index 000000000..704206fbd
--- /dev/null
+++ b/frontends/riscos/templates/nl
@@ -0,0 +1,3887 @@
+Template:
+
+wimp_window {
+ template_name:"configure"
+ visible:378,966,1050,1126
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BACK_ICON | wimp_WINDOW_CLOSE_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_TOGGLE_ICON | wimp_WINDOW_VSCROLL | wimp_WINDOW_SIZE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_LIGHT_GREY
+ extra_flags:
+ extent:0,-880,1236,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:4
+ ymin:160
+ text.text:"NetSurf-instellingen"
+ text.size:22
+ text.validation:""
+}
+
+wimp_window {
+ template_name:"con_cache"
+ visible:184,682,772,1110
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-428,588,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED
+ work_flags:
+ sprite_area:&1
+ xmin:588
+ ymin:240
+ text_only:"Buffer"
+ wimp_icon {
+ extent:16,-124,568,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:1
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-52,300,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Geheugenbuffer "
+ text_and_sprite.size:17
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:60,-104,212,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Grootte"
+ text.size:13
+ text.validation:""
+ }
+ wimp_icon {
+ extent:216,-108,380,-56
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"512.0"
+ text.size:10
+ text.validation:"Pptr_write;Kta;A0-9."
+ }
+ wimp_icon {
+ extent:392,-100,424,-68
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:1
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:424,-100,456,-68
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:1
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:464,-104,528,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"MB"
+ }
+ wimp_icon {
+ extent:16,-312,568,-152
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:1
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-180,268,-136
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Schijfbuffer "
+ text_and_sprite.size:15
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:60,-232,212,-188
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Grootte"
+ text.size:13
+ text.validation:""
+ }
+ wimp_icon {
+ extent:216,-236,380,-184
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"512"
+ text.size:10
+ text.validation:"Pptr_write;Kta;A0-9"
+ }
+ wimp_icon {
+ extent:392,-228,424,-196
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:1
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:424,-228,456,-196
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:1
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:464,-232,528,-192
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"MB"
+ }
+ wimp_icon {
+ extent:12,-292,212,-248
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Bewaar max."
+ text.size:12
+ text.validation:""
+ }
+ wimp_icon {
+ extent:216,-296,380,-244
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"512"
+ text.size:10
+ text.validation:"Pptr_write;Kta;A0-9"
+ }
+ wimp_icon {
+ extent:392,-288,424,-256
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:1
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:424,-288,456,-256
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:1
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:464,-292,560,-252
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"dagen"
+ }
+ wimp_icon {
+ extent:24,-396,200,-344
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Standaard"
+ text.size:10
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:216,-396,376,-344
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Annuleer"
+ text.size:9
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:392,-404,568,-336
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Stel in"
+ text.size:8
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"con_fonts"
+ visible:558,802,1282,1526
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-724,724,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED
+ work_flags:
+ sprite_area:&1
+ xmin:712
+ ymin:724
+ text_only:"Lettertypen"
+ wimp_icon {
+ extent:16,-424,704,-28
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:1
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-52,256,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Lettertypen "
+ text_and_sprite.size:14
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:24,-104,216,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Schreefloos"
+ }
+ wimp_icon {
+ extent:220,-108,628,-56
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Weergaveveld"
+ text.size:256
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:640,-104,684,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:1
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:24,-164,216,-120
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Met schreef"
+ }
+ wimp_icon {
+ extent:220,-168,628,-116
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Weergaveveld"
+ text.size:256
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:640,-164,684,-120
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:1
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:36,-224,216,-180
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Monospace"
+ }
+ wimp_icon {
+ extent:220,-228,628,-176
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Weergaveveld"
+ text.size:256
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:640,-224,684,-180
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:13
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:88,-284,216,-240
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Cursief"
+ }
+ wimp_icon {
+ extent:220,-288,628,-236
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Weergaveveld"
+ text.size:256
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:640,-284,684,-240
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:1
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:72,-344,216,-300
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Fantasie"
+ }
+ wimp_icon {
+ extent:220,-348,628,-296
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Weergaveveld"
+ text.size:256
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:640,-344,684,-300
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:1
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:56,-404,216,-360
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Standaard"
+ }
+ wimp_icon {
+ extent:220,-408,628,-356
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Weergaveveld"
+ text.size:256
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:640,-404,684,-360
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:1
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:16,-612,704,-452
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:1
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-480,296,-436
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Lettergrootte "
+ text_and_sprite.size:16
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:32,-532,200,-488
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Standaard"
+ }
+ wimp_icon {
+ extent:204,-536,372,-484
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"12.3"
+ text.size:10
+ text.validation:"Pptr_write;Kta;A0-9."
+ }
+ wimp_icon {
+ extent:388,-528,420,-496
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:1
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:420,-528,452,-496
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:1
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:460,-532,500,-488
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"pt"
+ }
+ wimp_icon {
+ extent:52,-592,200,-548
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Minimum"
+ }
+ wimp_icon {
+ extent:204,-596,372,-544
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"12.3"
+ text.size:10
+ text.validation:"Pptr_write;Kta;A0-9."
+ }
+ wimp_icon {
+ extent:388,-588,420,-556
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:1
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:420,-588,452,-556
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:1
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:460,-592,500,-548
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"pt"
+ }
+ wimp_icon {
+ extent:24,-696,200,-644
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Standaard"
+ text.size:10
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:340,-696,504,-644
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Annuleer"
+ text.size:9
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:520,-704,704,-636
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Stel in"
+ text.size:8
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"con_home"
+ visible:808,592,1608,888
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-296,800,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED
+ work_flags:
+ sprite_area:&1
+ xmin:800
+ ymin:296
+ text_only:"Startpagina"
+ wimp_icon {
+ extent:16,-184,784,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:1
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-52,284,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Startpagina "
+ text_and_sprite.size:16
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:24,-108,120,-64
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Adres"
+ }
+ wimp_icon {
+ extent:124,-112,712,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:""
+ text.size:128
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:720,-108,764,-64
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:13
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:124,-164,732,-120
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_SELECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Browservenster openen na opstarten"
+ text_and_sprite.size:35
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:24,-264,200,-212
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Standaard"
+ text.size:10
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:420,-264,584,-212
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Annuleer"
+ text.size:9
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:600,-272,784,-204
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Stel in"
+ text.size:8
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"con_image"
+ visible:1488,822,2164,1410
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-588,676,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ work_flags:
+ sprite_area:&1
+ xmin:676
+ ymin:588
+ text.text:"Afbeeldingen"
+ text.size:13
+ text.validation:""
+ wimp_icon {
+ extent:16,-292,660,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:1
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-52,396,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Afbeeldingskwaliteit "
+ text_and_sprite.size:23
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:40,-108,216,-64
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Voorgrond"
+ }
+ wimp_icon {
+ extent:220,-112,592,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"RISC OS-routines"
+ text.size:256
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:600,-108,644,-64
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:13
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:24,-168,216,-124
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Achtergrond"
+ }
+ wimp_icon {
+ extent:220,-172,592,-120
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"RISC OS-routines"
+ text.size:256
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:600,-168,644,-124
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:13
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:32,-276,644,-180
+ icon_flags:wimp_ICON_BORDER
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ }
+ wimp_icon {
+ extent:16,-476,660,-320
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:1
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-348,236,-304
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Animaties "
+ text_and_sprite.size:16
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:20,-404,232,-360
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Animatietijd"
+ text.size:15
+ text.validation:""
+ }
+ wimp_icon {
+ extent:236,-408,404,-356
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"12.34"
+ text.size:6
+ text.validation:"Pptr_write;Kta;A0-9."
+ }
+ wimp_icon {
+ extent:420,-400,452,-368
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:1
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:452,-400,484,-368
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:1
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:492,-404,644,-360
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"seconden"
+ text.size:9
+ text.validation:""
+ }
+ wimp_icon {
+ extent:236,-460,616,-416
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Animaties uitzetten"
+ text_and_sprite.size:20
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:24,-560,200,-508
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Standaard"
+ text.size:10
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:292,-560,456,-508
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Annuleer"
+ text.size:9
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:472,-568,656,-500
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Stel in"
+ text.size:8
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"con_inter"
+ visible:2320,436,3164,1220
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_FULL_SIZE | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-784,844,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:744
+ ymin:584
+ text.text:"Gebruikersinterface"
+ text.size:20
+ text.validation:""
+ wimp_icon {
+ extent:16,-168,820,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:1
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-52,576,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Ophalen / opslaan van bestanden "
+ text_and_sprite.size:34
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:32,-100,748,-56
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Bestand opslaan zonder bestandsextensie"
+ text_and_sprite.size:40
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:32,-152,808,-108
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Toestemming vragen bij overschrijven"
+ text_and_sprite.size:37
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:16,-344,820,-200
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:1
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:36,-224,496,-180
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Interactieve kenmerken "
+ text_and_sprite.size:25
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:32,-276,804,-232
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Recent bezochte adressen tonen tijdens typen"
+ text_and_sprite.size:45
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:32,-328,776,-284
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Adressen tonen bij de venstergeschiedenis"
+ text_and_sprite.size:42
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:16,-468,820,-372
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:1
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:36,-400,240,-356
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Miniaturen "
+ text_and_sprite.size:23
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:32,-452,708,-408
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Miniaturen gebruiken bij symboliseren"
+ text_and_sprite.size:42
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:24,-748,200,-696
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Standaard"
+ text.size:10
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:456,-748,620,-696
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Annuleer"
+ text.size:9
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:636,-756,820,-688
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Stel in"
+ text.size:8
+ text.validation:"R6,3"
+ }
+ wimp_icon {
+ extent:16,-664,820,-496
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:1
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:36,-524,240,-480
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Favorieten"
+ text_and_sprite.size:23
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:32,-576,728,-532
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Extern programma voor favorietenlijst"
+ text_and_sprite.size:38
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:24,-644,256,-592
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Programmapad"
+ text.size:13
+ text.validation:""
+ }
+ wimp_icon {
+ extent:260,-644,800,-592
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"Schrijfbaar veld"
+ text.size:256
+ text.validation:"Pptr_write;Kta"
+ }
+}
+
+wimp_window {
+ template_name:"con_lang"
+ visible:1574,956,2318,1256
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-300,744,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED
+ work_flags:
+ sprite_area:&1
+ xmin:744
+ ymin:300
+ text_only:"Taal"
+ wimp_icon {
+ extent:16,-188,728,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:1
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-52,284,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Taal "
+ text_and_sprite.size:16
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:64,-108,224,-64
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Interface"
+ }
+ wimp_icon {
+ extent:228,-112,660,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"1337"
+ text.size:256
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:668,-108,712,-64
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:13
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:32,-168,224,-124
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Webpagina's"
+ }
+ wimp_icon {
+ extent:228,-172,660,-120
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"8008135"
+ text.size:256
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:668,-168,712,-124
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:13
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:24,-272,200,-220
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Standaard"
+ text.size:10
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:360,-272,524,-220
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Annuleer"
+ text.size:9
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:540,-280,724,-212
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Stel in"
+ text.size:8
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"con_theme"
+ visible:410,38,1318,642
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-604,908,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED
+ work_flags:
+ sprite_area:&1
+ xmin:640
+ ymin:604
+ text_only:"Thema's"
+ wimp_icon {
+ extent:16,-492,892,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:1
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-52,392,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Beschikbare thema's "
+ text_and_sprite.size:22
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:24,-576,200,-524
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Standaard"
+ text.size:10
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:524,-576,688,-524
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Annuleer"
+ text.size:9
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:704,-584,888,-516
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Stel in"
+ text.size:8
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"download"
+ visible:486,610,1394,890
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BACK_ICON | wimp_WINDOW_CLOSE_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-280,908,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:88
+ ymin:28
+ text.text:"NetSurf-ophaalproces"
+ text.size:21
+ text.validation:""
+ wimp_icon {
+ extent:420,-84,488,-16
+ icon_flags:wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK_DRAG
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ sprite.id:"file_ddc"
+ sprite.size:9
+ sprite.area:&1
+ }
+ wimp_icon {
+ extent:204,-152,900,-100
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"http://netsurf.sourceforge.net/netsurf.zip"
+ text.size:43
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:204,-212,900,-160
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"netsurf"
+ text.size:8
+ text.validation:"Pptr_write"
+ }
+ wimp_icon {
+ extent:204,-212,900,-160
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"ADFS::A7000+.$.netsurf"
+ text.size:23
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:8,-272,900,-220
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:1
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:12,-268,296,-224
+ icon_flags:wimp_ICON_FILLED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_CREAM
+ }
+ wimp_icon {
+ extent:12,-268,896,-224
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"999 KB compleet gemiddeld 926.6 KB/s 0:39 resterend"
+ text.size:72
+ text.validation:""
+ }
+ wimp_icon {
+ extent:92,-148,200,-104
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Bron"
+ }
+ wimp_icon {
+ extent:12,-208,200,-164
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Bestemming"
+ }
+}
+
+wimp_window {
+ template_name:"history"
+ visible:252,388,1152,808
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_SCROLL_REPEAT | wimp_WINDOW_BACK_ICON | wimp_WINDOW_CLOSE_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_TOGGLE_ICON | wimp_WINDOW_VSCROLL | wimp_WINDOW_SIZE_ICON | wimp_WINDOW_HSCROLL | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_WHITE
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-880,1236,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:wimp_BUTTON_CLICK
+ sprite_area:&1
+ xmin:0
+ ymin:0
+ text.text:" Venstergeschiedenis "
+ text.size:22
+ text.validation:""
+}
+
+wimp_window {
+ template_name:"info"
+ visible:752,332,1412,700
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_CREAM
+ scroll_inner:wimp_COLOUR_ORANGE
+ highlight_bg:wimp_COLOUR_LIGHT_GREY
+ extra_flags:
+ extent:0,-368,660,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ work_flags:wimp_BUTTON_CLICK
+ sprite_area:&1
+ xmin:660
+ ymin:248
+ text.text:"Programma-informatie"
+ text.size:21
+ text.validation:""
+ wimp_icon {
+ extent:672,-200,848,-152
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_RED
+ text_only:"OK"
+ }
+ wimp_icon {
+ extent:168,-60,652,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK_DRAG
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"NetSurf"
+ text.size:8
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:168,-120,652,-68
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK_DRAG
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Webbrowser met open broncode"
+ text.size:29
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:168,-180,652,-128
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK_DRAG
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"© NetSurf-ontwikkelaars"
+ text.size:40
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:168,-360,652,-308
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK_DRAG
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"CVS-testuitgave"
+ text.size:40
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:72,-56,164,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Naam"
+ }
+ wimp_icon {
+ extent:40,-116,164,-72
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Functie"
+ }
+ wimp_icon {
+ extent:40,-176,164,-132
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Auteurs"
+ }
+ wimp_icon {
+ extent:40,-356,164,-312
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Versie"
+ }
+ wimp_icon {
+ extent:168,-300,652,-248
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK_DRAG
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"g.vankatwijk@freeler.nl"
+ text.size:50
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:8,-296,164,-252
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Contact"
+ text.size:20
+ text.validation:""
+ }
+ wimp_icon {
+ extent:168,-240,652,-188
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK_DRAG
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"NetSurf-vertalers"
+ text.size:40
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:4,-236,164,-192
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Vertaling"
+ }
+}
+
+wimp_window {
+ template_name:"login"
+ visible:582,400,1322,736
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-336,740,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:740
+ ymin:336
+ text.text:"Website-authenticatie"
+ text.size:22
+ text.validation:""
+ wimp_icon {
+ extent:596,-324,728,-256
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Login"
+ text.size:8
+ text.validation:"R6,3;Nok"
+ }
+ wimp_icon {
+ extent:408,-316,572,-264
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Annuleer"
+ text.size:9
+ text.validation:"R5,3;Ncancel"
+ }
+ wimp_icon {
+ extent:252,-60,732,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"moo.yoo.com"
+ text.size:255
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:252,-120,732,-68
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"my sekr3t area"
+ text.size:255
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:252,-180,732,-128
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:""
+ text.size:255
+ text.validation:"Pptr_write;Kta;N401username"
+ }
+ wimp_icon {
+ extent:252,-240,732,-188
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:""
+ text.size:255
+ text.validation:"Pptr_write;Kta;D*"
+ }
+ wimp_icon {
+ extent:100,-56,248,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Website"
+ }
+ wimp_icon {
+ extent:4,-176,248,-132
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Gebruikersnaam"
+ text.size:15
+ text.validation:""
+ }
+ wimp_icon {
+ extent:16,-236,248,-192
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Wachtwoord"
+ }
+ wimp_icon {
+ extent:108,-116,248,-72
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Gebied"
+ }
+}
+
+wimp_window {
+ template_name:"new_entry"
+ visible:480,660,1080,880
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-220,600,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:600
+ ymin:220
+ text.text:""
+ text.size:32
+ text.validation:""
+ wimp_icon {
+ extent:12,-56,108,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Naam"
+ }
+ wimp_icon {
+ extent:112,-60,588,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:""
+ text.size:128
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:12,-116,108,-72
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Adres"
+ }
+ wimp_icon {
+ extent:112,-120,532,-68
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:""
+ text.size:1024
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:268,-200,432,-148
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Annuleer"
+ text.size:9
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:456,-208,588,-140
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"OK"
+ text.size:8
+ text.validation:"R6,3"
+ }
+ wimp_icon {
+ extent:540,-116,584,-72
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:13
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+}
+
+wimp_window {
+ template_name:"new_folder"
+ visible:480,954,1080,1114
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-160,600,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:600
+ ymin:160
+ text.text:""
+ text.size:21
+ text.validation:""
+ wimp_icon {
+ extent:12,-56,108,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Naam"
+ }
+ wimp_icon {
+ extent:112,-60,588,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:""
+ text.size:128
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:268,-140,432,-88
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Annuleer"
+ text.size:9
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:456,-148,588,-80
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"OK"
+ text.size:8
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"objectinfo"
+ visible:428,292,1216,480
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-188,788,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:wimp_BUTTON_CLICK
+ sprite_area:&1
+ xmin:788
+ ymin:188
+ text.text:"Objectinformatie"
+ text.size:20
+ text.validation:""
+ wimp_icon {
+ extent:204,-60,780,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Weergaveveld"
+ text.size:64
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:204,-120,780,-68
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Weergaveveld"
+ text.size:64
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:204,-180,780,-128
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Weergaveveld"
+ text.size:64
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:12,-80,84,-12
+ icon_flags:wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ sprite.id:"file_faf"
+ sprite.size:9
+ sprite.area:&1
+ }
+ wimp_icon {
+ extent:92,-116,200,-72
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Doel"
+ }
+ wimp_icon {
+ extent:120,-176,200,-132
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Type"
+ }
+ wimp_icon {
+ extent:104,-56,200,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Adres"
+ }
+}
+
+wimp_window {
+ template_name:"open_url"
+ visible:248,266,1048,422
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-156,800,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:0
+ ymin:0
+ text.text:"Weblocatie openen"
+ text.size:18
+ text.validation:""
+ wimp_icon {
+ extent:8,-56,104,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Adres"
+ }
+ wimp_icon {
+ extent:108,-60,736,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:""
+ text.size:1
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:468,-136,632,-84
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Annuleer"
+ text.size:9
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:656,-144,788,-76
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Open"
+ text.size:8
+ text.validation:"R6,3"
+ }
+ wimp_icon {
+ extent:744,-56,788,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:13
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+}
+
+wimp_window {
+ template_name:"pageinfo"
+ visible:310,528,1102,776
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-248,792,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:792
+ ymin:248
+ text.text:"Documentinformatie"
+ text.size:19
+ text.validation:""
+ wimp_icon {
+ extent:208,-60,784,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Weergaveveld"
+ text.size:64
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:208,-120,784,-68
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Weergaveveld"
+ text.size:64
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:208,-180,784,-128
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Weergaveveld"
+ text.size:64
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:208,-240,784,-188
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Weergaveveld"
+ text.size:64
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:12,-80,84,-12
+ icon_flags:wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ sprite.id:"file_faf"
+ sprite.size:9
+ sprite.area:&1
+ }
+ wimp_icon {
+ extent:108,-116,204,-72
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Adres"
+ }
+ wimp_icon {
+ extent:60,-176,204,-132
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Codering"
+ }
+ wimp_icon {
+ extent:116,-236,204,-192
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Type"
+ }
+ wimp_icon {
+ extent:112,-56,204,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Titel"
+ }
+}
+
+wimp_window {
+ template_name:"print"
+ visible:472,136,1132,708
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-572,700,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:600
+ ymin:572
+ text.text:"Geen stuurprogramma aanwezig"
+ text.size:29
+ text.validation:""
+ wimp_icon {
+ extent:12,-176,652,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:1
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-100,504,-56
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:1
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"einde van de webpagina"
+ text_and_sprite.size:23
+ text_and_sprite.validation:"Sradiooff,radioon"
+ }
+ wimp_icon {
+ extent:32,-152,492,-108
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:1
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:6
+ text_and_sprite.validation:"Sradiooff,radioon"
+ }
+ wimp_icon {
+ extent:84,-156,164,-104
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"1"
+ text.size:3
+ text.validation:"Pptr_write;Kta;A0-9"
+ }
+ wimp_icon {
+ extent:176,-148,208,-116
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:1
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:208,-148,240,-116
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:1
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:244,-152,528,-108
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"pagina('s)"
+ text.size:11
+ text.validation:""
+ }
+ wimp_icon {
+ extent:12,-236,512,-192
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Voorgrondafbeeldingen"
+ text_and_sprite.size:22
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:12,-288,528,-244
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Achtergrondafbeeldingen"
+ text_and_sprite.size:24
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:12,-340,492,-296
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Afdrukken in achtergrond"
+ text_and_sprite.size:25
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:12,-404,180,-360
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_SELECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Staand"
+ text_and_sprite.size:7
+ text_and_sprite.validation:"Sradiooff,radioon"
+ }
+ wimp_icon {
+ extent:12,-452,196,-408
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Liggend"
+ text_and_sprite.size:8
+ text_and_sprite.validation:"Sradiooff,radioon"
+ }
+ wimp_icon {
+ extent:480,-456,560,-404
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"1"
+ text.size:3
+ text.validation:"Pptr_write;Kta;A0-9"
+ }
+ wimp_icon {
+ extent:572,-448,604,-416
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:1
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:604,-448,636,-416
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:1
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:292,-552,456,-500
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Annuleer"
+ text.size:9
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:480,-560,648,-492
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Druk af"
+ text.size:8
+ text.validation:"R6,3"
+ }
+ wimp_icon {
+ extent:344,-452,476,-408
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Kopieën"
+ }
+ wimp_icon {
+ extent:-16,-480,676,-472
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:1
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:32,-48,448,-4
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Afdrukken stoppen na "
+ text_and_sprite.size:23
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:232,-400,656,-356
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Alle tekst in zwart"
+ text_and_sprite.size:20
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+}
+
+wimp_window {
+ template_name:"query"
+ visible:142,526,942,806
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_LIGHT_GREY
+ extra_flags:
+ extent:0,-280,800,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:0
+ ymin:0
+ text.text:"Vraag van NetSurf"
+ text.size:21
+ text.validation:""
+ wimp_icon {
+ extent:92,-184,792,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Bericht"
+ text.size:300
+ text.validation:"R2;L"
+ }
+ wimp_icon {
+ extent:604,-268,788,-200
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"012345678901234567"
+ text.size:19
+ text.validation:"R6,3"
+ }
+ wimp_icon {
+ extent:424,-260,588,-208
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"0123456789012345678901"
+ text.size:23
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:16,-260,132,-208
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Hulp"
+ text.size:5
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:12,-80,80,-12
+ icon_flags:wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ sprite_only:"!netsurf"
+ }
+}
+
+wimp_window {
+ template_name:"saveas"
+ visible:824,676,1164,924
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BOUNDED_ONCE | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-248,340,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:308
+ ymin:244
+ text_only:"Bewaar als"
+ wimp_icon {
+ extent:144,-84,212,-16
+ icon_flags:wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK_DRAG
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ sprite.id:"file_faf"
+ sprite.size:13
+ sprite.area:&1
+ }
+ wimp_icon {
+ extent:8,-152,332,-100
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:""
+ text.size:256
+ text.validation:"Pptr_write"
+ }
+ wimp_icon {
+ extent:184,-236,332,-168
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Bewaar"
+ text.size:7
+ text.validation:"R6,3"
+ }
+ wimp_icon {
+ extent:8,-228,168,-176
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Annuleer"
+ text.size:9
+ text.validation:"R5,3"
+ }
+}
+
+wimp_window {
+ template_name:"search"
+ visible:1036,684,1792,928
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-244,756,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:756
+ ymin:244
+ text.text:"Tekst zoeken"
+ text.size:13
+ text.validation:""
+ wimp_icon {
+ extent:96,-60,692,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:""
+ text.size:32
+ text.validation:"KN;Pptr_write"
+ }
+ wimp_icon {
+ extent:96,-116,476,-72
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Hoofdlettergevoelig"
+ text_and_sprite.size:20
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:568,-228,744,-160
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Volgende"
+ text.size:10
+ text.validation:"R6,3"
+ }
+ wimp_icon {
+ extent:424,-220,552,-168
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Vorige"
+ text.size:7
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:248,-220,408,-168
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Annuleer"
+ text.size:9
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:12,-216,232,-172
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Niet gevonden"
+ text.size:14
+ text.validation:""
+ }
+ wimp_icon {
+ extent:-8,-148,772,-140
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:1
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:16,-56,92,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Zoek"
+ }
+ wimp_icon {
+ extent:700,-56,744,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_ICON_SHADED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:13
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:472,-116,748,-72
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Alles markeren"
+ text_and_sprite.size:15
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+}
+
+wimp_window {
+ template_name:"theme_inst"
+ visible:374,554,1174,834
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-280,800,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:800
+ ymin:280
+ text.text:"NetSurf-thema-intallatie"
+ text.size:25
+ text.validation:""
+ wimp_icon {
+ extent:92,-184,792,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Bericht"
+ text.size:300
+ text.validation:"R2;L"
+ }
+ wimp_icon {
+ extent:588,-268,788,-200
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Installeer"
+ text.size:11
+ text.validation:"R6,3"
+ }
+ wimp_icon {
+ extent:404,-260,564,-208
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Annuleer"
+ text.size:9
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:12,-80,80,-12
+ icon_flags:wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ sprite_only:"!netsurf"
+ }
+}
+
+wimp_window {
+ template_name:"tooltip"
+ visible:884,620,1148,656
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BOUNDED_ONCE | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-36,2000,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED
+ work_flags:
+ sprite_area:&1
+ xmin:0
+ ymin:0
+ text_only:"<Naamloos>"
+ wimp_icon {
+ extent:0,-40,300,4
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Commentaar"
+ text.size:256
+ text.validation:""
+ }
+}
+
+wimp_window {
+ template_name:"tree"
+ visible:530,654,1042,954
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_SCROLL_REPEAT | wimp_WINDOW_IGNORE_XEXTENT | wimp_WINDOW_IGNORE_YEXTENT | wimp_WINDOW_BOUNDED_ONCE | wimp_WINDOW_BACK_ICON | wimp_WINDOW_CLOSE_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_TOGGLE_ICON | wimp_WINDOW_VSCROLL | wimp_WINDOW_SIZE_ICON | wimp_WINDOW_HSCROLL | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_TRANSPARENT
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-880,1236,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:wimp_BUTTON_DOUBLE_CLICK_DRAG
+ sprite_area:&1
+ xmin:0
+ ymin:0
+ text.text:""
+ text.size:64
+ text.validation:""
+}
+
+wimp_window {
+ template_name:"url_suggest"
+ visible:320,390,1102,684
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_NO_BOUNDS | wimp_WINDOW_IGNORE_XEXTENT | wimp_WINDOW_IGNORE_YEXTENT | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_TRANSPARENT
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-65536,65536,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED
+ work_flags:wimp_BUTTON_CLICK
+ sprite_area:&1
+ xmin:0
+ ymin:0
+ text_only:"<Naamloos>"
+}
+
+wimp_window {
+ template_name:"warning"
+ visible:320,814,1120,1094
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BOUNDED_ONCE | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-280,800,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:0
+ ymin:0
+ text.text:"Waarschuwing van NetSurf"
+ text.size:25
+ text.validation:""
+ wimp_icon {
+ extent:92,-184,792,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Bericht"
+ text.size:300
+ text.validation:"R2;L"
+ }
+ wimp_icon {
+ extent:608,-268,788,-200
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Verder"
+ text.size:7
+ text.validation:"R6,3"
+ }
+ wimp_icon {
+ extent:484,-260,584,-208
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Hulp"
+ text.size:5
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:12,-80,80,-12
+ icon_flags:wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ sprite_only:"!netsurf"
+ }
+}
+
+wimp_window {
+ template_name:"zoom"
+ visible:182,356,650,578
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BOUNDED_ONCE | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-224,468,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ work_flags:
+ sprite_area:&1
+ xmin:468
+ ymin:220
+ text.text:"Pagina schalen"
+ text.size:15
+ text.validation:""
+ wimp_icon {
+ extent:0,-56,112,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Schaal"
+ }
+ wimp_icon {
+ extent:116,-60,212,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"100"
+ text.size:5
+ text.validation:"Pptr_write;KTA;A0-9."
+ }
+ wimp_icon {
+ extent:224,-52,256,-20
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:1
+ text_and_sprite.validation:"R5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:256,-52,288,-20
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:1
+ text_and_sprite.validation:"R5;sup,pup"
+ }
+ wimp_icon {
+ extent:292,-56,332,-12
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_HCENTRED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"%"
+ }
+ wimp_icon {
+ extent:116,-112,460,-68
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Frames meeschalen"
+ text_and_sprite.size:20
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:-4,-132,716,-124
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:1
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:148,-204,308,-152
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Annuleer"
+ text.size:9
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:324,-212,460,-144
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Schaal"
+ text.size:7
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"ssldisplay"
+ visible:862,768,1870,1308
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BOUNDED_ONCE | wimp_WINDOW_CLOSE_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-540,1008,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:1008
+ ymin:76
+ text.text:"SSL-certificaat"
+ text.size:16
+ text.validation:""
+ wimp_icon {
+ extent:16,-520,992,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:1
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-52,380,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Certificaatedetails "
+ text_and_sprite.size:22
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:72,-108,196,-64
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Versie"
+ }
+ wimp_icon {
+ extent:200,-108,312,-56
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:1
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:320,-104,528,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Geldig vanaf"
+ text.size:13
+ text.validation:""
+ }
+ wimp_icon {
+ extent:532,-108,976,-56
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:1
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:116,-168,196,-124
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Type"
+ }
+ wimp_icon {
+ extent:200,-168,312,-116
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:1
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:340,-164,528,-120
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Geldig tot"
+ }
+ wimp_icon {
+ extent:532,-168,976,-116
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:1
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:68,-228,196,-184
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Serienr"
+ }
+ wimp_icon {
+ extent:200,-228,976,-176
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:1
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:56,-288,196,-244
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Uitgever"
+ }
+ wimp_icon {
+ extent:200,-376,976,-236
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:1
+ text.validation:"R2;L"
+ }
+ wimp_icon {
+ extent:24,-432,196,-388
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Onderwerp"
+ }
+ wimp_icon {
+ extent:200,-504,976,-384
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:1
+ text.validation:"R2;L"
+ }
+}
+
+wimp_window {
+ template_name:"con_secure"
+ visible:1590,788,2206,1152
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-364,616,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ work_flags:
+ sprite_area:&1
+ xmin:616
+ ymin:364
+ text.text:"Privacy & veiligheid"
+ text.size:21
+ text.validation:""
+ wimp_icon {
+ extent:16,-120,600,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:1
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-52,364,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Cross-site privacy "
+ text_and_sprite.size:21
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:32,-104,592,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Sitegerelateerde info verzenden"
+ text_and_sprite.size:32
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:16,-252,600,-148
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:1
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-176,316,-132
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Sitegeschiedenis "
+ text_and_sprite.size:18
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:28,-228,112,-184
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Max."
+ }
+ wimp_icon {
+ extent:116,-232,240,-180
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"12"
+ text.size:4
+ text.validation:"Pptr_write;Kta;A0-9"
+ }
+ wimp_icon {
+ extent:252,-224,284,-192
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:1
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:284,-224,316,-192
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:1
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:324,-228,596,-184
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"dagen onthouden"
+ text.size:16
+ text.validation:""
+ }
+ wimp_icon {
+ extent:24,-336,200,-284
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Standaard"
+ text.size:10
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:232,-336,396,-284
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Annuleer"
+ text.size:9
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:412,-344,596,-276
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Stel in"
+ text.size:8
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"con_content"
+ visible:1248,854,1928,1354
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_FULL_SIZE | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-500,680,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:656
+ ymin:452
+ text_only:"Browsen"
+ wimp_icon {
+ extent:16,-272,660,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:1
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-52,492,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Paginaverwerking "
+ text_and_sprite.size:29
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:32,-100,460,-56
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Advertenties verbergen"
+ text_and_sprite.size:39
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:32,-152,592,-108
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Pop-up vensters verhinderen"
+ text_and_sprite.size:46
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:32,-256,540,-212
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_DELETED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"Plug-ins uitschakelen"
+ text_and_sprite.size:42
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:16,-384,660,-292
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:1
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-320,492,-276
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Koppelingen "
+ text_and_sprite.size:29
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:32,-368,644,-324
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"In nieuw venster openen toestaan"
+ text_and_sprite.size:36
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+ wimp_icon {
+ extent:24,-468,200,-416
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Standaard"
+ text.size:10
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:296,-468,460,-416
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Annuleer"
+ text.size:9
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:476,-476,660,-408
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Stel in"
+ text.size:8
+ text.validation:"R6,3"
+ }
+ wimp_icon {
+ extent:32,-204,532,-160
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:"JavaScript uitschakelen"
+ text_and_sprite.size:24
+ text_and_sprite.validation:"Soptoff,opton"
+ }
+}
+
+wimp_window {
+ template_name:"con_connect"
+ visible:1328,566,2068,1234
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-668,740,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED
+ work_flags:
+ sprite_area:&1
+ xmin:740
+ ymin:668
+ text_only:"Verbinding"
+ wimp_icon {
+ extent:16,-304,724,-24
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:1
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:28,-52,232,-8
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" HTTP-proxy "
+ text_and_sprite.size:15
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:96,-104,268,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_only:"Proxy-type"
+ }
+ wimp_icon {
+ extent:272,-108,652,-56
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Weergaveveld"
+ text.size:32
+ text.validation:"R2"
+ }
+ wimp_icon {
+ extent:660,-104,704,-60
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:1
+ text_and_sprite.validation:"R5;sgright,pgright"
+ }
+ wimp_icon {
+ extent:156,-164,268,-120
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Server"
+ text.size:7
+ text.validation:""
+ }
+ wimp_icon {
+ extent:272,-168,584,-116
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"myhost.proxy"
+ text.size:255
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:580,-164,608,-120
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_HCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:":"
+ text.size:2
+ text.validation:""
+ }
+ wimp_icon {
+ extent:604,-168,708,-116
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"8080"
+ text.size:8
+ text.validation:"Pptr_write;Kta;A0-9"
+ }
+ wimp_icon {
+ extent:12,-224,268,-180
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Gebruikersnaam"
+ text.size:15
+ text.validation:""
+ }
+ wimp_icon {
+ extent:272,-228,708,-176
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"k1dd13"
+ text.size:64
+ text.validation:"Pptr_write;Kta"
+ }
+ wimp_icon {
+ extent:44,-284,268,-240
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Wachtwoord"
+ text.size:11
+ text.validation:""
+ }
+ wimp_icon {
+ extent:272,-288,708,-236
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"1337"
+ text.size:64
+ text.validation:"Pptr_write;Kta;D*"
+ }
+ wimp_icon {
+ extent:16,-552,724,-332
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:1
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-360,332,-316
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Ophaalopdrachten "
+ text_and_sprite.size:19
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:148,-412,408,-368
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Maximum aantal"
+ text.size:15
+ text.validation:""
+ }
+ wimp_icon {
+ extent:412,-416,620,-364
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"99"
+ text.size:3
+ text.validation:"Pptr_write;Kta;A0-9"
+ }
+ wimp_icon {
+ extent:636,-408,668,-376
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:1
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:668,-408,700,-376
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:1
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:116,-472,408,-428
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Aantal per server"
+ text.size:18
+ text.validation:""
+ }
+ wimp_icon {
+ extent:412,-476,620,-424
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"99"
+ text.size:4
+ text.validation:"Pptr_write;Kta;A0-9"
+ }
+ wimp_icon {
+ extent:636,-468,672,-436
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:1
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:668,-468,700,-436
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:1
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:24,-532,408,-488
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Gebufferde verbindingen"
+ text.size:24
+ text.validation:""
+ }
+ wimp_icon {
+ extent:412,-536,620,-484
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_WHITE
+ text.text:"99"
+ text.size:4
+ text.validation:"Pptr_write;Kta;A0-9"
+ }
+ wimp_icon {
+ extent:636,-528,672,-496
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:1
+ text_and_sprite.validation:"r5;sdown,pdown"
+ }
+ wimp_icon {
+ extent:668,-528,700,-496
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:""
+ text_and_sprite.size:1
+ text_and_sprite.validation:"r5;sup,pup"
+ }
+ wimp_icon {
+ extent:24,-640,200,-588
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Standaard"
+ text.size:10
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:360,-640,524,-588
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Annuleer"
+ text.size:9
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:540,-648,724,-580
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Stel in"
+ text.size:8
+ text.validation:"R6,3"
+ }
+}
+
+wimp_window {
+ template_name:"sslcert"
+ visible:348,250,1136,898
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BOUNDED_ONCE | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-648,788,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:
+ sprite_area:&1
+ xmin:788
+ ymin:648
+ text.text:"SSL-certificaatprobleem"
+ text.size:24
+ text.validation:""
+ wimp_icon {
+ extent:16,-148,772,-16
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"NetSurf kan de rechtmatigheid van een SSL-certificaat niet verifiëren. Verifieer de details hieronder."
+ text.size:150
+ text.validation:"R2;L"
+ }
+ wimp_icon {
+ extent:16,-548,772,-176
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:""
+ text.size:1
+ text.validation:"R4"
+ }
+ wimp_icon {
+ extent:32,-204,380,-160
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text_and_sprite.text:" Certificaatketen "
+ text_and_sprite.size:22
+ text_and_sprite.validation:""
+ }
+ wimp_icon {
+ extent:404,-624,568,-572
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Verwerp"
+ text.size:8
+ text.validation:"R5,3"
+ }
+ wimp_icon {
+ extent:588,-632,772,-564
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
+ icon_esg:0
+ icon_fg:wimp_COLOUR_BLACK
+ icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
+ text.text:"Accepteer"
+ text.size:10
+ text.validation:"R6,3"
+ }
+}
diff --git a/frontends/riscos/textarea.c b/frontends/riscos/textarea.c
new file mode 100644
index 000000000..ecf3e0c3d
--- /dev/null
+++ b/frontends/riscos/textarea.c
@@ -0,0 +1,1160 @@
+/*
+ * Copyright 2006 John-Mark Bell <jmb202@ecs.soton.ac.uk>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Single/Multi-line UTF-8 text area (implementation)
+ */
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include <swis.h>
+#include <oslib/colourtrans.h>
+#include <oslib/osbyte.h>
+#include <oslib/serviceinternational.h>
+#include <oslib/wimp.h>
+#include <oslib/wimpspriteop.h>
+
+#include "utils/log.h"
+#include "utils/utf8.h"
+#include "desktop/browser.h"
+
+#include "riscos/gui.h"
+#include "riscos/oslib_pre7.h"
+#include "riscos/textarea.h"
+#include "riscos/ucstables.h"
+#include "riscos/wimp.h"
+#include "riscos/wimp_event.h"
+#include "riscos/wimputils.h"
+
+#define MARGIN_LEFT 8
+#define MARGIN_RIGHT 8
+
+struct line_info {
+ unsigned int b_start; /**< Byte offset of line start */
+ unsigned int b_length; /**< Byte length of line */
+};
+
+struct text_area {
+#define MAGIC (('T'<<24) | ('E'<<16) | ('X'<<8) | 'T')
+ unsigned int magic; /**< Magic word, for sanity */
+
+ unsigned int flags; /**< Textarea flags */
+ unsigned int vis_width; /**< Visible width, in pixels */
+ unsigned int vis_height; /**< Visible height, in pixels */
+ wimp_w window; /**< Window handle */
+
+ char *text; /**< UTF-8 text */
+ unsigned int text_alloc; /**< Size of allocated text */
+ unsigned int text_len; /**< Length of text, in bytes */
+ struct {
+ unsigned int line; /**< Line caret is on */
+ unsigned int char_off; /**< Character index of caret */
+ } caret_pos;
+// unsigned int selection_start; /**< Character index of sel start */
+// unsigned int selection_end; /**< Character index of sel end */
+
+ wimp_w parent; /**< Parent window handle */
+ wimp_i icon; /**< Parent icon handle */
+
+ char *font_family; /**< Font family of text */
+ unsigned int font_size; /**< Font size (16ths/pt) */
+ rufl_style font_style; /**< Font style (rufl) */
+ int line_height; /**< Total height of a line, given font size */
+ int line_spacing; /**< Height of line spacing, given font size */
+
+ unsigned int line_count; /**< Count of lines */
+#define LINE_CHUNK_SIZE 256
+ struct line_info *lines; /**< Line info array */
+
+ struct text_area *next; /**< Next text area in list */
+ struct text_area *prev; /**< Prev text area in list */
+};
+
+static wimp_window text_area_definition = {
+ {0, 0, 16, 16},
+ 0,
+ 0,
+ wimp_TOP,
+ wimp_WINDOW_NEW_FORMAT | wimp_WINDOW_NO_BOUNDS,
+ wimp_COLOUR_BLACK,
+ wimp_COLOUR_LIGHT_GREY,
+ wimp_COLOUR_LIGHT_GREY,
+ wimp_COLOUR_VERY_LIGHT_GREY,
+ wimp_COLOUR_DARK_GREY,
+ wimp_COLOUR_MID_LIGHT_GREY,
+ wimp_COLOUR_CREAM,
+ 0,
+ {0, -16384, 16384, 0},
+ wimp_ICON_TEXT | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED,
+ wimp_BUTTON_CLICK << wimp_ICON_BUTTON_TYPE_SHIFT,
+ wimpspriteop_AREA,
+ 1,
+ 1,
+ {""},
+ 0,
+ {}
+};
+
+static void ro_textarea_reflow(struct text_area *ta, unsigned int line);
+static bool ro_textarea_mouse_click(wimp_pointer *pointer);
+static bool ro_textarea_key_press(wimp_key *key);
+static void ro_textarea_redraw(wimp_draw *redraw);
+static void ro_textarea_redraw_internal(wimp_draw *redraw, bool update);
+static void ro_textarea_open(wimp_open *open);
+
+/**
+ * Create a text area
+ *
+ * \param parent Parent window
+ * \param icon Icon in parent window to replace
+ * \param flags Text area flags
+ * \param font_family RUfl font family to use, or NULL for default
+ * \param font_size Font size to use (pt * 16), or 0 for default
+ * \param font_style Font style to use, or 0 for default
+ * \return Opaque handle for textarea or 0 on error
+ */
+uintptr_t ro_textarea_create(wimp_w parent, wimp_i icon, unsigned int flags,
+ const char *font_family, unsigned int font_size,
+ rufl_style font_style)
+{
+ struct text_area *ret;
+ os_error *error;
+
+ ret = malloc(sizeof(struct text_area));
+ if (!ret) {
+ LOG("malloc failed");
+ return 0;
+ }
+
+ ret->parent = parent;
+ ret->icon = icon;
+ ret->magic = MAGIC;
+ ret->flags = flags;
+ ret->text = malloc(64);
+ if (!ret->text) {
+ LOG("malloc failed");
+ free(ret);
+ return 0;
+ }
+ ret->text[0] = '\0';
+ ret->text_alloc = 64;
+ ret->text_len = 1;
+ ret->caret_pos.line = ret->caret_pos.char_off = (unsigned int)-1;
+// ret->selection_start = (unsigned int)-1;
+// ret->selection_end = (unsigned int)-1;
+ ret->font_family = strdup(font_family ? font_family : "Corpus");
+ if (!ret->font_family) {
+ LOG("strdup failed");
+ free(ret->text);
+ free(ret);
+ return 0;
+ }
+ ret->font_size = font_size ? font_size : 192 /* 12pt */;
+ ret->font_style = font_style ? font_style : rufl_WEIGHT_400;
+
+ /** \todo Better line height calculation */
+ ret->line_height = (int)(((ret->font_size * 1.3) / 16) * 2.0) + 1;
+ ret->line_spacing = ret->line_height / 8;
+
+ ret->line_count = 0;
+ ret->lines = 0;
+
+ if (flags & TEXTAREA_READONLY)
+ text_area_definition.title_fg = 0xff;
+ else
+ text_area_definition.title_fg = wimp_COLOUR_BLACK;
+ error = xwimp_create_window(&text_area_definition, &ret->window);
+ if (error) {
+ LOG("xwimp_create_window: 0x%x: %s", error->errnum, error->errmess);
+ free(ret->font_family);
+ free(ret->text);
+ free(ret);
+ return 0;
+ }
+
+ /* set the window dimensions */
+ if (!ro_textarea_update((uintptr_t)ret)) {
+ ro_textarea_destroy((uintptr_t)ret);
+ return 0;
+ }
+
+ /* and register our event handlers */
+ ro_gui_wimp_event_set_user_data(ret->window, ret);
+ ro_gui_wimp_event_register_mouse_click(ret->window,
+ ro_textarea_mouse_click);
+ ro_gui_wimp_event_register_keypress(ret->window,
+ ro_textarea_key_press);
+ ro_gui_wimp_event_register_redraw_window(ret->window,
+ ro_textarea_redraw);
+ ro_gui_wimp_event_register_open_window(ret->window,
+ ro_textarea_open);
+
+ return (uintptr_t)ret;
+}
+
+/**
+ * Update the a text area following a change in the parent icon
+ *
+ * \param self Text area to update
+ */
+bool ro_textarea_update(uintptr_t self)
+{
+ struct text_area *ta;
+ wimp_window_state state;
+ wimp_icon_state istate;
+ os_box extent;
+ os_error *error;
+
+ ta = (struct text_area *)self;
+ if (!ta || ta->magic != MAGIC)
+ return false;
+
+ state.w = ta->parent;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ return false;
+ }
+
+ istate.w = ta->parent;
+ istate.i = ta->icon;
+ error = xwimp_get_icon_state(&istate);
+ if (error) {
+ LOG("xwimp_get_icon_state: 0x%x: %s", error->errnum, error->errmess);
+ return false;
+ }
+
+ state.w = ta->window;
+ state.visible.x1 = state.visible.x0 + istate.icon.extent.x1 -
+ ro_get_vscroll_width(ta->window) - state.xscroll;
+ state.visible.x0 += istate.icon.extent.x0 + 2 - state.xscroll;
+ state.visible.y0 = state.visible.y1 + istate.icon.extent.y0 +
+ ro_get_hscroll_height(ta->window) - state.yscroll;
+ state.visible.y1 += istate.icon.extent.y1 - 2 - state.yscroll;
+
+ if (ta->flags & TEXTAREA_READONLY) {
+ state.visible.x0 += 2;
+ state.visible.x1 -= 4;
+ state.visible.y0 += 2;
+ state.visible.y1 -= 4;
+ }
+
+ /* set our width/height */
+ ta->vis_width = state.visible.x1 - state.visible.x0;
+ ta->vis_height = state.visible.y1 - state.visible.y0;
+
+ /* Set window extent to visible area */
+ extent.x0 = 0;
+ extent.y0 = -ta->vis_height;
+ extent.x1 = ta->vis_width;
+ extent.y1 = 0;
+
+ error = xwimp_set_extent(ta->window, &extent);
+ if (error) {
+ LOG("xwimp_set_extent: 0x%x: %s", error->errnum, error->errmess);
+ return false;
+ }
+
+ /* and open the window */
+ error = xwimp_open_window_nested(PTR_WIMP_OPEN(&state), ta->parent,
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_XORIGIN_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_TOP_OR_RIGHT
+ << wimp_CHILD_YORIGIN_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_LS_EDGE_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_RS_EDGE_SHIFT);
+ if (error) {
+ LOG("xwimp_open_window_nested: 0x%x: %s", error->errnum, error->errmess);
+ return false;
+ }
+
+ /* reflow the text */
+ ro_textarea_reflow(ta, 0);
+ return true;
+}
+
+/**
+ * Destroy a text area
+ *
+ * \param self Text area to destroy
+ */
+void ro_textarea_destroy(uintptr_t self)
+{
+ struct text_area *ta;
+ os_error *error;
+
+ ta = (struct text_area *)self;
+ if (!ta || ta->magic != MAGIC)
+ return;
+
+ error = xwimp_delete_window(ta->window);
+ if (error) {
+ LOG("xwimp_delete_window: 0x%x: %s", error->errnum, error->errmess);
+ }
+
+ ro_gui_wimp_event_finalise(ta->window);
+
+ free(ta->font_family);
+ free(ta->text);
+ free(ta);
+}
+
+/**
+ * Set the text in a text area, discarding any current text
+ *
+ * \param self Text area
+ * \param text UTF-8 text to set text area's contents to
+ * \return true on success, false on memory exhaustion
+ */
+bool ro_textarea_set_text(uintptr_t self, const char *text)
+{
+ struct text_area *ta;
+ unsigned int len = strlen(text) + 1;
+
+ ta = (struct text_area *)self;
+ if (!ta || ta->magic != MAGIC) {
+ LOG("magic doesn't match");
+ return true;
+ }
+
+ if (len >= ta->text_alloc) {
+ char *temp = realloc(ta->text, len + 64);
+ if (!temp) {
+ LOG("realloc failed");
+ return false;
+ }
+ ta->text = temp;
+ ta->text_alloc = len+64;
+ }
+
+ memcpy(ta->text, text, len);
+ ta->text_len = len;
+
+ ro_textarea_reflow(ta, 0);
+
+ return true;
+}
+
+/**
+ * Extract the text from a text area
+ *
+ * \param self Text area
+ * \param buf Pointer to buffer to receive data, or NULL
+ * to read length required
+ * \param len Length (bytes) of buffer pointed to by buf, or 0 to read length
+ * \return Length (bytes) written/required or -1 on error
+ */
+int ro_textarea_get_text(uintptr_t self, char *buf, unsigned int len)
+{
+ struct text_area *ta;
+
+ ta = (struct text_area *)self;
+ if (!ta || ta->magic != MAGIC) {
+ LOG("magic doesn't match");
+ return -1;
+ }
+
+ if (buf == NULL && len == 0) {
+ /* want length */
+ return ta->text_len;
+ }
+
+ if (len < ta->text_len) {
+ LOG("buffer too small");
+ return -1;
+ }
+
+ memcpy(buf, ta->text, ta->text_len);
+
+ return ta->text_len;
+}
+
+/**
+ * Insert text into the text area
+ *
+ * \param self Text area
+ * \param index 0-based character index to insert at
+ * \param text UTF-8 text to insert
+ */
+void ro_textarea_insert_text(uintptr_t self, unsigned int index,
+ const char *text)
+{
+ struct text_area *ta;
+ unsigned int b_len = strlen(text);
+ size_t b_off, c_len;
+
+ ta = (struct text_area *)self;
+ if (!ta || ta->magic != MAGIC) {
+ LOG("magic doesn't match");
+ return;
+ }
+
+ c_len = utf8_length(ta->text);
+
+ /* Find insertion point */
+ if (index > c_len)
+ index = c_len;
+
+ for (b_off = 0; index-- > 0;
+ b_off = utf8_next(ta->text, ta->text_len, b_off))
+ ; /* do nothing */
+
+ if (b_len + ta->text_len >= ta->text_alloc) {
+ char *temp = realloc(ta->text, b_len + ta->text_len + 64);
+ if (!temp) {
+ LOG("realloc failed");
+ return;
+ }
+
+ ta->text = temp;
+ ta->text_alloc = b_len + ta->text_len + 64;
+ }
+
+ /* Shift text following up */
+ memmove(ta->text + b_off + b_len, ta->text + b_off,
+ ta->text_len - b_off);
+ /* Insert new text */
+ memcpy(ta->text + b_off, text, b_len);
+
+ ta->text_len += b_len;
+
+ /** \todo calculate line to reflow from */
+ ro_textarea_reflow(ta, 0);
+}
+
+/**
+ * Replace text in a text area
+ *
+ * \param self Text area
+ * \param start Start character index of replaced section (inclusive)
+ * \param end End character index of replaced section (exclusive)
+ * \param text UTF-8 text to insert
+ */
+void ro_textarea_replace_text(uintptr_t self, unsigned int start,
+ unsigned int end, const char *text)
+{
+ struct text_area *ta;
+ int b_len = strlen(text);
+ size_t b_start, b_end, c_len, diff;
+
+ ta = (struct text_area *)self;
+ if (!ta || ta->magic != MAGIC) {
+ LOG("magic doesn't match");
+ return;
+ }
+
+ c_len = utf8_length(ta->text);
+
+ if (start > c_len)
+ start = c_len;
+ if (end > c_len)
+ end = c_len;
+
+ if (start == end)
+ return ro_textarea_insert_text(self, start, text);
+
+ if (start > end) {
+ int temp = end;
+ end = start;
+ start = temp;
+ }
+
+ diff = end - start;
+
+ for (b_start = 0; start-- > 0;
+ b_start = utf8_next(ta->text, ta->text_len, b_start))
+ ; /* do nothing */
+
+ for (b_end = b_start; diff-- > 0;
+ b_end = utf8_next(ta->text, ta->text_len, b_end))
+ ; /* do nothing */
+
+ if (b_len + ta->text_len - (b_end - b_start) >= ta->text_alloc) {
+ char *temp = realloc(ta->text,
+ b_len + ta->text_len - (b_end - b_start) + 64);
+ if (!temp) {
+ LOG("realloc failed");
+ return;
+ }
+
+ ta->text = temp;
+ ta->text_alloc =
+ b_len + ta->text_len - (b_end - b_start) + 64;
+ }
+
+ /* Shift text following to new position */
+ memmove(ta->text + b_start + b_len, ta->text + b_end,
+ ta->text_len - b_end);
+
+ /* Insert new text */
+ memcpy(ta->text + b_start, text, b_len);
+
+ ta->text_len += b_len - (b_end - b_start);
+
+ /** \todo calculate line to reflow from */
+ ro_textarea_reflow(ta, 0);
+}
+
+/**
+ * Set the caret's position
+ *
+ * \param self Text area
+ * \param caret 0-based character index to place caret at
+ */
+void ro_textarea_set_caret(uintptr_t self, unsigned int caret)
+{
+ struct text_area *ta;
+ size_t c_len, b_off;
+ unsigned int i;
+ size_t index;
+ int x;
+ os_coord os_line_height;
+ rufl_code code;
+ os_error *error;
+
+ ta = (struct text_area *)self;
+ if (!ta || ta->magic != MAGIC) {
+ LOG("magic doesn't match");
+ return;
+ }
+
+ c_len = utf8_length(ta->text);
+
+ if (caret > c_len)
+ caret = c_len;
+
+ /* Find byte offset of caret position */
+ for (b_off = 0; caret > 0; caret--)
+ b_off = utf8_next(ta->text, ta->text_len, b_off);
+
+ /* Now find line in which byte offset appears */
+ for (i = 0; i < ta->line_count - 1; i++)
+ if (ta->lines[i + 1].b_start > b_off)
+ break;
+
+ ta->caret_pos.line = i;
+
+ /* Now calculate the char. offset of the caret in this line */
+ for (c_len = 0, ta->caret_pos.char_off = 0;
+ c_len < b_off - ta->lines[i].b_start;
+ c_len = utf8_next(ta->text + ta->lines[i].b_start,
+ ta->lines[i].b_length, c_len))
+ ta->caret_pos.char_off++;
+
+
+ /* Finally, redraw the WIMP caret */
+ index = ro_textarea_get_caret(self);
+ os_line_height.x = 0;
+ os_line_height.y = (int)((float)(ta->line_height - ta->line_spacing) * 0.62) + 1;
+ ro_convert_pixels_to_os_units(&os_line_height, (os_mode)-1);
+
+ for (b_off = 0; index-- > 0; b_off = utf8_next(ta->text, ta->text_len, b_off))
+ ; /* do nothing */
+
+ code = rufl_width(ta->font_family, ta->font_style, ta->font_size,
+ ta->text + ta->lines[ta->caret_pos.line].b_start,
+ b_off - ta->lines[ta->caret_pos.line].b_start, &x);
+ if (code != rufl_OK) {
+ if (code == rufl_FONT_MANAGER_ERROR)
+ LOG("rufl_width: 0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess);
+ else
+ LOG("rufl_width: 0x%x", code);
+ return;
+ }
+
+ error = xwimp_set_caret_position(ta->window, -1, x + MARGIN_LEFT,
+ -((ta->caret_pos.line + 1) * ta->line_height) -
+ ta->line_height / 4 + ta->line_spacing,
+ os_line_height.y, -1);
+ if (error) {
+ LOG("xwimp_set_caret_position: 0x%x: %s", error->errnum, error->errmess);
+ return;
+ }
+}
+
+/**
+ * Set the caret's position
+ *
+ * \param self Text area
+ * \param x X position of caret on the screen
+ * \param y Y position of caret on the screen
+ */
+void ro_textarea_set_caret_xy(uintptr_t self, int x, int y)
+{
+ struct text_area *ta;
+ wimp_window_state state;
+ size_t b_off, c_off, temp;
+ int line;
+ os_coord os_line_height;
+ rufl_code code;
+ os_error *error;
+
+ ta = (struct text_area *)self;
+ if (!ta || ta->magic != MAGIC) {
+ LOG("magic doesn't match");
+ return;
+ }
+
+ if (ta->flags & TEXTAREA_READONLY)
+ return;
+
+ os_line_height.x = 0;
+ os_line_height.y = (int)((float)(ta->line_height - ta->line_spacing) * 0.62) + 1;
+ ro_convert_pixels_to_os_units(&os_line_height, (os_mode)-1);
+
+ state.w = ta->window;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ return;
+ }
+
+ x = x - (state.visible.x0 - state.xscroll) - MARGIN_LEFT;
+ y = (state.visible.y1 - state.yscroll) - y;
+
+ line = y / ta->line_height;
+
+ if (line < 0)
+ line = 0;
+ if (ta->line_count - 1 < (unsigned)line)
+ line = ta->line_count - 1;
+
+ code = rufl_x_to_offset(ta->font_family, ta->font_style,
+ ta->font_size,
+ ta->text + ta->lines[line].b_start,
+ ta->lines[line].b_length,
+ x, &b_off, &x);
+ if (code != rufl_OK) {
+ if (code == rufl_FONT_MANAGER_ERROR)
+ LOG("rufl_x_to_offset: 0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess);
+ else
+ LOG("rufl_x_to_offset: 0x%x", code);
+ return;
+ }
+
+ for (temp = 0, c_off = 0; temp < b_off + ta->lines[line].b_start;
+ temp = utf8_next(ta->text, ta->text_len, temp))
+ c_off++;
+
+ ro_textarea_set_caret((uintptr_t)ta, c_off);
+}
+
+/**
+ * Get the caret's position
+ *
+ * \param self Text area
+ * \return 0-based character index of caret location, or -1 on error
+ */
+unsigned int ro_textarea_get_caret(uintptr_t self)
+{
+ struct text_area *ta;
+ size_t c_off = 0, b_off;
+
+ ta = (struct text_area *)self;
+ if (!ta || ta->magic != MAGIC) {
+ LOG("magic doesn't match");
+ return -1;
+ }
+
+ /* Calculate character offset of this line's start */
+ for (b_off = 0; b_off < ta->lines[ta->caret_pos.line].b_start;
+ b_off = utf8_next(ta->text, ta->text_len, b_off))
+ c_off++;
+
+ return c_off + ta->caret_pos.char_off;
+}
+
+/** \todo Selection handling */
+
+/**
+ * Reflow a text area from the given line onwards
+ *
+ * \param ta Text area to reflow
+ * \param line Line number to begin reflow on
+ */
+void ro_textarea_reflow(struct text_area *ta, unsigned int line)
+{
+ rufl_code code;
+ char *text;
+ unsigned int len;
+ size_t b_off;
+ int x;
+ char *space;
+ unsigned int line_count = 0;
+ os_box extent;
+ os_error *error;
+
+ /** \todo pay attention to line parameter */
+ /** \todo create horizontal scrollbar if needed */
+
+ ta->line_count = 0;
+
+ if (!ta->lines) {
+ ta->lines =
+ malloc(LINE_CHUNK_SIZE * sizeof(struct line_info));
+ if (!ta->lines) {
+ LOG("malloc failed");
+ return;
+ }
+ }
+
+ if (!(ta->flags & TEXTAREA_MULTILINE)) {
+ /* Single line */
+ ta->lines[line_count].b_start = 0;
+ ta->lines[line_count++].b_length = ta->text_len - 1;
+
+ ta->line_count = line_count;
+
+ return;
+ }
+
+ for (len = ta->text_len - 1, text = ta->text; len > 0;
+ len -= b_off, text += b_off) {
+ code = rufl_split(ta->font_family, ta->font_style,
+ ta->font_size, text, len,
+ ta->vis_width - MARGIN_LEFT - MARGIN_RIGHT,
+ &b_off, &x);
+ if (code != rufl_OK) {
+ if (code == rufl_FONT_MANAGER_ERROR)
+ LOG("rufl_x_to_offset: 0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess);
+ else
+ LOG("rufl_x_to_offset: 0x%x", code);
+ return;
+ }
+
+ if (line_count > 0 && line_count % LINE_CHUNK_SIZE == 0) {
+ struct line_info *temp = realloc(ta->lines,
+ (line_count + LINE_CHUNK_SIZE) *
+ sizeof(struct line_info));
+ if (!temp) {
+ LOG("realloc failed");
+ return;
+ }
+
+ ta->lines = temp;
+ }
+
+ /* handle CR/LF */
+ for (space = text; space < text + b_off; space++) {
+ if (*space == '\r' || *space == '\n')
+ break;
+ }
+
+ if (space != text + b_off) {
+ /* Found newline; use it */
+ ta->lines[line_count].b_start = text - ta->text;
+ ta->lines[line_count++].b_length = space - text;
+
+ /* CRLF / LFCR pair */
+ if (*space == '\r' && *(space + 1) == '\n')
+ space++;
+ else if (*space == '\n' && *(space + 1) == '\r')
+ space++;
+
+ b_off = space + 1 - text;
+
+ if (len - b_off == 0) {
+ /* reached end of input => add last line */
+ ta->lines[line_count].b_start =
+ text + b_off - ta->text;
+ ta->lines[line_count++].b_length = 0;
+ }
+
+ continue;
+ }
+
+ if (len - b_off > 0) {
+ /* find last space (if any) */
+ for (space = text + b_off; space > text; space--)
+ if (*space == ' ')
+ break;
+
+ if (space != text)
+ b_off = space + 1 - text;
+ }
+
+ ta->lines[line_count].b_start = text - ta->text;
+ ta->lines[line_count++].b_length = b_off;
+ }
+
+ ta->line_count = line_count;
+
+ /* and now update extent */
+ extent.x0 = 0;
+ extent.y1 = 0;
+ extent.x1 = ta->vis_width;
+ extent.y0 = -ta->line_height * line_count - ta->line_spacing;
+
+ if (extent.y0 > (int)-ta->vis_height)
+ /* haven't filled window yet */
+ return;
+
+ error = xwimp_set_extent(ta->window, &extent);
+ if (error) {
+ LOG("xwimp_set_extent: 0x%x: %s", error->errnum, error->errmess);
+ return;
+ }
+
+ /* Create vertical scrollbar if we don't already have one */
+ if (!ro_gui_wimp_check_window_furniture(ta->window,
+ wimp_WINDOW_VSCROLL)) {
+ wimp_window_state state;
+ wimp_w parent;
+ bits linkage;
+ unsigned int vscroll_width;
+
+ /* Save window parent & linkage flags */
+ state.w = ta->window;
+ error = xwimp_get_window_state_and_nesting(&state,
+ &parent, &linkage);
+ if (error) {
+ LOG("xwimp_get_window_state_and_nesting: 0x%x: %s", error->errnum, error->errmess);
+ return;
+ }
+
+ /* Now, attempt to create vertical scrollbar */
+ ro_gui_wimp_update_window_furniture(ta->window,
+ wimp_WINDOW_VSCROLL,
+ wimp_WINDOW_VSCROLL);
+
+ /* Get new window state */
+ state.w = ta->window;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ return;
+ }
+
+ /* Get scroll width */
+ vscroll_width = ro_get_vscroll_width(NULL);
+
+ /* Shrink width by difference */
+ state.visible.x1 -= vscroll_width;
+
+ /* and reopen window */
+ error = xwimp_open_window_nested(PTR_WIMP_OPEN(&state),
+ parent, linkage);
+ if (error) {
+ LOG("xwimp_open_window_nested: 0x%x: %s", error->errnum, error->errmess);
+ return;
+ }
+
+ /* finally, update visible width */
+ ta->vis_width -= vscroll_width;
+
+ /* Now we've done that, we have to reflow the text area */
+ ro_textarea_reflow(ta, 0);
+ }
+}
+
+/**
+ * Handle mouse clicks in a text area
+ *
+ * \param pointer Mouse click state block
+ * \return true if click handled, false otherwise
+ */
+bool ro_textarea_mouse_click(wimp_pointer *pointer)
+{
+ struct text_area *ta;
+
+ ta = (struct text_area *)ro_gui_wimp_event_get_user_data(pointer->w);
+
+ ro_textarea_set_caret_xy((uintptr_t)ta, pointer->pos.x, pointer->pos.y);
+ return true;
+}
+
+/**
+ * Handle key presses in a text area
+ *
+ * \param key Key pressed state block
+ * \return true if press handled, false otherwise
+ */
+bool ro_textarea_key_press(wimp_key *key)
+{
+ uint32_t c = (uint32_t) key->c;
+ wimp_key keypress;
+ struct text_area *ta;
+ bool redraw = false;
+ unsigned int c_pos;
+
+ ta = (struct text_area *)ro_gui_wimp_event_get_user_data(key->w);
+
+ if (ta->flags & TEXTAREA_READONLY)
+ return true;
+
+ if (!(c & IS_WIMP_KEY ||
+ (c <= 0x001f || (0x007f <= c && c <= 0x009f)))) {
+ /* normal character - insert */
+ char utf8[7];
+ size_t utf8_len;
+
+ utf8_len = utf8_from_ucs4(c, utf8);
+ utf8[utf8_len] = '\0';
+
+ c_pos = ro_textarea_get_caret((uintptr_t)ta);
+ ro_textarea_insert_text((uintptr_t)ta, c_pos, utf8);
+ ro_textarea_set_caret((uintptr_t)ta, ++c_pos);
+
+ redraw = true;
+ } else {
+ os_error *error;
+ /** \todo handle command keys */
+ switch (c & ~IS_WIMP_KEY) {
+ case 8: /* Backspace */
+ c_pos = ro_textarea_get_caret((uintptr_t)ta);
+ if (c_pos > 0) {
+ ro_textarea_replace_text((uintptr_t)ta,
+ c_pos - 1, c_pos, "");
+ ro_textarea_set_caret((uintptr_t)ta, c_pos - 1);
+ redraw = true;
+ }
+ break;
+ case 21: /* Ctrl + U */
+ ro_textarea_set_text((uintptr_t)ta, "");
+ ro_textarea_set_caret((uintptr_t)ta, 0);
+ redraw = true;
+ break;
+ case wimp_KEY_DELETE:
+ c_pos = ro_textarea_get_caret((uintptr_t)ta);
+ if (os_version < RISCOS5 && c_pos > 0) {
+ ro_textarea_replace_text((uintptr_t)ta,
+ c_pos - 1, c_pos, "");
+ ro_textarea_set_caret((uintptr_t)ta, c_pos - 1);
+ } else {
+ ro_textarea_replace_text((uintptr_t)ta, c_pos,
+ c_pos + 1, "");
+ }
+ redraw = true;
+ break;
+
+ case wimp_KEY_LEFT:
+ c_pos = ro_textarea_get_caret((uintptr_t)ta);
+ if (c_pos > 0)
+ ro_textarea_set_caret((uintptr_t)ta, c_pos - 1);
+ break;
+ case wimp_KEY_RIGHT:
+ c_pos = ro_textarea_get_caret((uintptr_t)ta);
+ ro_textarea_set_caret((uintptr_t)ta, c_pos + 1);
+ break;
+ case wimp_KEY_UP:
+ /** \todo Move caret up a line */
+ break;
+ case wimp_KEY_DOWN:
+ /** \todo Move caret down a line */
+ break;
+
+ case wimp_KEY_HOME:
+ case wimp_KEY_CONTROL | wimp_KEY_LEFT:
+ /** \todo line start */
+ break;
+ case wimp_KEY_CONTROL | wimp_KEY_RIGHT:
+ /** \todo line end */
+ break;
+ case wimp_KEY_CONTROL | wimp_KEY_UP:
+ ro_textarea_set_caret((uintptr_t)ta, 0);
+ break;
+ case wimp_KEY_CONTROL | wimp_KEY_DOWN:
+ ro_textarea_set_caret((uintptr_t)ta,
+ utf8_length(ta->text));
+ break;
+
+ case wimp_KEY_COPY:
+ if (os_version < RISCOS5) {
+ c_pos = ro_textarea_get_caret((uintptr_t)ta);
+ ro_textarea_replace_text((uintptr_t)ta, c_pos,
+ c_pos + 1, "");
+ } else {
+ /** \todo line end */
+ }
+ break;
+
+ /** pass on RETURN and ESCAPE to the parent icon */
+ case wimp_KEY_RETURN:
+ if (ta->flags & TEXTAREA_MULTILINE) {
+ /* Insert newline */
+ c_pos = ro_textarea_get_caret((uintptr_t)ta);
+ ro_textarea_insert_text((uintptr_t)ta, c_pos,
+ "\n");
+ ro_textarea_set_caret((uintptr_t)ta, ++c_pos);
+
+ redraw = true;
+
+ break;
+ }
+ /* fall through */
+ case wimp_KEY_ESCAPE:
+ keypress = *key;
+ keypress.w = ta->parent;
+ keypress.i = ta->icon;
+ keypress.index = 0; /* undefined if not in an icon */
+ error = xwimp_send_message_to_window(wimp_KEY_PRESSED,
+ (wimp_message*)&keypress, ta->parent,
+ ta->icon, 0);
+ if (error) {
+ LOG("xwimp_send_message: 0x%x:%s", error->errnum, error->errmess);
+ }
+ break;
+ }
+ }
+
+ if (redraw) {
+ wimp_draw update;
+
+ update.w = ta->window;
+ update.box.x0 = 0;
+ update.box.y1 = 0;
+ update.box.x1 = ta->vis_width;
+ update.box.y0 = -ta->line_height * (ta->line_count + 1);
+ ro_textarea_redraw_internal(&update, true);
+ }
+
+ return true;
+}
+
+/**
+ * Handle WIMP redraw requests for text areas
+ *
+ * \param redraw Redraw request block
+ */
+void ro_textarea_redraw(wimp_draw *redraw)
+{
+ ro_textarea_redraw_internal(redraw, false);
+}
+
+/**
+ * Internal textarea redraw routine
+ *
+ * \param redraw Redraw/update request block
+ * \param update True if update, false if full redraw
+ */
+void ro_textarea_redraw_internal(wimp_draw *redraw, bool update)
+{
+ struct text_area *ta;
+ int line;
+ osbool more;
+ rufl_code code;
+ os_error *error;
+
+ ta = (struct text_area *)ro_gui_wimp_event_get_user_data(redraw->w);
+
+ if (update)
+ error = xwimp_update_window(redraw, &more);
+ else
+ error = xwimp_redraw_window(redraw, &more);
+ if (error) {
+ LOG("xwimp_redraw_window: 0x%x: %s", error->errnum, error->errmess);
+ return;
+ }
+
+ while (more) {
+ int line0, line1;
+ int clip_y0, clip_y1;
+ clip_y0 = (redraw->box.y1-redraw->yscroll) - redraw->clip.y1;
+ clip_y1 = (redraw->box.y1-redraw->yscroll) - redraw->clip.y0;
+
+ error = xcolourtrans_set_gcol(
+ (ta->flags & TEXTAREA_READONLY) ? 0xD9D9D900
+ : 0xFFFFFF00,
+ colourtrans_SET_BG_GCOL | colourtrans_USE_ECFS_GCOL,
+ os_ACTION_OVERWRITE, 0, 0);
+ if (error) {
+ LOG("xcolourtrans_set_gcol: 0x%x: %s", error->errnum, error->errmess);
+ return;
+ }
+
+ error = xos_clg();
+ if (error) {
+ LOG("xos_clg: 0x%x: %s", error->errnum, error->errmess);
+ return;
+ }
+
+ if (!ta->lines)
+ /* Nothing to redraw */
+ return;
+
+ line0 = clip_y0 / ta->line_height - 1;
+ line1 = clip_y1 / ta->line_height + 1;
+
+ if (line0 < 0)
+ line0 = 0;
+ if (line1 < 0)
+ line1 = 0;
+ if (ta->line_count - 1 < (unsigned)line0)
+ line0 = ta->line_count - 1;
+ if (ta->line_count - 1 < (unsigned)line1)
+ line1 = ta->line_count - 1;
+ if (line1 < line0)
+ line1 = line0;
+
+ for (line = line0; line <= line1; line++) {
+ if (ta->lines[line].b_length == 0)
+ continue;
+
+ error = xcolourtrans_set_font_colours(font_CURRENT,
+ (ta->flags & TEXTAREA_READONLY) ?
+ 0xD9D9D900 : 0xFFFFFF00,
+ 0x00000000, 14, 0, 0, 0);
+ if (error) {
+ LOG("xcolourtrans_set_font_colours: 0x%x: %s", error->errnum, error->errmess);
+ return;
+ }
+
+ code = rufl_paint(ta->font_family, ta->font_style,
+ ta->font_size,
+ ta->text + ta->lines[line].b_start,
+ ta->lines[line].b_length,
+ redraw->box.x0 - redraw->xscroll + MARGIN_LEFT,
+ redraw->box.y1 - redraw->yscroll -
+ ((line + 1) *
+ ta->line_height - ta->line_spacing),
+ rufl_BLEND_FONT);
+ if (code != rufl_OK) {
+ if (code == rufl_FONT_MANAGER_ERROR)
+ LOG("rufl_paint: rufl_FONT_MANAGER_ERROR: 0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess);
+ else
+ LOG("rufl_paint: 0x%x", code);
+ }
+ }
+
+ error = xwimp_get_rectangle(redraw, &more);
+ if (error) {
+ LOG("xwimp_get_rectangle: 0x%x: %s", error->errnum, error->errmess);
+ return;
+ }
+ }
+}
+
+/**
+ * Handle a WIMP open window request
+ *
+ * \param open OpenWindow block
+ */
+void ro_textarea_open(wimp_open *open)
+{
+ os_error *error;
+
+ error = xwimp_open_window(open);
+ if (error) {
+ LOG("xwimp_open_window: 0x%x: %s", error->errnum, error->errmess);
+ return;
+ }
+}
diff --git a/frontends/riscos/textarea.h b/frontends/riscos/textarea.h
new file mode 100644
index 000000000..c726a0e78
--- /dev/null
+++ b/frontends/riscos/textarea.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2006 John-Mark Bell <jmb202@ecs.soton.ac.uk>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Single/Multi-line UTF-8 text area (interface)
+ */
+
+#ifndef _NETSURF_RISCOS_TEXTAREA_H_
+#define _NETSURF_RISCOS_TEXTAREA_H_
+#include <stdbool.h>
+#include <stdint.h>
+#include "rufl.h"
+#include "oslib/wimp.h"
+
+/* Text area flags */
+#define TEXTAREA_MULTILINE 0x01 /**< Text area is multiline */
+#define TEXTAREA_READONLY 0x02 /**< Text area is read only */
+
+uintptr_t ro_textarea_create(wimp_w parent, wimp_i icon, unsigned int flags,
+ const char *font_family, unsigned int font_size,
+ rufl_style font_style);
+bool ro_textarea_update(uintptr_t self);
+void ro_textarea_destroy(uintptr_t self);
+bool ro_textarea_set_text(uintptr_t self, const char *text);
+int ro_textarea_get_text(uintptr_t self, char *buf, unsigned int len);
+void ro_textarea_insert_text(uintptr_t self, unsigned int index,
+ const char *text);
+void ro_textarea_replace_text(uintptr_t self, unsigned int start,
+ unsigned int end, const char *text);
+void ro_textarea_set_caret(uintptr_t self, unsigned int caret);
+void ro_textarea_set_caret_xy(uintptr_t self, int x, int y);
+unsigned int ro_textarea_get_caret(uintptr_t self);
+
+
+#endif
diff --git a/frontends/riscos/textselection.c b/frontends/riscos/textselection.c
new file mode 100644
index 000000000..718171db0
--- /dev/null
+++ b/frontends/riscos/textselection.c
@@ -0,0 +1,657 @@
+/*
+ * Copyright 2005 Adrian Lees <adrianl@users.sourceforge.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Text selection code (platform-dependent implementation)
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <oslib/osfile.h>
+#include <oslib/wimp.h>
+
+#include "utils/log.h"
+#include "utils/utf8.h"
+#include "utils/utils.h"
+#include "content/hlcache.h"
+#include "desktop/gui_clipboard.h"
+#include "desktop/gui_window.h"
+#include "desktop/textinput.h"
+#include "desktop/browser.h"
+
+#include "riscos/gui.h"
+#include "riscos/menus.h"
+#include "riscos/message.h"
+#include "riscos/mouse.h"
+#include "riscos/save.h"
+#include "riscos/textselection.h"
+#include "riscos/ucstables.h"
+
+
+#ifndef wimp_DRAG_CLAIM_SUPPRESS_DRAGBOX
+#define wimp_DRAG_CLAIM_SUPPRESS_DRAGBOX ((wimp_drag_claim_flags) 0x2u)
+#endif
+
+
+/** Receive of Dragging message has claimed it */
+static bool dragging_claimed = false;
+static wimp_t dragging_claimant;
+static os_box dragging_box = { -34, -34, 34, 34 }; /* \todo - size properly */
+static wimp_drag_claim_flags last_claim_flags = 0;
+static struct gui_window *last_start_window;
+
+static bool drag_claimed = false;
+
+static bool owns_clipboard = false;
+static bool owns_caret_and_selection = false;
+
+/* Current clipboard contents if we own the clipboard
+ * Current paste buffer if we don't
+ */
+static char *clipboard = NULL;
+static size_t clip_length = 0;
+
+/* Paste context */
+static ro_gui_selection_prepare_paste_cb paste_cb = NULL;
+static void *paste_cb_pw = NULL;
+static int paste_prev_message = 0;
+
+static void ro_gui_selection_drag_end(wimp_dragged *drag, void *g);
+static void ro_gui_discard_clipboard_contents(void);
+static void ro_gui_dragging_bounced(wimp_message *message);
+
+
+/**
+ * Start drag-selecting text within a browser window (RO-dependent part)
+ *
+ * \param g gui window
+ */
+
+void gui_start_selection(struct gui_window *g)
+{
+ wimp_full_message_claim_entity msg;
+ wimp_auto_scroll_info scroll;
+ wimp_window_state state;
+ wimp_drag drag;
+ os_error *error;
+
+ LOG("starting text_selection drag");
+
+ state.w = g->window;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ /* claim caret and selection */
+ msg.size = sizeof(msg);
+ msg.your_ref = 0;
+ msg.action = message_CLAIM_ENTITY;
+ msg.flags = wimp_CLAIM_CARET_OR_SELECTION;
+
+ error = xwimp_send_message(wimp_USER_MESSAGE,
+ (wimp_message*)&msg, wimp_BROADCAST);
+ if (error) {
+ LOG("xwimp_send_message: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+ owns_caret_and_selection = true;
+
+ scroll.w = g->window;
+ scroll.pause_zone_sizes.x0 = 80;
+ scroll.pause_zone_sizes.y0 = 80;
+ scroll.pause_zone_sizes.x1 = 80;
+ scroll.pause_zone_sizes.y1 = 80;
+ scroll.pause_duration = 0;
+ scroll.state_change = (void *)0;
+ error = xwimp_auto_scroll(wimp_AUTO_SCROLL_ENABLE_VERTICAL |
+ wimp_AUTO_SCROLL_ENABLE_HORIZONTAL,
+ &scroll, 0);
+ if (error)
+ LOG("xwimp_auto_scroll: 0x%x: %s", error->errnum, error->errmess);
+
+ ro_mouse_drag_start(ro_gui_selection_drag_end, ro_gui_window_mouse_at,
+ NULL, g);
+
+ drag.type = wimp_DRAG_USER_POINT;
+ /* Don't constrain mouse pointer during drags */
+ drag.bbox.x0 = -16384;
+ drag.bbox.y0 = -16384;
+ drag.bbox.x1 = 16384;
+ drag.bbox.y1 = 16384;
+
+ error = xwimp_drag_box(&drag);
+ if (error) {
+ LOG("xwimp_drag_box: 0x%x : %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+ last_start_window = g;
+}
+
+
+/**
+ * End of text selection drag operation
+ *
+ * \param *drag position of pointer at conclusion of drag
+ * \param *data gui window pointer.
+ */
+
+static void ro_gui_selection_drag_end(wimp_dragged *drag, void *data)
+{
+ wimp_auto_scroll_info scroll;
+ wimp_pointer pointer;
+ os_error *error;
+ os_coord pos;
+ struct gui_window *g = (struct gui_window *) data;
+
+ scroll.w = g->window;
+ error = xwimp_auto_scroll(0, &scroll, 0);
+ if (error)
+ LOG("xwimp_auto_scroll: 0x%x: %s", error->errnum, error->errmess);
+
+ error = xwimp_drag_box((wimp_drag*)-1);
+ if (error) {
+ LOG("xwimp_drag_box: 0x%x : %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+
+ error = xwimp_get_pointer_info(&pointer);
+ if (error) {
+ LOG("xwimp_get_pointer_info 0x%x : %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ if (ro_gui_window_to_window_pos(g, drag->final.x0, drag->final.y0, &pos))
+ browser_window_mouse_track(g->bw, 0, pos.x, pos.y);
+}
+
+/**
+ * Core tells front end to put given text in clipboard
+ *
+ * \param buffer UTF-8 text, owned by core
+ * \param length Byte length of UTF-8 text in buffer
+ * \param styles Array of styles given to text runs, owned by core, or NULL
+ * \param n_styles Number of text run styles in array
+ */
+static void gui_set_clipboard(const char *buffer, size_t length,
+ nsclipboard_styles styles[], int n_styles)
+{
+ char *new_cb;
+
+ if (length == 0)
+ return;
+
+ new_cb = malloc(length);
+ if (new_cb == NULL)
+ return;
+
+ memcpy(new_cb, buffer, length);
+
+ /* Replace existing clipboard contents */
+ free(clipboard);
+ clipboard = new_cb;
+ clip_length = length;
+
+ if (!owns_clipboard) {
+ /* Tell RO we now own clipboard */
+ wimp_full_message_claim_entity msg;
+ os_error *error;
+
+ LOG("claiming clipboard");
+
+ msg.size = sizeof(msg);
+ msg.your_ref = 0;
+ msg.action = message_CLAIM_ENTITY;
+ msg.flags = wimp_CLAIM_CLIPBOARD;
+
+ error = xwimp_send_message(wimp_USER_MESSAGE,
+ (wimp_message*)&msg, wimp_BROADCAST);
+ if (error) {
+ LOG("xwimp_send_message: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+ owns_clipboard = true;
+ }
+
+ LOG("clipboard now holds %zd bytes", clip_length);
+}
+
+
+/**
+ * Core asks front end for clipboard contents.
+ *
+ * \param buffer UTF-8 text, allocated by front end, ownership yielded to core
+ * \param length Byte length of UTF-8 text in buffer
+ */
+static void gui_get_clipboard(char **buffer, size_t *length)
+{
+ *buffer = NULL;
+ *length = 0;
+
+ if (clip_length > 0) {
+ char *cb = malloc(clip_length);
+ if (cb != NULL) {
+ memcpy(cb, clipboard, clip_length);
+ *buffer = cb;
+ *length = clip_length;
+ }
+ }
+}
+
+
+/**
+ * Discard the current contents of the clipboard, if any, releasing the
+ * memory it uses.
+ */
+
+void ro_gui_discard_clipboard_contents(void)
+{
+ free(clipboard);
+ clipboard = NULL;
+ clip_length = 0;
+}
+
+
+static void ro_gui_selection_prepare_paste_complete(void)
+{
+ ro_gui_selection_prepare_paste_cb cb = paste_cb;
+ void *pw = paste_cb_pw;
+
+ paste_cb = NULL;
+ paste_cb_pw = NULL;
+ paste_prev_message = 0;
+
+ cb(pw);
+}
+
+static void ro_gui_selection_prepare_paste_bounced(wimp_message *message)
+{
+ ro_gui_selection_prepare_paste_complete();
+}
+
+/**
+ * Prepare to paste data from another application
+ *
+ * \param w Window being pasted into
+ * \param cb Callback to call once preparation is complete
+ * \param pw Private data for callback
+ */
+
+void ro_gui_selection_prepare_paste(wimp_w w,
+ ro_gui_selection_prepare_paste_cb cb, void *pw)
+{
+ if (owns_clipboard) {
+ /* We own the clipboard: we're already prepared */
+ cb(pw);
+ } else {
+ /* Someone else owns the clipboard: request its contents */
+ wimp_full_message_data_request msg;
+ bool success;
+
+ ro_gui_discard_clipboard_contents();
+
+ msg.size = 48; /* There's only one filetype listed. */
+ msg.your_ref = 0;
+ msg.action = message_DATA_REQUEST;
+ msg.w = w;
+ msg.i = -1;
+ msg.pos.x = 0;
+ msg.pos.y = 0;
+ msg.flags = wimp_DATA_REQUEST_CLIPBOARD;
+ msg.file_types[0] = osfile_TYPE_TEXT;
+ msg.file_types[1] = ~0;
+
+ success = ro_message_send_message(wimp_USER_MESSAGE_RECORDED,
+ (wimp_message *) &msg, wimp_BROADCAST,
+ ro_gui_selection_prepare_paste_bounced);
+ if (success == false) {
+ /* Ensure key is handled, anyway */
+ cb(pw);
+ } else {
+ /* Set up paste context */
+ paste_cb = cb;
+ paste_cb_pw = pw;
+ paste_prev_message = msg.my_ref;
+ }
+ }
+}
+
+/**
+ * Prepare to paste data from another application (step 2)
+ *
+ * \param dataxfer DataSave message
+ * \return True if message was handled, false otherwise
+ */
+bool ro_gui_selection_prepare_paste_datasave(
+ wimp_full_message_data_xfer *dataxfer)
+{
+ bool success;
+
+ /* Ignore messages that aren't for us */
+ if (dataxfer->your_ref == 0 || dataxfer->your_ref != paste_prev_message)
+ return false;
+
+ /* We're done if the paste data isn't text */
+ if (dataxfer->file_type != osfile_TYPE_TEXT) {
+ ro_gui_selection_prepare_paste_complete();
+ return true;
+ }
+
+ /* Generate and send DataSaveAck */
+ dataxfer->your_ref = dataxfer->my_ref;
+ dataxfer->size = offsetof(wimp_full_message_data_xfer, file_name) + 16;
+ dataxfer->action = message_DATA_SAVE_ACK;
+ dataxfer->est_size = -1;
+ memcpy(dataxfer->file_name, "<Wimp$Scrap>", SLEN("<Wimp$Scrap>") + 1);
+
+ success = ro_message_send_message(wimp_USER_MESSAGE_RECORDED,
+ (wimp_message *) dataxfer, dataxfer->sender,
+ ro_gui_selection_prepare_paste_bounced);
+ if (success == false) {
+ ro_gui_selection_prepare_paste_complete();
+ } else {
+ paste_prev_message = dataxfer->my_ref;
+ }
+
+ return true;
+}
+
+
+/**
+ * Prepare to paste data from another application (step 3)
+ *
+ * \param dataxfer DataLoad message
+ * \return True if message was handled, false otherwise
+ */
+bool ro_gui_selection_prepare_paste_dataload(
+ wimp_full_message_data_xfer *dataxfer)
+{
+ FILE *fp;
+
+ /* Ignore messages that aren't for us */
+ if (dataxfer->your_ref == 0 || dataxfer->your_ref != paste_prev_message)
+ return false;
+
+ fp = fopen(dataxfer->file_name, "r");
+ if (fp != NULL) {
+ long size;
+ fseek(fp, 0, SEEK_END);
+ size = ftell(fp);
+ fseek(fp, 0, SEEK_SET);
+
+ if (size > 0) {
+ char *local_cb = malloc(size);
+ if (local_cb != NULL) {
+ nserror ret;
+ fread(local_cb, 1, size, fp);
+
+ ret = utf8_from_local_encoding(local_cb, size,
+ &clipboard);
+ if (ret == NSERROR_OK) {
+ clip_length = strlen(clipboard);
+ }
+
+ free(local_cb);
+ }
+ }
+
+ fclose(fp);
+ }
+
+ /* Send DataLoadAck */
+ dataxfer->action = message_DATA_LOAD_ACK;
+ dataxfer->your_ref = dataxfer->my_ref;
+ ro_message_send_message(wimp_USER_MESSAGE,
+ (wimp_message *) dataxfer, dataxfer->sender, NULL);
+
+ ro_gui_selection_prepare_paste_complete();
+ return true;
+}
+
+
+/**
+ * Responds to CLAIM_ENTITY message notifying us that the caret
+ * and selection or clipboard have been claimed by another application.
+ *
+ * \param claim CLAIM_ENTITY message
+ */
+
+void ro_gui_selection_claim_entity(wimp_full_message_claim_entity *claim)
+{
+ /* ignore our own broadcasts! */
+ if (claim->sender != task_handle) {
+
+ LOG("%x", claim->flags);
+
+ if (claim->flags & wimp_CLAIM_CARET_OR_SELECTION) {
+ owns_caret_and_selection = false;
+ }
+
+ if (claim->flags & wimp_CLAIM_CLIPBOARD) {
+ ro_gui_discard_clipboard_contents();
+ owns_clipboard = false;
+ }
+ }
+}
+
+
+/**
+ * Responds to DATA_REQUEST message, returning information about the
+ * clipboard contents if we own the clipboard.
+ *
+ * \param req DATA_REQUEST message
+ */
+
+void ro_gui_selection_data_request(wimp_full_message_data_request *req)
+{
+ if (owns_clipboard && clip_length > 0 &&
+ (req->flags & wimp_DATA_REQUEST_CLIPBOARD)) {
+ wimp_full_message_data_xfer message;
+ int size;
+// int i;
+
+// for(i = 0; i < NOF_ELEMENTS(req->file_types); i++) {
+// bits ftype = req->file_types[i];
+// if (ftype == ~0U) break; /* list terminator */
+//
+// LOG("type %x", ftype);
+// i++;
+// }
+
+ /* we can only supply text at the moment, so that's what you're getting! */
+ size = offsetof(wimp_full_message_data_xfer, file_name) + 9;
+ message.size = (size + 3) & ~3;
+ message.your_ref = req->my_ref;
+ message.action = message_DATA_SAVE;
+ message.w = req->w;
+ message.i = req->i;
+ message.pos = req->pos;
+ message.file_type = osfile_TYPE_TEXT;
+ message.est_size = clip_length;
+ memcpy(message.file_name, "TextFile", 9);
+
+ ro_gui_send_datasave(GUI_SAVE_CLIPBOARD_CONTENTS,
+ &message, req->sender);
+ }
+}
+
+
+/**
+ * Save the clipboard contents to a file.
+ *
+ * \param path the pathname of the file
+ * \return true iff success, otherwise reporting the error before returning false
+ */
+
+bool ro_gui_save_clipboard(const char *path)
+{
+ char *local_cb;
+ nserror ret;
+ os_error *error;
+
+ assert(clip_length > 0 && clipboard);
+
+ ret = utf8_to_local_encoding(clipboard, clip_length, &local_cb);
+ if (ret != NSERROR_OK) {
+ ro_warn_user("SaveError", "Could not convert");
+ return false;
+ }
+
+ error = xosfile_save_stamped(path, osfile_TYPE_TEXT,
+ (byte*) local_cb,
+ (byte*) local_cb + strlen(local_cb));
+
+ free(local_cb);
+
+ if (error) {
+ LOG("xosfile_save_stamped: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("SaveError", error->errmess);
+ return false;
+ }
+
+ return true;
+}
+
+
+/**
+ * Handler for Message_Dragging, used to implement auto-scrolling and
+ * ghost caret when a drag is in progress.
+ */
+
+void ro_gui_selection_dragging(wimp_message *message)
+{
+ wimp_full_message_dragging *drag = (wimp_full_message_dragging*)message;
+ struct gui_window *g;
+ os_coord pos;
+
+ /* with autoscrolling, we will probably need to remember the
+ * gui_window and override the drag->w window handle which
+ * could be any window on the desktop */
+ g = ro_gui_window_lookup(drag->w);
+
+ if ((drag->flags & wimp_DRAGGING_TERMINATE_DRAG) || !g) {
+
+ drag_claimed = false;
+ return;
+ }
+
+ if (!ro_gui_window_to_window_pos(g, drag->pos.x, drag->pos.y, &pos))
+ return;
+
+ drag_claimed = false;
+}
+
+
+
+/**
+ * Reset drag-and-drop state when drag completes (DataSave received)
+ */
+
+void ro_gui_selection_drag_reset(void)
+{
+ drag_claimed = false;
+}
+
+
+/**
+ *
+ */
+
+void ro_gui_selection_drag_claim(wimp_message *message)
+{
+ wimp_full_message_drag_claim *claim = (wimp_full_message_drag_claim*)message;
+
+ dragging_claimant = message->sender;
+ dragging_claimed = true;
+
+ /* have we been asked to remove the drag box/sprite? */
+ if (claim->flags & wimp_DRAG_CLAIM_SUPPRESS_DRAGBOX) {
+ ro_gui_drag_box_cancel();
+ }
+ else {
+ /* \todo - restore it here? */
+ }
+
+ /* do we need to restore the default pointer shape? */
+ if ((last_claim_flags & wimp_DRAG_CLAIM_POINTER_CHANGED) &&
+ !(claim->flags & wimp_DRAG_CLAIM_POINTER_CHANGED)) {
+ gui_window_set_pointer(last_start_window, GUI_POINTER_DEFAULT);
+ }
+
+ last_claim_flags = claim->flags;
+}
+
+
+void ro_gui_selection_send_dragging(wimp_pointer *pointer)
+{
+ wimp_full_message_dragging dragmsg;
+
+ LOG("sending DRAGGING to %p, %d", pointer->w, pointer->i);
+
+ dragmsg.size = offsetof(wimp_full_message_dragging, file_types) + 8;
+ dragmsg.your_ref = 0;
+ dragmsg.action = message_DRAGGING;
+ dragmsg.w = pointer->w;
+ dragmsg.i = pointer->i;
+ dragmsg.pos = pointer->pos;
+/* \todo - this is interesting because it depends upon not just the state of the
+ shift key, but also whether it /can/ be deleted, ie. from text area/input
+ rather than page contents */
+ dragmsg.flags = wimp_DRAGGING_FROM_SELECTION;
+ dragmsg.box = dragging_box;
+ dragmsg.file_types[0] = osfile_TYPE_TEXT;
+ dragmsg.file_types[1] = ~0;
+
+ /* if the message_dragmsg messages have been claimed we must address them
+ to the claimant task, which is not necessarily the task that owns whatever
+ window happens to be under the pointer */
+
+ if (dragging_claimed) {
+ ro_message_send_message(wimp_USER_MESSAGE_RECORDED,
+ (wimp_message*)&dragmsg, dragging_claimant, ro_gui_dragging_bounced);
+ }
+ else {
+ ro_message_send_message_to_window(wimp_USER_MESSAGE_RECORDED,
+ (wimp_message*)&dragmsg, pointer->w, pointer->i,
+ ro_gui_dragging_bounced, &dragging_claimant);
+ }
+}
+
+
+/**
+ * Our message_DRAGGING message was bounced, ie. the intended recipient does not
+ * support the drag-and-drop protocol or cannot receive the data at the pointer
+ * position.
+ */
+
+void ro_gui_dragging_bounced(wimp_message *message)
+{
+ dragging_claimed = false;
+}
+
+static struct gui_clipboard_table clipboard_table = {
+ .get = gui_get_clipboard,
+ .set = gui_set_clipboard,
+};
+
+struct gui_clipboard_table *riscos_clipboard_table = &clipboard_table;
diff --git a/frontends/riscos/textselection.h b/frontends/riscos/textselection.h
new file mode 100644
index 000000000..400e3dd26
--- /dev/null
+++ b/frontends/riscos/textselection.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2006 Adrian Lees <adrianl@users.sourceforge.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Text selection import/export (interface).
+ */
+
+#ifndef _NETSURF_RISCOS_TEXTSELECTION_H_
+#define _NETSURF_RISCOS_TEXTSELECTION_H_
+
+#include "oslib/wimp.h"
+
+struct gui_clipboard_table *riscos_clipboard_table;
+
+void gui_start_selection(struct gui_window *g);
+
+typedef void (*ro_gui_selection_prepare_paste_cb)(void *pw);
+
+void ro_gui_selection_prepare_paste(wimp_w w,
+ ro_gui_selection_prepare_paste_cb cb, void *pw);
+bool ro_gui_selection_prepare_paste_datasave(
+ wimp_full_message_data_xfer *dataxfer);
+bool ro_gui_selection_prepare_paste_dataload(
+ wimp_full_message_data_xfer *dataxfer);
+
+void ro_gui_selection_claim_entity(wimp_full_message_claim_entity *claim);
+void ro_gui_selection_data_request(wimp_full_message_data_request *req);
+bool ro_gui_save_clipboard(const char *path);
+
+/* drag-and-drop, receiving */
+void ro_gui_selection_dragging(wimp_message *message);
+void ro_gui_selection_drag_reset(void);
+
+/* drag-and-drop, sending */
+void ro_gui_selection_send_dragging(wimp_pointer *pointer);
+void ro_gui_selection_drag_claim(wimp_message *message);
+
+#endif
diff --git a/frontends/riscos/theme.c b/frontends/riscos/theme.c
new file mode 100644
index 000000000..714b9e5a1
--- /dev/null
+++ b/frontends/riscos/theme.c
@@ -0,0 +1,741 @@
+/*
+ * Copyright 2004, 2005 Richard Wilson <info@tinct.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Window themes (implementation).
+ */
+
+#include <alloca.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+#include "oslib/dragasprite.h"
+#include "oslib/os.h"
+#include "oslib/osgbpb.h"
+#include "oslib/osfile.h"
+#include "oslib/osfind.h"
+#include "oslib/osspriteop.h"
+#include "oslib/wimpspriteop.h"
+#include "oslib/squash.h"
+#include "oslib/wimp.h"
+#include "oslib/wimpextend.h"
+#include "oslib/wimpspriteop.h"
+
+#include "utils/nsoption.h"
+#include "utils/log.h"
+#include "content/content.h"
+
+#include "riscos/cookies.h"
+#include "riscos/dialog.h"
+#include "riscos/global_history.h"
+#include "riscos/gui.h"
+#include "riscos/hotlist.h"
+#include "riscos/menus.h"
+#include "riscos/theme.h"
+#include "riscos/treeview.h"
+#include "riscos/wimp.h"
+#include "riscos/wimp_event.h"
+#include "riscos/wimputils.h"
+
+/** @todo provide a proper interface for these and make them static again! */
+
+static struct theme_descriptor *theme_current = NULL;
+static struct theme_descriptor *theme_descriptors = NULL;
+
+static bool ro_gui_theme_add_descriptor(const char *folder, const char *leafname);
+static void ro_gui_theme_get_available_in_dir(const char *directory);
+static void ro_gui_theme_free(struct theme_descriptor *descriptor);
+
+/**
+ * Initialise the theme handler
+ */
+void ro_gui_theme_initialise(void)
+{
+ struct theme_descriptor *descriptor;
+
+ theme_descriptors = ro_gui_theme_get_available();
+ descriptor = ro_gui_theme_find(nsoption_charp(theme));
+ if (!descriptor)
+ descriptor = ro_gui_theme_find("Aletheia");
+ ro_gui_theme_apply(descriptor);
+}
+
+
+/**
+ * Finalise the theme handler
+ */
+void ro_gui_theme_finalise(void)
+{
+ ro_gui_theme_close(theme_current, false);
+ ro_gui_theme_free(theme_descriptors);
+}
+
+
+/**
+ * Finds a theme from the cached values.
+ *
+ * The returned theme is only guaranteed to be valid until the next call
+ * to ro_gui_theme_get_available() unless it has been opened using
+ * ro_gui_theme_open().
+ *
+ * \param leafname the filename of the theme_descriptor to return
+ * \return the requested theme_descriptor, or NULL if not found
+ */
+struct theme_descriptor *ro_gui_theme_find(const char *leafname)
+{
+ struct theme_descriptor *descriptor;
+
+ if (!leafname)
+ return NULL;
+
+ for (descriptor = theme_descriptors; descriptor;
+ descriptor = descriptor->next)
+ if (!strcmp(leafname, descriptor->leafname))
+ return descriptor;
+ /* fallback for 10 chars on old filesystems */
+ for (descriptor = theme_descriptors; descriptor;
+ descriptor = descriptor->next)
+ if (!strncmp(leafname, descriptor->leafname, 10))
+ return descriptor;
+ return NULL;
+}
+
+
+/**
+ * Reads and caches the currently available themes.
+ *
+ * \return the requested theme_descriptor, or NULL if not found
+ */
+struct theme_descriptor *ro_gui_theme_get_available(void)
+{
+ struct theme_descriptor *current;
+ struct theme_descriptor *test;
+
+ /* close any unused descriptors */
+ ro_gui_theme_free(theme_descriptors);
+
+ /* add our default 'Aletheia' theme */
+ ro_gui_theme_add_descriptor("NetSurf:Resources", "Aletheia");
+
+ /* scan our choices directory */
+ ro_gui_theme_get_available_in_dir(nsoption_charp(theme_path));
+
+ /* sort alphabetically in a very rubbish way */
+ if ((theme_descriptors) && (theme_descriptors->next)) {
+ current = theme_descriptors;
+ while ((test = current->next)) {
+ if (strcmp(current->name, test->name) > 0) {
+ current->next->previous = current->previous;
+ if (current->previous)
+ current->previous->next = current->next;
+ current->next = test->next;
+ test->next = current;
+ current->previous = test;
+ if (current->next)
+ current->next->previous = current;
+
+ current = test->previous;
+ if (!current) current = test;
+ } else {
+ current = current->next;
+ }
+ }
+ while (theme_descriptors->previous)
+ theme_descriptors = theme_descriptors->previous;
+ }
+
+ return theme_descriptors;
+}
+
+
+/**
+ * Adds the themes in a directory to the global cache.
+ *
+ * \param directory the directory to scan
+ */
+static void ro_gui_theme_get_available_in_dir(const char *directory)
+{
+ int context = 0;
+ int read_count;
+ osgbpb_INFO(100) info;
+
+ while (context != -1) {
+ /* read some directory info */
+ os_error *error = xosgbpb_dir_entries_info(directory,
+ (osgbpb_info_list *) &info, 1, context,
+ sizeof(info), 0, &read_count, &context);
+ if (error) {
+ LOG("xosgbpb_dir_entries_info: 0x%x: %s",
+ error->errnum, error->errmess);
+ if (error->errnum == 0xd6) /* no such dir */
+ return;
+ ro_warn_user("MiscError", error->errmess);
+ break;
+ }
+
+ /* only process files */
+ if ((read_count != 0) && (info.obj_type == fileswitch_IS_FILE))
+ ro_gui_theme_add_descriptor(directory, info.name);
+ }
+}
+
+
+/**
+ * Returns the current theme handle, or NULL if none is set.
+ *
+ * \return The theme descriptor handle, or NULL.
+ */
+
+struct theme_descriptor *ro_gui_theme_get_current(void)
+{
+ return theme_current;
+}
+
+
+/**
+ * Returns a sprite area for use with the given theme. This may return a
+ * pointer to the wimp sprite pool if a theme area isn't available.
+ *
+ * \param *descriptor The theme to use, or NULL for the current.
+ * \return A pointer to the theme sprite area.
+ */
+
+osspriteop_area *ro_gui_theme_get_sprites(struct theme_descriptor *descriptor)
+{
+ osspriteop_area *area;
+
+ if (descriptor == NULL)
+ descriptor = theme_current;
+
+ if (descriptor != NULL && descriptor->theme != NULL)
+ area = descriptor->theme->sprite_area;
+ else
+ area = (osspriteop_area *) 1;
+
+ return area;
+}
+
+
+/**
+ * Returns an interger element from the specified theme, or the current theme
+ * if the descriptor is NULL.
+ *
+ * This is an attempt to abstract the theme data from its clients: it should
+ * simplify the task of expanding the theme system in the future should this
+ * be necessary to include other parts of the RISC OS GUI in the theme system.
+ *
+ * \param *descriptor The theme to use, or NULL for the current.
+ * \param style The style to use.
+ * \param element The style element to return.
+ * \return The requested value, or 0.
+ */
+
+int ro_gui_theme_get_style_element(struct theme_descriptor *descriptor,
+ theme_style style, theme_element element)
+{
+ if (descriptor == NULL)
+ descriptor = theme_current;
+
+ if (descriptor == NULL)
+ return 0;
+
+ switch (style) {
+ case THEME_STYLE_NONE:
+ switch(element) {
+ case THEME_ELEMENT_FOREGROUND:
+ return wimp_COLOUR_BLACK;
+ case THEME_ELEMENT_BACKGROUND:
+ return wimp_COLOUR_VERY_LIGHT_GREY;
+ default:
+ return 0;
+ }
+ break;
+
+ case THEME_STYLE_BROWSER_TOOLBAR:
+ switch (element) {
+ case THEME_ELEMENT_FOREGROUND:
+ return wimp_COLOUR_BLACK;
+ case THEME_ELEMENT_BACKGROUND:
+ return descriptor->browser_background;
+ default:
+ return 0;
+ }
+ break;
+
+ case THEME_STYLE_HOTLIST_TOOLBAR:
+ case THEME_STYLE_COOKIES_TOOLBAR:
+ case THEME_STYLE_GLOBAL_HISTORY_TOOLBAR:
+ switch (element) {
+ case THEME_ELEMENT_FOREGROUND:
+ return wimp_COLOUR_BLACK;
+ case THEME_ELEMENT_BACKGROUND:
+ return descriptor->hotlist_background;
+ default:
+ return 0;
+ }
+ break;
+
+ case THEME_STYLE_STATUS_BAR:
+ switch (element) {
+ case THEME_ELEMENT_FOREGROUND:
+ return descriptor->status_foreground;
+ case THEME_ELEMENT_BACKGROUND:
+ return descriptor->status_background;
+ default:
+ return 0;
+ }
+ break;
+
+ default:
+ return 0;
+ }
+}
+
+/**
+ * Returns details of the throbber as defined in a theme.
+ *
+ * \param *descriptor The theme of interest (NULL for current).
+ * \param *frames Return the number of animation frames.
+ * \param *width Return the throbber width.
+ * \param *height Return the throbber height.
+ * \param *right Return the 'locate on right' flag.
+ * \param *redraw Return the 'forcible redraw' flag.
+ * \return true if meaningful data has been returned;
+ * else false.
+ */
+
+bool ro_gui_theme_get_throbber_data(struct theme_descriptor *descriptor,
+ int *frames, int *width, int *height,
+ bool *right, bool *redraw)
+{
+ if (descriptor == NULL)
+ descriptor = theme_current;
+
+ if (descriptor == NULL || descriptor->theme == NULL)
+ return false;
+
+ if (frames != NULL)
+ *frames = descriptor->theme->throbber_frames;
+ if (width != NULL)
+ *width = descriptor->theme->throbber_width;
+ if (height != NULL)
+ *height = descriptor->theme->throbber_height;
+ if (right != NULL)
+ *right = descriptor->throbber_right;
+ if (redraw != NULL)
+ *redraw = descriptor->throbber_redraw;
+
+ return true;
+}
+
+
+/**
+ * Checks a theme is valid and adds it to the current list
+ *
+ * \param folder the theme folder
+ * \param leafname the theme leafname
+ * \return whether the theme was added
+ */
+bool ro_gui_theme_add_descriptor(const char *folder, const char *leafname)
+{
+ struct theme_file_header file_header;
+ struct theme_descriptor *current;
+ struct theme_descriptor *test;
+ int output_left;
+ os_fw file_handle;
+ os_error *error;
+ char *filename;
+
+ /* create a full filename */
+ filename = malloc(strlen(folder) + strlen(leafname) + 2);
+ if (!filename) {
+ LOG("No memory for malloc");
+ ro_warn_user("NoMemory", 0);
+ return false;
+ }
+ sprintf(filename, "%s.%s", folder, leafname);
+
+ /* get the header */
+ error = xosfind_openinw(osfind_NO_PATH, filename, 0,
+ &file_handle);
+ if (error) {
+ LOG("xosfind_openinw: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("FileError", error->errmess);
+ free(filename);
+ return false;
+ }
+ if (file_handle == 0) {
+ free(filename);
+ return false;
+ }
+ error = xosgbpb_read_atw(file_handle,
+ (byte *) &file_header,
+ sizeof (struct theme_file_header),
+ 0, &output_left);
+ xosfind_closew(file_handle);
+ if (error) {
+ LOG("xosbgpb_read_atw: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("FileError", error->errmess);
+ free(filename);
+ return false;
+ }
+ if (output_left > 0) { /* should try to read more? */
+ free(filename);
+ return false;
+ }
+
+ /* create a new theme descriptor */
+ current = (struct theme_descriptor *)calloc(1,
+ sizeof(struct theme_descriptor));
+ if (!current) {
+ LOG("calloc failed");
+ ro_warn_user("NoMemory", 0);
+ free(filename);
+ return false;
+ }
+ if (!ro_gui_theme_read_file_header(current, &file_header)) {
+ free(filename);
+ free(current);
+ return false;
+ }
+ current->filename = filename;
+ current->leafname = current->filename + strlen(folder) + 1;
+
+ /* don't add duplicates */
+ for (test = theme_descriptors; test; test = test->next) {
+ if (!strcmp(current->name, test->name)) {
+ free(current->filename);
+ free(current);
+ return false;
+ }
+ }
+
+ /* link in our new descriptor at the head*/
+ if (theme_descriptors) {
+ current->next = theme_descriptors;
+ theme_descriptors->previous = current;
+ }
+ theme_descriptors = current;
+ return true;
+
+}
+
+
+/**
+ * Fills in the basic details for a descriptor from a file header.
+ * The filename string is not set.
+ *
+ * \param descriptor the descriptor to set up
+ * \param file_header the header to read from
+ * \return false for a badly formed theme, true otherwise
+ */
+bool ro_gui_theme_read_file_header(struct theme_descriptor *descriptor,
+ struct theme_file_header *file_header)
+{
+ if ((file_header->magic_value != 0x4d54534e) ||
+ (file_header->parser_version > 2))
+ return false;
+
+ strcpy(descriptor->name, file_header->name);
+ strcpy(descriptor->author, file_header->author);
+ descriptor->browser_background = file_header->browser_bg;
+ descriptor->hotlist_background = file_header->hotlist_bg;
+ descriptor->status_background = file_header->status_bg;
+ descriptor->status_foreground = file_header->status_fg;
+ descriptor->decompressed_size = file_header->decompressed_sprite_size;
+ descriptor->compressed_size = file_header->compressed_sprite_size;
+ if (file_header->parser_version >= 2) {
+ descriptor->throbber_right =
+ !(file_header->theme_flags & (1 << 0));
+ descriptor->throbber_redraw =
+ file_header->theme_flags & (1 << 1);
+ } else {
+ descriptor->throbber_right =
+ (file_header->theme_flags == 0x00);
+ descriptor->throbber_redraw = true;
+ }
+ return true;
+}
+
+
+/**
+ * Opens a theme ready for use.
+ *
+ * \param descriptor the theme_descriptor to open
+ * \param list whether to open all themes in the list
+ * \return whether the operation was successful
+ */
+bool ro_gui_theme_open(struct theme_descriptor *descriptor, bool list)
+{
+ fileswitch_object_type obj_type;
+ squash_output_status status;
+ os_coord dimensions;
+ os_mode mode;
+ os_error *error;
+ struct theme_descriptor *next_descriptor;
+ char sprite_name[16];
+ const char *name = sprite_name;
+ bool result = true;
+ int i, n;
+ int workspace_size, file_size;
+ char *raw_data, *workspace;
+ osspriteop_area *decompressed;
+
+ /* If we are freeing the whole of the list then we need to
+ start at the first descriptor.
+ */
+ if (list && descriptor)
+ while (descriptor->previous) descriptor = descriptor->previous;
+
+ /* Open the themes
+ */
+ for (; descriptor; descriptor = next_descriptor) {
+ /* see if we should iterate through the entire list */
+ if (list)
+ next_descriptor = descriptor->next;
+ else
+ next_descriptor = NULL;
+
+ /* if we are already loaded, increase the usage count */
+ if (descriptor->theme) {
+ descriptor->theme->users = descriptor->theme->users + 1;
+ continue;
+ }
+
+ /* create a new theme */
+ descriptor->theme = (struct theme *)calloc(1,
+ sizeof(struct theme));
+ if (!descriptor->theme) {
+ LOG("calloc() failed");
+ ro_warn_user("NoMemory", 0);
+ continue;
+ }
+ descriptor->theme->users = 1;
+
+ /* try to load the associated file */
+ error = xosfile_read_stamped_no_path(descriptor->filename,
+ &obj_type, 0, 0, &file_size, 0, 0);
+ if (error) {
+ LOG("xosfile_read_stamped_no_path: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("FileError", error->errmess);
+ continue;
+ }
+ if (obj_type != fileswitch_IS_FILE)
+ continue;
+ raw_data = malloc(file_size);
+ if (!raw_data) {
+ LOG("malloc() failed");
+ ro_warn_user("NoMemory", 0);
+ continue;
+ }
+ error = xosfile_load_stamped_no_path(descriptor->filename,
+ (byte *)raw_data, 0, 0, 0, 0, 0);
+ if (error) {
+ free(raw_data);
+ LOG("xosfile_load_stamped_no_path: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("FileError", error->errmess);
+ continue;
+ }
+
+ /* decompress the new data */
+ error = xsquash_decompress_return_sizes(-1, &workspace_size, 0);
+ if (error) {
+ free(raw_data);
+ LOG("xsquash_decompress_return_sizes: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("MiscError", error->errmess);
+ continue;
+ }
+ decompressed = (osspriteop_area *)malloc(
+ descriptor->decompressed_size);
+ workspace = malloc(workspace_size);
+ if ((!decompressed) || (!workspace)) {
+ free(decompressed);
+ free(raw_data);
+ LOG("malloc() failed");
+ ro_warn_user("NoMemory", 0);
+ continue;
+ }
+ error = xsquash_decompress(squash_INPUT_ALL_PRESENT, workspace,
+ (byte *)(raw_data + sizeof(
+ struct theme_file_header)),
+ descriptor->compressed_size,
+ (byte *)decompressed,
+ descriptor->decompressed_size,
+ &status, 0, 0, 0, 0);
+ free(workspace);
+ free(raw_data);
+ if (error) {
+ free(decompressed);
+ LOG("xsquash_decompress: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("MiscError", error->errmess);
+ continue;
+ }
+ if (status != 0) {
+ free(decompressed);
+ continue;
+ }
+ descriptor->theme->sprite_area = decompressed;
+
+ /* find the highest sprite called 'throbber%i', and get the
+ * maximum dimensions for all 'thobber%i' icons. */
+ for (i = 1; i <= descriptor->theme->sprite_area->sprite_count;
+ i++) {
+ error = xosspriteop_return_name(osspriteop_USER_AREA,
+ descriptor->theme->sprite_area,
+ sprite_name, 16, i, 0);
+ if (error) {
+ LOG("xosspriteop_return_name: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("MiscError", error->errmess);
+ continue;
+ }
+ if (strncmp(sprite_name, "throbber", 8))
+ continue;
+
+ /* get the max sprite width/height */
+ error = xosspriteop_read_sprite_info(
+ osspriteop_USER_AREA,
+ descriptor->theme->sprite_area,
+ (osspriteop_id) name,
+ &dimensions.x, &dimensions.y,
+ (osbool *) 0, &mode);
+ if (error) {
+ LOG("xosspriteop_read_sprite_info: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("MiscError", error->errmess);
+ continue;
+ }
+ ro_convert_pixels_to_os_units(&dimensions, mode);
+ if (descriptor->theme->throbber_width < dimensions.x)
+ descriptor->theme->throbber_width =
+ dimensions.x;
+ if (descriptor->theme->throbber_height < dimensions.y)
+ descriptor->theme->throbber_height =
+ dimensions.y;
+
+ /* get the throbber number */
+ n = atoi(sprite_name + 8);
+ if (descriptor->theme->throbber_frames < n)
+ descriptor->theme->throbber_frames = n;
+ }
+ }
+ return result;
+}
+
+
+/**
+ * Applies the theme to all current windows and subsequent ones.
+ *
+ * \param descriptor the theme_descriptor to open
+ * \return whether the operation was successful
+ */
+bool ro_gui_theme_apply(struct theme_descriptor *descriptor)
+{
+ struct theme_descriptor *theme_previous;
+
+ /* check if the theme is already applied */
+ if (descriptor == theme_current)
+ return true;
+
+ /* re-open the new-theme and release the current theme */
+ if (!ro_gui_theme_open(descriptor, false))
+ return false;
+ theme_previous = theme_current;
+ theme_current = descriptor;
+
+ /* apply the theme to all the current toolbar-ed windows */
+ ro_toolbar_theme_update();
+
+ ro_gui_theme_close(theme_previous, false);
+ return true;
+}
+
+
+/**
+ * Closes a theme after use.
+ *
+ * \param descriptor the theme_descriptor to close
+ * \param list whether to open all themes in the list
+ * \return whether the operation was successful
+ */
+void ro_gui_theme_close(struct theme_descriptor *descriptor, bool list)
+{
+
+ if (!descriptor)
+ return;
+
+ /* move to the start of the list */
+ while (list && descriptor->previous)
+ descriptor = descriptor->previous;
+
+ /* close the themes */
+ while (descriptor) {
+ if (descriptor->theme) {
+ descriptor->theme->users = descriptor->theme->users - 1;
+ if (descriptor->theme->users <= 0) {
+ free(descriptor->theme->sprite_area);
+ free(descriptor->theme);
+ descriptor->theme = NULL;
+ }
+ }
+ if (!list)
+ return;
+ descriptor = descriptor->next;
+ }
+}
+
+
+/**
+ * Frees any unused theme descriptors.
+ *
+ * \param descriptor the theme_descriptor to free
+ */
+void ro_gui_theme_free(struct theme_descriptor *descriptor)
+{
+ struct theme_descriptor *next_descriptor;
+
+ if (!descriptor)
+ return;
+
+ /* move to the start of the list */
+ while (descriptor->previous)
+ descriptor = descriptor->previous;
+
+ /* free closed themes */
+ for (; descriptor; descriptor = next_descriptor) {
+ next_descriptor = descriptor->next;
+
+ /* no theme? no descriptor */
+ if (!descriptor->theme) {
+ if (descriptor->previous)
+ descriptor->previous->next = descriptor->next;
+ if (descriptor->next)
+ descriptor->next->previous =
+ descriptor->previous;
+
+ /* keep the cached list in sync */
+ if (theme_descriptors == descriptor)
+ theme_descriptors = next_descriptor;
+
+ /* release any memory */
+ free(descriptor->filename);
+ free(descriptor);
+ }
+ }
+}
+
+
diff --git a/frontends/riscos/theme.h b/frontends/riscos/theme.h
new file mode 100644
index 000000000..4a4ba1cb2
--- /dev/null
+++ b/frontends/riscos/theme.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2005 Richard Wilson <info@tinct.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Window themes(interface).
+ */
+
+#include <stdbool.h>
+#include "oslib/osspriteop.h"
+
+#ifndef _NETSURF_RISCOS_THEME_H_
+#define _NETSURF_RISCOS_THEME_H_
+
+/** Theme styles, collecting groups of attributes for different locations. */
+
+typedef enum {
+ THEME_STYLE_NONE = 0,
+ THEME_STYLE_BROWSER_TOOLBAR,
+ THEME_STYLE_HOTLIST_TOOLBAR,
+ THEME_STYLE_COOKIES_TOOLBAR,
+ THEME_STYLE_GLOBAL_HISTORY_TOOLBAR,
+ THEME_STYLE_STATUS_BAR
+} theme_style;
+
+/** Theme elements, which belong to styles. */
+
+typedef enum {
+ THEME_ELEMENT_FOREGROUND,
+ THEME_ELEMENT_BACKGROUND
+} theme_element;
+
+struct theme_file_header {
+ unsigned int magic_value;
+ unsigned int parser_version;
+ char name[32];
+ char author[64];
+ char browser_bg;
+ char hotlist_bg;
+ char status_bg;
+ char status_fg;
+ char theme_flags;
+ char future_expansion_1;
+ char future_expansion_2;
+ char future_expansion_3;
+ unsigned int compressed_sprite_size;
+ unsigned int decompressed_sprite_size;
+};
+
+struct theme {
+ osspriteop_area *sprite_area; /**< sprite area for theme */
+ int throbber_width; /**< width of the throbber */
+ int throbber_height; /**< height of the throbber */
+ int throbber_frames; /**< frames of animation for the throbber */
+ int users; /**< number of users for the theme */
+};
+
+struct theme_descriptor {
+ char *leafname; /**< theme leafname */
+ char *filename; /**< theme filename */
+ char name[32]; /**< theme name */
+ char author[64]; /**< theme author */
+ int browser_background; /**< background colour of browser toolbar */
+ int hotlist_background; /**< background colour of hotlist toolbar */
+ int status_background; /**< background colour of status window */
+ int status_foreground; /**< colour of status window text */
+ bool throbber_right; /**< throbber is on the right (left otherwise) */
+ bool throbber_redraw; /**< throbber requires forcible updating */
+ unsigned int decompressed_size; /**< decompressed sprite size */
+ unsigned int compressed_size; /**< compressed sprite size */
+ struct theme *theme; /**< corresponding theme (must be opened) */
+ struct theme_descriptor *previous; /**< previous descriptor in the list */
+ struct theme_descriptor *next; /**< next descriptor in the list */
+};
+
+void ro_gui_theme_initialise(void);
+void ro_gui_theme_finalise(void);
+struct theme_descriptor *ro_gui_theme_find(const char *leafname);
+struct theme_descriptor *ro_gui_theme_get_available(void);
+struct theme_descriptor *ro_gui_theme_get_current(void);
+osspriteop_area *ro_gui_theme_get_sprites(struct theme_descriptor *descriptor);
+int ro_gui_theme_get_style_element(struct theme_descriptor *descriptor,
+ theme_style style, theme_element element);
+bool ro_gui_theme_get_throbber_data(struct theme_descriptor *descriptor,
+ int *frames, int *width, int *height,
+ bool *right, bool *redraw);
+
+bool ro_gui_theme_read_file_header(struct theme_descriptor *descriptor,
+ struct theme_file_header *file_header);
+
+bool ro_gui_theme_open(struct theme_descriptor *descriptor, bool list);
+bool ro_gui_theme_apply(struct theme_descriptor *descriptor);
+void ro_gui_theme_close(struct theme_descriptor *descriptor, bool list);
+#endif
+
diff --git a/frontends/riscos/theme_install.c b/frontends/riscos/theme_install.c
new file mode 100644
index 000000000..5c11ffb83
--- /dev/null
+++ b/frontends/riscos/theme_install.c
@@ -0,0 +1,237 @@
+/*
+ * Copyright 2005 James Bursa <bursa@users.sourceforge.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Theme auto-installing.
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <oslib/osfile.h>
+#include <oslib/wimp.h>
+
+#include "utils/nsoption.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "content/content.h"
+#include "content/hlcache.h"
+#include "desktop/browser.h"
+#include "desktop/theme.h"
+
+#include "riscos/dialog.h"
+#include "riscos/gui.h"
+#include "riscos/theme.h"
+#include "riscos/wimp.h"
+#include "riscos/wimp_event.h"
+
+
+static hlcache_handle *theme_install_content = NULL;
+static struct theme_descriptor theme_install_descriptor;
+wimp_w dialog_theme_install;
+
+
+static void theme_install_close(wimp_w w);
+static nserror theme_install_callback(hlcache_handle *handle,
+ const hlcache_event *event, void *pw);
+static bool theme_install_read(const char *source_data,
+ unsigned long source_size);
+
+
+/**
+ * Handle a CONTENT_THEME that has started loading.
+ */
+
+void theme_install_start(hlcache_handle *c)
+{
+ assert(c != NULL);
+ assert(content_get_type(c) == CONTENT_THEME);
+
+ if (ro_gui_dialog_open_top(dialog_theme_install, NULL, 0, 0)) {
+ ro_warn_user("ThemeInstActive", 0);
+ return;
+ }
+
+ /* stop theme sitting in memory cache */
+ content_invalidate_reuse_data(c);
+
+ hlcache_handle_replace_callback(c, theme_install_callback, NULL);
+
+ ro_gui_set_icon_string(dialog_theme_install, ICON_THEME_INSTALL_MESSAGE,
+ messages_get("ThemeInstDown"), true);
+ ro_gui_set_icon_shaded_state(dialog_theme_install,
+ ICON_THEME_INSTALL_INSTALL, true);
+ ro_gui_wimp_event_register_close_window(dialog_theme_install,
+ theme_install_close);
+}
+
+
+/**
+ * Callback for fetchcache() for theme install fetches.
+ */
+
+nserror theme_install_callback(hlcache_handle *handle,
+ const hlcache_event *event, void *pw)
+{
+ switch (event->type) {
+
+ case CONTENT_MSG_DONE:
+ {
+ const char *source_data;
+ unsigned long source_size;
+ int author_indent = 0;
+ char buffer[256];
+
+ theme_install_content = handle;
+
+ source_data = content_get_source_data(handle, &source_size);
+
+ if (!theme_install_read(source_data, source_size)) {
+ ro_warn_user("ThemeInvalid", 0);
+ theme_install_close(dialog_theme_install);
+ break;
+ }
+
+ /* remove '© ' from the start of the data */
+ if (theme_install_descriptor.author[0] == '©')
+ author_indent++;
+ while (theme_install_descriptor.author[author_indent] == ' ')
+ author_indent++;
+ snprintf(buffer, sizeof buffer, messages_get("ThemeInstall"),
+ theme_install_descriptor.name,
+ &theme_install_descriptor.author[author_indent]);
+ buffer[sizeof buffer - 1] = '\0';
+ ro_gui_set_icon_string(dialog_theme_install,
+ ICON_THEME_INSTALL_MESSAGE,
+ buffer, true);
+ ro_gui_set_icon_shaded_state(dialog_theme_install,
+ ICON_THEME_INSTALL_INSTALL, false);
+ }
+ break;
+
+ case CONTENT_MSG_ERROR:
+ theme_install_close(dialog_theme_install);
+ ro_warn_user(event->data.error, 0);
+ break;
+
+ default:
+ break;
+ }
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * Fill in theme_install_descriptor from received theme data.
+ *
+ * \param source_data received data
+ * \param source_size size of data
+ * \return true if data is a correct theme, false on error
+ *
+ * If the data is a correct theme, theme_install_descriptor is filled in.
+ */
+
+bool theme_install_read(const char *source_data, unsigned long source_size)
+{
+ const void *data = source_data;
+
+ if (source_size < sizeof(struct theme_file_header))
+ return false;
+ if (!ro_gui_theme_read_file_header(&theme_install_descriptor,
+ (struct theme_file_header *) data))
+ return false;
+ if (source_size - sizeof(struct theme_file_header) !=
+ theme_install_descriptor.compressed_size)
+ return false;
+ return true;
+}
+
+
+/**
+ * Install the downloaded theme.
+ *
+ * \param w the theme install window handle
+ */
+
+bool ro_gui_theme_install_apply(wimp_w w)
+{
+ char theme_save[256];
+ char *theme_file;
+ struct theme_descriptor *theme_install;
+ os_error *error;
+ char *fix;
+ const char *source_data;
+ unsigned long source_size;
+
+ assert(theme_install_content);
+
+ /* convert spaces to hard spaces */
+ theme_file = strdup(theme_install_descriptor.name);
+ if (!theme_file) {
+ LOG("malloc failed");
+ ro_warn_user("NoMemory", 0);
+ return false;
+ }
+ for (fix = theme_file; *fix != '\0'; fix++)
+ if (*fix == ' ')
+ *fix = 160; /* hard space */
+
+ /* simply overwrite previous theme versions */
+ snprintf(theme_save, sizeof theme_save, "%s.%s",
+ nsoption_charp(theme_save), theme_file);
+
+ theme_save[sizeof theme_save - 1] = '\0';
+
+ source_data = content_get_source_data(theme_install_content,
+ &source_size);
+
+ error = xosfile_save_stamped(theme_save, 0xffd,
+ (byte *) source_data,
+ (byte *) source_data + source_size);
+ if (error) {
+ LOG("xosfile_save_stamped: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("ThemeInstallErr", 0);
+ free(theme_file);
+ return false;
+ }
+
+ /* apply the new theme */
+ ro_gui_theme_get_available();
+ theme_install = ro_gui_theme_find(theme_file);
+ if (!theme_install || !ro_gui_theme_apply(theme_install)) {
+ ro_warn_user("ThemeApplyErr", 0);
+ } else {
+ nsoption_set_charp(theme, strdup(theme_install->leafname));
+ }
+ free(theme_file);
+ ro_gui_save_options();
+ return true;
+}
+
+
+/**
+ * Close the theme installer and free resources.
+ */
+
+void theme_install_close(wimp_w w)
+{
+ if (theme_install_content)
+ hlcache_handle_release(theme_install_content);
+
+ theme_install_content = NULL;
+}
diff --git a/frontends/riscos/tinct.h b/frontends/riscos/tinct.h
new file mode 100644
index 000000000..e02dcdece
--- /dev/null
+++ b/frontends/riscos/tinct.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2005 Richard Wilson <info@tinct.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Complete details on using Tinct are available from http://www.tinct.net.
+ */
+
+/** \file
+ * Tinct SWI numbers and flags for version 0.11
+ */
+
+#ifndef _NETSURF_RISCOS_TINCT_H_
+#define _NETSURF_RISCOS_TINCT_H_
+
+
+/**
+ * Plots an alpha-blended sprite at the specified coordinates.
+ *
+ * -> R2 Sprite pointer
+ * R3 X coordinate
+ * R4 Y coordinate
+ * R7 Flag word
+*/
+#define Tinct_PlotAlpha 0x57240
+
+
+/**
+ * Plots a scaled alpha-blended sprite at the specified coordinates.
+ *
+ * -> R2 Sprite pointer
+ * R3 X coordinate
+ * R4 Y coordinate
+ * R5 Scaled sprite width
+ * R6 Scaled sprite height
+ * R7 Flag word
+ */
+#define Tinct_PlotScaledAlpha 0x57241
+
+
+/**
+ * Plots a sprite at the specified coordinates with a constant 0xff value for
+ * the alpha channel, ie without a mask.
+ *
+ * -> R2 Sprite pointer
+ * R3 X coordinate
+ * R4 Y coordinate
+ * R7 Flag word
+ */
+#define Tinct_Plot 0x57242
+
+/**
+ * Plots a scaled sprite at the specified coordinates with a constant 0xff value
+ * for the alpha channel, ie without a mask.
+ *
+ * -> R2 Sprite pointer
+ * R3 X coordinate
+ * R4 Y coordinate
+ * R5 Scaled sprite width
+ * R6 Scaled sprite height
+ * R7 Flag word
+ */
+#define Tinct_PlotScaled 0x57243
+
+
+/**
+ * Converts a paletted sprite into its 32bpp equivalent. Sufficient memory must
+ * have previously been allocated for the sprite (44 + width * height * 4).
+ * As sprites with 16bpp or 32bpp do not have palettes, conversion cannot be
+ * performed on these variants. All sprites must be supplied with a full palette,
+ * eg 8bpp must have 256 palette entries.
+ *
+ * -> R2 Source sprite pointer
+ * R3 Destination sprite pointer
+ */
+#define Tinct_ConvertSprite 0x57244
+
+
+/**
+ * Returns the features available to the caller by specifying bits in the flag
+ * word. The features available are unique for each mode, although the current
+ * version of Tinct supports the same subset of features for all modes.
+ *
+ * -> R0 Feature to test for, or 0 for all features
+ * <- R0 Features available
+ */
+#define Tinct_AvailableFeatures 0x57245
+
+
+/**
+ * Compresses an image using a fast algorithm. Sufficient memory must have been
+ * previously allocated for the maximum possible compressed size. This value is
+ * equal to 28 + (width * height * 4) * 33 / 32.
+ *
+ * -> R0 Source sprite pointer
+ * R2 Output data buffer
+ * R3 Output bytes available
+ * R7 Flag word (currently 0)
+ * <- R0 Size of compressed data
+ */
+#define Tinct_Compress 0x57246
+
+
+/**
+ * Decompresses an image previously compressed. Sufficient memory must have been
+ * previously allocated for the decompressed data (44 + width * height * 4) where
+ * width and height are available at +0 and +4 of the compressed data respectively.
+ *
+ * -> R0 Input data buffer
+ * R2 Output data buffer
+ * R7 Flag word (currently 0)
+ * <- R0 Size of decompressed data
+ */
+#define Tinct_Decompress 0x57247
+
+
+/* Plotting flags
+*/
+#define tinct_READ_SCREEN_BASE 0x01 /** <-- Use when hardware scrolling */
+#define tinct_BILINEAR_FILTER 0x02 /** <-- Perform bi-linear filtering */
+#define tinct_DITHER 0x04 /** <-- Perform dithering */
+#define tinct_ERROR_DIFFUSE 0x08 /** <-- Perform error diffusion */
+#define tinct_DITHER_INVERTED 0x0C /** <-- Perform dithering with inverted pattern */
+#define tinct_FILL_HORIZONTALLY 0x10 /** <-- Horizontally fill clipping region with image */
+#define tinct_FILL_VERTICALLY 0x20 /** <-- Vertically fill clipping region with image */
+#define tinct_FORCE_PALETTE_READ 0x40 /** <-- Use after a palette change when out of the desktop */
+#define tinct_USE_OS_SPRITE_OP 0x80 /** <-- Use when printing */
+
+/* Compression flags
+*/
+#define tinct_OPAQUE_IMAGE 0x01 /** <-- Image is opaque, compress further */
+
+/* Shifts
+*/
+#define tinct_BACKGROUND_SHIFT 0x08
+
+/* Sprite mode
+*/
+#define tinct_SPRITE_MODE (os_mode)0x301680b5
+#endif
diff --git a/frontends/riscos/toolbar.c b/frontends/riscos/toolbar.c
new file mode 100644
index 000000000..83751a7b4
--- /dev/null
+++ b/frontends/riscos/toolbar.c
@@ -0,0 +1,1788 @@
+/*
+ * Copyright 2004, 2005 Richard Wilson <info@tinct.net>
+ * Copyright 2010, 2011 Stephen Fryatt <stevef@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Window toolbars (implementation).
+ */
+
+#include <alloca.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+#include "oslib/dragasprite.h"
+#include "oslib/os.h"
+#include "oslib/osgbpb.h"
+#include "oslib/osfile.h"
+#include "oslib/osfind.h"
+#include "oslib/osspriteop.h"
+#include "oslib/wimpspriteop.h"
+#include "oslib/squash.h"
+#include "oslib/wimp.h"
+#include "oslib/wimpextend.h"
+#include "oslib/wimpspriteop.h"
+
+#include "utils/log.h"
+#include "utils/nsoption.h"
+#include "content/content.h"
+#include "desktop/plotters.h"
+
+#include "riscos/cookies.h"
+#include "riscos/dialog.h"
+#include "riscos/global_history.h"
+#include "riscos/gui.h"
+#include "riscos/gui/button_bar.h"
+#include "riscos/gui/throbber.h"
+#include "riscos/gui/url_bar.h"
+#include "riscos/hotlist.h"
+#include "riscos/menus.h"
+#include "riscos/save.h"
+#include "riscos/theme.h"
+#include "riscos/toolbar.h"
+#include "riscos/treeview.h"
+#include "riscos/url_complete.h"
+#include "riscos/wimp.h"
+#include "riscos/wimp_event.h"
+#include "riscos/wimputils.h"
+#include "riscos/window.h"
+
+
+#define TOOLBAR_WIDGET_GUTTER 8
+#define TOOLBAR_DEFAULT_WIDTH 16384
+
+/* Toolbar rows used to index into the arrays of row-specific data.
+ */
+
+#define TOOLBAR_ROW_TOP 0
+#define TOOLBAR_ROW_DIV1 1
+#define TOOLBAR_ROW_EDIT 2
+#define TOOLBAR_MAX_ROWS 3
+
+/* The toolbar data structure.
+ */
+
+struct toolbar {
+ /** Bar details. */
+ struct theme_descriptor *theme;
+ theme_style style;
+ toolbar_flags flags;
+
+ int current_width, current_height;
+ int full_width, full_height;
+ int clip_width, clip_height;
+
+ /** Toolbar and parent window handles. */
+ wimp_w toolbar_handle;
+ wimp_w parent_handle;
+
+ /** Row locations and sizes. */
+ int row_y0[TOOLBAR_MAX_ROWS];
+ int row_y1[TOOLBAR_MAX_ROWS];
+
+ /** Details for the button bar. */
+ struct button_bar *buttons;
+ bool buttons_display;
+ os_coord buttons_size;
+
+ /** Details for the URL bar. */
+ struct url_bar *url;
+ bool url_display;
+ os_coord url_size;
+
+ /** Details for the throbber. */
+ struct throbber *throbber;
+ bool throbber_display;
+ bool throbber_right;
+ os_coord throbber_size;
+
+ /** Client callback data. */
+ const struct toolbar_callbacks *callbacks;
+ void *client_data;
+
+ /** Details for the toolbar editor. */
+ wimp_i editor_div1;
+ struct button_bar *editor;
+ os_coord editor_size;
+
+ bool editing;
+
+ /** Interactive help data. */
+
+ const char *help_prefix;
+
+ /** The next bar in the toolbar list. */
+ struct toolbar *next;
+};
+
+
+/* Global variables for the toolbar module.
+ */
+
+/** The list of defined toolbars. */
+static struct toolbar *ro_toolbar_bars = NULL;
+
+/** The Toolber Menu */
+wimp_menu *toolbar_menu;
+
+
+/* A basic window definition for the toolbar and status bar.
+ */
+
+static wimp_window ro_toolbar_window = {
+ {0, 0, 1, 1},
+ 0,
+ 0,
+ wimp_TOP,
+ wimp_WINDOW_NEW_FORMAT | wimp_WINDOW_MOVEABLE | wimp_WINDOW_NO_BOUNDS |
+ wimp_WINDOW_FURNITURE_WINDOW |
+ wimp_WINDOW_IGNORE_XEXTENT | wimp_WINDOW_IGNORE_YEXTENT,
+ wimp_COLOUR_BLACK,
+ wimp_COLOUR_LIGHT_GREY,
+ wimp_COLOUR_LIGHT_GREY,
+ wimp_COLOUR_VERY_LIGHT_GREY,
+ wimp_COLOUR_DARK_GREY,
+ wimp_COLOUR_MID_LIGHT_GREY,
+ wimp_COLOUR_CREAM,
+ wimp_WINDOW_NEVER3D | 0x16u /* RISC OS 5.03+ */,
+ {0, 0, TOOLBAR_DEFAULT_WIDTH, 16384},
+ 0,
+ wimp_BUTTON_DOUBLE_CLICK_DRAG << wimp_ICON_BUTTON_TYPE_SHIFT,
+ wimpspriteop_AREA,
+ 1,
+ 1,
+ {""},
+ 0,
+ { }
+};
+
+static char ro_toolbar_null_string[] = "";
+static char ro_toolbar_line_validation[] = "R2";
+
+/*
+ * Private function prototypes.
+ */
+
+static void ro_toolbar_update_current_widgets(struct toolbar *toolbar);
+static void ro_toolbar_refresh_widget_dimensions(struct toolbar *toolbar);
+static void ro_toolbar_reformat_widgets(struct toolbar *toolbar);
+
+static void ro_toolbar_redraw(wimp_draw *redraw);
+static bool ro_toolbar_click(wimp_pointer *pointer);
+static bool ro_toolbar_keypress(wimp_key *key);
+static bool ro_toolbar_menu_prepare(wimp_w w, wimp_i i, wimp_menu *menu,
+ wimp_pointer *pointer);
+static void ro_toolbar_menu_warning(wimp_w w, wimp_i i, wimp_menu *menu,
+ wimp_selection *selection, menu_action action);
+static bool ro_toolbar_menu_select(wimp_w w, wimp_i i, wimp_menu *menu,
+ wimp_selection *selection, menu_action action);
+static const char *ro_toolbar_get_help_suffix(wimp_w w, wimp_i i, os_coord *pos,
+ wimp_mouse_state buttons);
+
+static void ro_toolbar_update_buttons(struct toolbar *toolbar);
+
+
+/* This is an exported interface documented in toolbar.h */
+
+void ro_toolbar_init(void)
+{
+ /* browser toolbar menu */
+ static const struct ns_menu toolbar_definition = {
+ "Toolbar", {
+ { "Toolbars", NO_ACTION, 0 },
+ { "Toolbars.ToolButtons", TOOLBAR_BUTTONS, 0 },
+ { "Toolbars.ToolAddress", TOOLBAR_ADDRESS_BAR, 0 },
+ { "Toolbars.ToolThrob", TOOLBAR_THROBBER, 0 },
+ { "EditToolbar", TOOLBAR_EDIT, 0 },
+ {NULL, 0, 0}
+ }
+ };
+ toolbar_menu = ro_gui_menu_define_menu(
+ &toolbar_definition);
+}
+
+
+/* This is an exported interface documented in toolbar.h */
+
+struct toolbar *ro_toolbar_create(struct theme_descriptor *descriptor,
+ wimp_w parent, theme_style style, toolbar_flags bar_flags,
+ const struct toolbar_callbacks *callbacks, void *client_data,
+ const char *help)
+{
+ struct toolbar *toolbar;
+
+ /* Allocate memory for the bar and link it into the list of bars. */
+
+ toolbar = calloc(sizeof(struct toolbar), 1);
+ if (toolbar == NULL) {
+ LOG("No memory for malloc()");
+ ro_warn_user("NoMemory", 0);
+ return NULL;
+ }
+
+ toolbar->next = ro_toolbar_bars;
+ ro_toolbar_bars = toolbar;
+
+ /* Store the supplied settings. */
+
+ toolbar->flags = bar_flags;
+ toolbar->theme = descriptor;
+ toolbar->style = style;
+ toolbar->parent_handle = parent;
+ toolbar->callbacks = callbacks;
+ toolbar->client_data = client_data;
+
+ /* Set up the internal widgets: initially, there are none. */
+
+ toolbar->buttons = NULL;
+ toolbar->buttons_display = false;
+
+ toolbar->url = NULL;
+ toolbar->url_display = false;
+
+ toolbar->throbber = NULL;
+ toolbar->throbber_display = false;
+
+ /* Set up the bar editor. */
+
+ toolbar->editor = NULL;
+ toolbar->editor_div1 = -1;
+
+ toolbar->editing = false;
+
+ toolbar->help_prefix = help;
+
+ return toolbar;
+}
+
+
+/* This is an exported interface documented in toolbar.h */
+
+bool ro_toolbar_add_buttons(struct toolbar *toolbar,
+ const struct button_bar_buttons buttons[], char *button_order)
+{
+ if (toolbar == NULL)
+ return false;
+
+ if (toolbar->buttons != NULL)
+ return false;
+
+ toolbar->buttons = ro_gui_button_bar_create(toolbar->theme, buttons);
+ if (toolbar->buttons != NULL) {
+ toolbar->buttons_display = true;
+ ro_gui_button_bar_arrange_buttons(toolbar->buttons,
+ button_order);
+ }
+
+ toolbar->editor = ro_gui_button_bar_create(toolbar->theme, buttons);
+ if (toolbar->editor != NULL)
+ ro_gui_button_bar_hide(toolbar->editor, !toolbar->editing);
+
+ if (toolbar->buttons != NULL && toolbar->editor != NULL)
+ if (!ro_gui_button_bar_link_editor(toolbar->buttons,
+ toolbar->editor,
+ (void (*)(void *))
+ ro_toolbar_update_current_widgets,
+ toolbar))
+ return false;
+
+ return (toolbar->buttons == NULL || toolbar->editor == NULL) ?
+ false : true;
+}
+
+
+/* This is an exported interface documented in toolbar.h */
+
+bool ro_toolbar_add_throbber(struct toolbar *toolbar)
+{
+ if (toolbar == NULL)
+ return false;
+
+ if (toolbar->throbber != NULL)
+ return false;
+
+ toolbar->throbber = ro_gui_throbber_create(toolbar->theme);
+
+ if (toolbar->throbber != NULL)
+ toolbar->throbber_display = true;
+
+ return (toolbar->throbber == NULL) ? false : true;
+}
+
+
+/* This is an exported interface documented in toolbar.h */
+
+bool ro_toolbar_add_url(struct toolbar *toolbar)
+{
+ if (toolbar == NULL)
+ return false;
+
+ if (toolbar->url != NULL)
+ return false;
+
+ toolbar->url = ro_gui_url_bar_create(toolbar->theme);
+
+ if (toolbar->url != NULL)
+ toolbar->url_display = true;
+
+ return (toolbar->url == NULL) ? false : true;
+}
+
+
+/* This is an exported interface documented in toolbar.h */
+
+bool ro_toolbar_rebuild(struct toolbar *toolbar)
+{
+ os_error *error;
+ wimp_icon_create icon;
+ wimp_w old_window = NULL;
+
+ if (toolbar == NULL)
+ return false;
+
+ /* Start to set up the toolbar window. */
+
+ ro_toolbar_window.sprite_area =
+ ro_gui_theme_get_sprites(toolbar->theme);
+ ro_toolbar_window.work_bg =
+ ro_gui_theme_get_style_element(toolbar->theme,
+ toolbar->style, THEME_ELEMENT_BACKGROUND);
+
+ /* Delete any existing toolbar window... */
+
+ if (toolbar->toolbar_handle != NULL) {
+ old_window = toolbar->toolbar_handle;
+ error = xwimp_delete_window(toolbar->toolbar_handle);
+ if (error)
+ LOG("xwimp_delete_window: 0x%x: %s", error->errnum, error->errmess);
+ toolbar->toolbar_handle = NULL;
+ }
+
+ /* ...and create a new window. */
+
+ error = xwimp_create_window(&ro_toolbar_window,
+ &toolbar->toolbar_handle);
+ if (error) {
+ LOG("xwimp_create_window: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return false;
+ }
+
+ /* Set up the toolbar's event handlers. Only set the user activity-
+ * related callbacks if the bar isn't for display purposes. If the
+ * toolbar is being recreated, simply transfer the handlers across
+ * from the old, now-deleted window.
+ */
+
+ if (old_window == NULL) {
+ ro_gui_wimp_event_register_redraw_window(
+ toolbar->toolbar_handle, ro_toolbar_redraw);
+ ro_gui_wimp_event_set_user_data(toolbar->toolbar_handle,
+ toolbar);
+
+ if (!(toolbar->flags & TOOLBAR_FLAGS_DISPLAY)) {
+ ro_gui_wimp_event_register_mouse_click(
+ toolbar->toolbar_handle,
+ ro_toolbar_click);
+ ro_gui_wimp_event_register_keypress(
+ toolbar->toolbar_handle,
+ ro_toolbar_keypress);
+ ro_gui_wimp_event_register_menu_prepare(
+ toolbar->toolbar_handle,
+ ro_toolbar_menu_prepare);
+ ro_gui_wimp_event_register_menu_warning(
+ toolbar->toolbar_handle,
+ ro_toolbar_menu_warning);
+ ro_gui_wimp_event_register_menu_selection(
+ toolbar->toolbar_handle,
+ ro_toolbar_menu_select);
+ ro_gui_wimp_event_register_menu(toolbar->toolbar_handle,
+ toolbar_menu, true, false);
+ ro_gui_wimp_event_register_help_suffix(
+ toolbar->toolbar_handle,
+ ro_toolbar_get_help_suffix);
+ }
+ } else {
+ ro_gui_wimp_event_transfer(old_window, toolbar->toolbar_handle);
+ }
+
+ /* The help prefix changes from edit to non-edit more. */
+
+ ro_gui_wimp_event_set_help_prefix(toolbar->toolbar_handle,
+ (toolbar->editing) ?
+ "HelpEditToolbar" : toolbar->help_prefix);
+
+ /* Place the widgets into the new bar, using the new theme.
+ *
+ * \TODO -- If any widgets fail to rebuild, then we currently just
+ * carry on without them. Not sure if the whole bar
+ * rebuild should fail here?
+ */
+
+ if (toolbar->throbber != NULL) {
+ if (!ro_gui_throbber_rebuild(toolbar->throbber, toolbar->theme,
+ toolbar->style, toolbar->toolbar_handle,
+ toolbar->editing)) {
+ ro_gui_throbber_destroy(toolbar->throbber);
+ toolbar->throbber = NULL;
+ }
+
+ ro_gui_theme_get_throbber_data(toolbar->theme, NULL, NULL, NULL,
+ &toolbar->throbber_right, NULL);
+ }
+
+ if (toolbar->buttons != NULL) {
+ if (!ro_gui_button_bar_rebuild(toolbar->buttons, toolbar->theme,
+ toolbar->style, toolbar->toolbar_handle,
+ toolbar->editing)) {
+ ro_gui_button_bar_destroy(toolbar->buttons);
+ toolbar->buttons = NULL;
+ }
+ }
+
+ if (toolbar->editor != NULL) {
+ if (!ro_gui_button_bar_rebuild(toolbar->editor, toolbar->theme,
+ toolbar->style, toolbar->toolbar_handle,
+ toolbar->editing)) {
+ ro_gui_button_bar_destroy(toolbar->editor);
+ toolbar->editor = NULL;
+ }
+ }
+
+ if (toolbar->url != NULL) {
+ if (!ro_gui_url_bar_rebuild(toolbar->url, toolbar->theme,
+ toolbar->style, toolbar->toolbar_handle,
+ toolbar->flags & TOOLBAR_FLAGS_DISPLAY,
+ toolbar->editing)) {
+ ro_gui_url_bar_destroy(toolbar->url);
+ toolbar->url = NULL;
+ }
+ }
+
+ /* If this is an editor, add in a divider icon and the editor
+ * button bar.
+ */
+
+ if (toolbar->editing) {
+ icon.w = toolbar->toolbar_handle;
+ icon.icon.flags = wimp_ICON_TEXT | wimp_ICON_INDIRECTED |
+ wimp_ICON_VCENTRED | wimp_ICON_BORDER |
+ (wimp_COLOUR_BLACK <<
+ wimp_ICON_FG_COLOUR_SHIFT) |
+ (wimp_COLOUR_VERY_LIGHT_GREY <<
+ wimp_ICON_BG_COLOUR_SHIFT);
+ icon.icon.extent.x0 = 0;
+ icon.icon.extent.x1 = 0;
+ icon.icon.extent.y1 = 0;
+ icon.icon.extent.y0 = 0;
+ icon.icon.data.indirected_text.text = ro_toolbar_null_string;
+ icon.icon.data.indirected_text.validation =
+ ro_toolbar_line_validation;
+ icon.icon.data.indirected_text.size = 1;
+ error = xwimp_create_icon(&icon, &toolbar->editor_div1);
+ if (error) {
+ LOG("xwimp_create_icon: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ toolbar->editor_div1 = -1;
+ }
+ }
+
+ /* Establish the required dimensions to fit the widgets, then
+ * reflow the bar contents.
+ */
+
+ ro_toolbar_refresh_widget_dimensions(toolbar);
+
+ ro_toolbar_process(toolbar, -1, true);
+
+ if (toolbar->parent_handle != NULL)
+ ro_toolbar_attach(toolbar, toolbar->parent_handle);
+
+ ro_toolbar_update_buttons(toolbar);
+
+ return true;
+}
+
+
+/* This is an exported interface documented in toolbar.h */
+
+bool ro_toolbar_attach(struct toolbar *toolbar, wimp_w parent)
+{
+ wimp_outline outline;
+ wimp_window_state state;
+ os_error *error;
+
+ if (toolbar == NULL || toolbar->toolbar_handle == NULL)
+ return false;
+
+ toolbar->parent_handle = parent;
+
+ /* Only try to attach the toolbar if there's any of it visible to
+ * matter.
+ */
+
+ if (toolbar->current_height > 0) {
+ outline.w = parent;
+ xwimp_get_window_outline(&outline);
+ state.w = parent;
+ xwimp_get_window_state(&state);
+ state.w = toolbar->toolbar_handle;
+ state.visible.x1 = outline.outline.x1 - 2;
+ state.visible.y0 = state.visible.y1 + 2 -
+ toolbar->current_height;
+ state.xscroll = 0;
+ state.yscroll = 0;
+ error = xwimp_open_window_nested(PTR_WIMP_OPEN(&state), parent,
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_XORIGIN_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_TOP_OR_RIGHT
+ << wimp_CHILD_YORIGIN_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_LS_EDGE_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_TOP_OR_RIGHT
+ << wimp_CHILD_BS_EDGE_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_TOP_OR_RIGHT
+ << wimp_CHILD_RS_EDGE_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_TOP_OR_RIGHT
+ << wimp_CHILD_TS_EDGE_SHIFT);
+ if (error) {
+ LOG("xwimp_open_window_nested: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return false;
+ }
+
+ return true;
+ }
+
+ error = xwimp_close_window(toolbar->toolbar_handle);
+ if (error) {
+ LOG("xwimp_close_window: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return false;
+ }
+ return true;
+}
+
+
+/* This is an exported interface documented in toolbar.h */
+
+bool ro_toolbar_process(struct toolbar *toolbar, int width, bool reformat)
+{
+ os_error *error;
+ wimp_outline outline;
+ wimp_window_state state;
+ os_box extent;
+ int old_height, old_width;
+
+ if (!toolbar)
+ return false;
+
+ old_height = toolbar->current_height;
+ old_width = toolbar->current_width;
+
+ /* Measure the parent window width if the caller has asked us to
+ * calculate the clip width ourselves. Otherwise, if a clip width
+ * has been specified, set the clip to that.
+ */
+
+ if ((toolbar->parent_handle != NULL) && (width == -1)) {
+ outline.w = toolbar->parent_handle;
+ error = xwimp_get_window_outline(&outline);
+ if (error) {
+ LOG("xwimp_get_window_outline: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return false;
+ }
+
+ toolbar->clip_width = outline.outline.x1 -
+ outline.outline.x0 - 2;
+ toolbar->current_width = toolbar->clip_width;
+ } else if (width != -1) {
+ toolbar->clip_width = width;
+ toolbar->current_width = toolbar->clip_width;
+ }
+
+ /* Find the parent visible height to clip our toolbar height to
+ */
+
+ if (toolbar->parent_handle != NULL) {
+ state.w = toolbar->parent_handle;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return false;
+ }
+
+ toolbar->clip_height = state.visible.y1 - state.visible.y0 + 2;
+
+ /* We can't obscure the height of the scroll bar as we
+ * lose the resize icon if we do.
+ */
+
+ if (toolbar->clip_height >= toolbar->full_height)
+ toolbar->current_height = toolbar->full_height;
+ else
+ toolbar->current_height = toolbar->clip_height;
+
+ /* Resize the work area extent and update our position. */
+
+ if (old_height != toolbar->current_height) {
+ extent.x0 = 0;
+ extent.y0 = 0;
+ extent.x1 = TOOLBAR_DEFAULT_WIDTH;
+ extent.y1 = toolbar->current_height - 2;
+ error = xwimp_set_extent(toolbar->toolbar_handle,
+ &extent);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+
+ ro_toolbar_attach(toolbar, toolbar->parent_handle);
+ }
+ } else {
+ toolbar->clip_height = toolbar->full_height;
+ toolbar->current_height = toolbar->full_height;
+ }
+
+ /* Reflow the widgets into the toolbar if the dimensions have
+ * changed or we have been asked to anyway. */
+
+ if (toolbar->current_width != old_width || reformat)
+ ro_toolbar_reformat_widgets(toolbar);
+
+ return true;
+}
+
+
+/**
+ * Update the widgets currently on view in a toolbar. This can be used
+ * generally, but is primarily offered to widgets as a way for them
+ * to force an update.
+ *
+ * \param *toolbar The toolbar to update.
+ */
+
+void ro_toolbar_update_current_widgets(struct toolbar *toolbar)
+{
+ int old_height;
+
+ if (toolbar == NULL)
+ return;
+
+ old_height = toolbar->full_height;
+
+ ro_toolbar_refresh_widget_dimensions(toolbar);
+ ro_toolbar_reformat_widgets(toolbar);
+
+ /* If the toolbar height has changed, we need to tell the client. */
+
+ if (toolbar->full_height != old_height)
+ ro_toolbar_refresh(toolbar);
+}
+
+
+/**
+ * Get the minimum dimenstions required by the toolbar widgets after
+ * these have changed. The minimum dimensions are assumed not to change
+ * unless we change theme (ie. we rebuild the bar) or we knowingly
+ * alter a widget (eg. we add or remove button-bar buttons).
+ *
+ *
+ * \param *toolbar The toolbar to refresh.
+ */
+
+void ro_toolbar_refresh_widget_dimensions(struct toolbar *toolbar)
+{
+ int width, height;
+ int row_width, row_height;
+
+ if (toolbar == NULL)
+ return;
+
+ /* Process the toolbar editor and any associated divider rows.
+ */
+
+ if (toolbar->editor != NULL && toolbar->editing) {
+ width = 0;
+ height = 0;
+ ro_gui_button_bar_get_dims(toolbar->editor, &width, &height);
+
+ toolbar->editor_size.x = width;
+ toolbar->editor_size.y = height;
+
+ toolbar->row_y0[TOOLBAR_ROW_EDIT] = TOOLBAR_WIDGET_GUTTER;
+ toolbar->row_y1[TOOLBAR_ROW_EDIT] = TOOLBAR_WIDGET_GUTTER
+ + height;
+
+ toolbar->row_y0[TOOLBAR_ROW_DIV1] = TOOLBAR_WIDGET_GUTTER +
+ toolbar->row_y1[TOOLBAR_ROW_EDIT];
+ toolbar->row_y1[TOOLBAR_ROW_DIV1] = 8 +
+ toolbar->row_y0[TOOLBAR_ROW_DIV1];
+ } else {
+ toolbar->editor_size.x = 0;
+ toolbar->editor_size.y = 0;
+
+ toolbar->row_y0[TOOLBAR_ROW_EDIT] = 0;
+ toolbar->row_y1[TOOLBAR_ROW_EDIT] = 0;
+ toolbar->row_y0[TOOLBAR_ROW_DIV1] = 0;
+ toolbar->row_y1[TOOLBAR_ROW_DIV1] = 0;
+ }
+
+ /* Process the top row icons. */
+
+ row_width = 0;
+ row_height = 0;
+
+ /* If the editor is active, any button bar if forced into view. */
+
+ if (toolbar->buttons != NULL &&
+ (toolbar->buttons_display || toolbar->editing)) {
+ width = 0;
+ height = 0;
+ ro_gui_button_bar_get_dims(toolbar->buttons, &width, &height);
+
+ row_width += width;
+ toolbar->buttons_size.x = width;
+ toolbar->buttons_size.y = height;
+
+ if (height > row_height)
+ row_height = height;
+ } else {
+ toolbar->buttons_size.x = 0;
+ toolbar->buttons_size.y = 0;
+ }
+
+ if (toolbar->url != NULL && toolbar->url_display) {
+ width = 0;
+ height = 0;
+ ro_gui_url_bar_get_dims(toolbar->url, &width, &height);
+
+ if (row_width > 0)
+ row_width += TOOLBAR_WIDGET_GUTTER;
+ row_width += width;
+
+ toolbar->url_size.x = width;
+ toolbar->url_size.y = height;
+
+ if (height > row_height)
+ row_height = height;
+ } else {
+ toolbar->url_size.x = 0;
+ toolbar->url_size.y = 0;
+ }
+
+ if (toolbar->throbber != NULL && toolbar->throbber_display) {
+ width = 0;
+ height = 0;
+ ro_gui_throbber_get_dims(toolbar->throbber, &width, &height);
+
+ if (row_width > 0)
+ row_width += TOOLBAR_WIDGET_GUTTER;
+ row_width += width;
+
+ toolbar->throbber_size.x = width;
+ toolbar->throbber_size.y = height;
+
+ if (height > row_height)
+ row_height = height;
+ } else {
+ toolbar->throbber_size.x = 0;
+ toolbar->throbber_size.y = 0;
+ }
+
+ if (row_height > 0) {
+ toolbar->row_y0[TOOLBAR_ROW_TOP] = TOOLBAR_WIDGET_GUTTER +
+ toolbar->row_y1[TOOLBAR_ROW_DIV1];
+ toolbar->row_y1[TOOLBAR_ROW_TOP] = row_height +
+ toolbar->row_y0[TOOLBAR_ROW_TOP];
+ } else {
+ toolbar->row_y0[TOOLBAR_ROW_TOP] = 0;
+ toolbar->row_y1[TOOLBAR_ROW_TOP] = 0;
+ }
+
+ /* Establish the full dimensions of the bar.
+ *
+ * \TODO -- This currently assumes an "all or nothing" approach to
+ * the editor bar, and will need reworking once we have to
+ * worry about tab bars.
+ */
+
+ if (toolbar->row_y1[TOOLBAR_ROW_TOP] > 0) {
+ toolbar->full_height = toolbar->row_y1[TOOLBAR_ROW_TOP] +
+ TOOLBAR_WIDGET_GUTTER;
+ } else {
+ toolbar->full_height = 0;
+ }
+ toolbar->full_width = 2 * TOOLBAR_WIDGET_GUTTER +
+ ((row_width > toolbar->editor_size.x) ?
+ row_width : toolbar->editor_size.x);
+}
+
+
+/**
+ * Reformat (reflow) the widgets into the toolbar, based on the toolbar size
+ * and the previously calculated widget dimensions.
+ *
+ * \param *toolbar The toolbar to reformat.
+ */
+
+void ro_toolbar_reformat_widgets(struct toolbar *toolbar)
+{
+ int left_margin, right_margin;
+
+ left_margin = TOOLBAR_WIDGET_GUTTER;
+ right_margin = toolbar->clip_width - TOOLBAR_WIDGET_GUTTER;
+
+ /* Flow the toolbar editor row, which will be a fixed with and
+ * may alter the right margin.
+ */
+
+ if (toolbar->editor != NULL && toolbar->editing) {
+ if (right_margin < left_margin + toolbar->editor_size.x)
+ right_margin = left_margin + toolbar->editor_size.x;
+
+ ro_gui_button_bar_set_extent(toolbar->editor,
+ left_margin,
+ toolbar->row_y0[TOOLBAR_ROW_EDIT],
+ left_margin + toolbar->editor_size.x,
+ toolbar->row_y1[TOOLBAR_ROW_EDIT]);
+
+ if (toolbar->editor_div1 != -1)
+ xwimp_resize_icon(toolbar->toolbar_handle,
+ toolbar->editor_div1, -8,
+ toolbar->row_y0[TOOLBAR_ROW_DIV1],
+ toolbar->clip_width + 8,
+ toolbar->row_y1[TOOLBAR_ROW_DIV1]);
+ }
+
+ /* Flow the top row. */
+
+ if (toolbar->throbber != NULL && toolbar->throbber_display) {
+ if (toolbar->throbber_right) {
+ right_margin -= (toolbar->throbber_size.x +
+ TOOLBAR_WIDGET_GUTTER);
+ } else {
+ ro_gui_throbber_set_extent(toolbar->throbber,
+ left_margin,
+ toolbar->row_y0[TOOLBAR_ROW_TOP],
+ left_margin + toolbar->throbber_size.x,
+ toolbar->row_y1[TOOLBAR_ROW_TOP]);
+ left_margin += (toolbar->throbber_size.x +
+ TOOLBAR_WIDGET_GUTTER);
+ }
+ }
+
+ if (toolbar->buttons != NULL &&
+ (toolbar->buttons_display || toolbar->editing)) {
+ if (right_margin < left_margin + toolbar->buttons_size.x)
+ right_margin = left_margin + toolbar->buttons_size.x;
+
+ ro_gui_button_bar_set_extent(toolbar->buttons,
+ left_margin,
+ toolbar->row_y0[TOOLBAR_ROW_TOP],
+ left_margin + toolbar->buttons_size.x,
+ toolbar->row_y1[TOOLBAR_ROW_TOP]);
+ left_margin += (toolbar->buttons_size.x +
+ TOOLBAR_WIDGET_GUTTER);
+ }
+
+ if (toolbar->url != NULL && toolbar->url_display) {
+ if (right_margin < left_margin + toolbar->url_size.x)
+ right_margin = left_margin + toolbar->url_size.x;
+
+ ro_gui_url_bar_set_extent(toolbar->url,
+ left_margin,
+ toolbar->row_y0[TOOLBAR_ROW_TOP],
+ right_margin,
+ toolbar->row_y1[TOOLBAR_ROW_TOP]);
+
+ left_margin = right_margin + TOOLBAR_WIDGET_GUTTER;
+ }
+
+ if (toolbar->throbber != NULL && toolbar->throbber_display &&
+ toolbar->throbber_right) {
+ left_margin = right_margin + TOOLBAR_WIDGET_GUTTER;
+ ro_gui_throbber_set_extent(toolbar->throbber,
+ left_margin,
+ toolbar->row_y0[TOOLBAR_ROW_TOP],
+ left_margin + toolbar->throbber_size.x,
+ toolbar->row_y1[TOOLBAR_ROW_TOP]);
+ }
+
+}
+
+
+/* This is an exported interface documented in toolbar.h */
+
+void ro_toolbar_destroy(struct toolbar *toolbar)
+{
+ struct toolbar *bar;
+
+ if (toolbar == NULL)
+ return;
+
+ LOG("Destroying toolbar 0x%x", (unsigned int)toolbar);
+
+ /* Destroy the widgets. */
+
+ if (toolbar->buttons != NULL)
+ ro_gui_button_bar_destroy(toolbar->buttons);
+
+ if (toolbar->editor != NULL)
+ ro_gui_button_bar_destroy(toolbar->editor);
+
+ if (toolbar->url != NULL)
+ ro_gui_url_bar_destroy(toolbar->url);
+
+ if (toolbar->throbber != NULL)
+ ro_gui_throbber_destroy(toolbar->throbber);
+
+ /* Delete the toolbar window. */
+
+ if (toolbar->toolbar_handle != NULL) {
+ xwimp_delete_window(toolbar->toolbar_handle);
+ ro_gui_wimp_event_finalise(toolbar->toolbar_handle);
+ }
+
+ /* Remove the bar from the list and free the memory.
+ */
+
+ if (ro_toolbar_bars == toolbar) {
+ ro_toolbar_bars = toolbar->next;
+ } else {
+ for (bar = ro_toolbar_bars; bar != NULL && bar->next != toolbar;
+ bar = bar->next);
+
+ if (bar->next == toolbar)
+ bar->next = toolbar->next;
+ }
+
+ free(toolbar);
+
+}
+
+
+/**
+ * Handle redraw request events for a toolbar workarea.
+ *
+ * \param *redraw The redraw block for the event.
+ */
+
+void ro_toolbar_redraw(wimp_draw *redraw)
+{
+ struct toolbar *toolbar;
+ osbool more;
+ os_error *error;
+
+ toolbar = (struct toolbar *)ro_gui_wimp_event_get_user_data(redraw->w);
+
+ assert(toolbar != NULL);
+
+ error = xwimp_redraw_window(redraw, &more);
+ if (error) {
+ LOG("xwimp_redraw_window: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+ while (more) {
+ ro_plot_origin_x = redraw->box.x0 - redraw->xscroll;
+ ro_plot_origin_y = redraw->box.y1 - redraw->yscroll;
+
+ if (toolbar->buttons != NULL && toolbar->buttons_display)
+ ro_gui_button_bar_redraw(toolbar->buttons, redraw);
+
+ if (toolbar->editor != NULL && toolbar->editing)
+ ro_gui_button_bar_redraw(toolbar->editor, redraw);
+
+ if (toolbar->url != NULL && toolbar->url_display)
+ ro_gui_url_bar_redraw(toolbar->url, redraw);
+
+ error = xwimp_get_rectangle(redraw, &more);
+ if (error) {
+ LOG("xwimp_get_rectangle: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+ }
+}
+
+
+/**
+ * Process clicks on a toolbar, passing details on to clients where necessary.
+ *
+ * \param *pointer The wimp mouse click event.
+ * \return True if the event was handled; else false.
+ */
+
+bool ro_toolbar_click(wimp_pointer *pointer)
+{
+ struct toolbar *toolbar;
+ union toolbar_action action;
+ wimp_window_state state;
+ os_error *error;
+
+ toolbar = (struct toolbar *)
+ ro_gui_wimp_event_get_user_data(pointer->w);
+
+ if (toolbar == NULL)
+ return false;
+
+ assert(pointer->w == toolbar->toolbar_handle);
+
+ state.w = toolbar->toolbar_handle;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return false;
+ }
+
+ /* If the click wasn't in the URL Bar's text field, then it will
+ * need to close any URL Complete window that is open.
+ *
+ * \TODO -- This should really move into the URL Bar module, as
+ * URL Complete is really an extension to that.
+ */
+
+ if (toolbar->url != NULL && toolbar->url_display &&
+ !ro_gui_url_bar_test_for_text_field_click(toolbar->url,
+ pointer))
+ ro_gui_url_complete_close();
+
+ /* Pass the click around the toolbar widgets. */
+
+ if (toolbar->buttons != NULL &&
+ (toolbar->buttons_display || toolbar->editing) &&
+ ro_gui_button_bar_click(toolbar->buttons, pointer,
+ &state, &action.button)) {
+ if (action.button != TOOLBAR_BUTTON_NONE &&
+ !toolbar->editing &&
+ toolbar->callbacks != NULL &&
+ toolbar->callbacks->user_action != NULL)
+ toolbar->callbacks->user_action(toolbar->client_data,
+ TOOLBAR_ACTION_BUTTON, action);
+ return true;
+ }
+
+ if (toolbar->url != NULL && toolbar->url_display &&
+ ro_gui_url_bar_click(toolbar->url, pointer,
+ &state, &action.url)) {
+ if (action.url != TOOLBAR_URL_NONE &&
+ !toolbar->editing &&
+ toolbar->callbacks != NULL &&
+ toolbar->callbacks->user_action != NULL)
+ toolbar->callbacks->user_action(toolbar->client_data,
+ TOOLBAR_ACTION_URL, action);
+ return true;
+ }
+
+ if (toolbar->editor != NULL && toolbar->editing &&
+ ro_gui_button_bar_click(toolbar->editor, pointer,
+ &state, &action.button)) {
+ return true;
+ }
+
+ /* Nothing else has handled this, so try passing it to the
+ * URL Complete module.
+ *
+ * \TODO -- This should really move into the URL Bar module, as
+ * URL Complete is really an extension to that.
+ */
+
+ if (toolbar->url != NULL && toolbar->url_display &&
+ ro_gui_url_bar_test_for_text_field_click(toolbar->url,
+ pointer)) {
+ ro_gui_url_complete_start(toolbar);
+ return true;
+ }
+
+ return false;
+}
+
+
+/**
+ * Process keypresses in a toolbar, passing details on to clients where
+ * necessary.
+ *
+ * \param *key The wimp key press event.
+ * \return True if the event was handled; else false.
+ */
+
+bool ro_toolbar_keypress(wimp_key *key)
+{
+ struct toolbar *toolbar;
+
+ toolbar = (struct toolbar *) ro_gui_wimp_event_get_user_data(key->w);
+
+ if (toolbar == NULL)
+ return false;
+
+ /* Pass the keypress on to the client and stop if they handle it. */
+
+ if (toolbar->callbacks->key_press != NULL &&
+ toolbar->callbacks->key_press(toolbar->client_data, key))
+ return true;
+
+ /* If the caret is in the URL bar, ask the URL Complete module if it
+ * wants to handle the keypress.
+ *
+ * \TODO -- This should really move into the URL Bar module, as
+ * URL Complete is really an extension to that.
+ */
+
+ if (toolbar->url != NULL && toolbar->url_display &&
+ ro_gui_url_bar_test_for_text_field_keypress(
+ toolbar->url, key) &&
+ ro_gui_url_complete_keypress(toolbar, key->c))
+ return true;
+
+ return false;
+}
+
+
+/**
+ * Prepare the toolbar menu for (re-)opening
+ *
+ * \param w The window owning the menu.
+ * \param i The icon owning the menu.
+ * \param *menu The menu about to be opened.
+ * \param *pointer Pointer to the relevant wimp event block, or
+ * NULL for an Adjust click.
+ * \return true if the event was handled; else false.
+ */
+
+bool ro_toolbar_menu_prepare(wimp_w w, wimp_i i, wimp_menu *menu,
+ wimp_pointer *pointer)
+{
+ struct toolbar *toolbar;
+
+ toolbar = (struct toolbar *) ro_gui_wimp_event_get_user_data(w);
+
+ if (toolbar == NULL)
+ return false;
+
+ /* Pass the event on to potentially interested widgets. */
+
+ if (toolbar->url != NULL && ro_gui_url_bar_menu_prepare(toolbar->url,
+ i, menu, pointer))
+ return true;
+
+ /* Try to process the event as a toolbar menu. */
+
+ if (menu != toolbar_menu)
+ return false;
+
+ /* Shade menu entries according to the state of the window and object
+ * under the pointer.
+ */
+
+ /* Toolbar (Sub)Menu */
+
+ ro_gui_menu_set_entry_shaded(menu, TOOLBAR_EDIT,
+ ro_toolbar_menu_edit_shade(toolbar));
+ ro_gui_menu_set_entry_ticked(menu, TOOLBAR_EDIT,
+ ro_toolbar_menu_edit_tick(toolbar));
+
+ ro_gui_menu_set_entry_shaded(menu, TOOLBAR_BUTTONS,
+ ro_toolbar_menu_option_shade(toolbar) ||
+ toolbar->buttons == NULL);
+ ro_gui_menu_set_entry_ticked(menu, TOOLBAR_BUTTONS,
+ ro_toolbar_menu_buttons_tick(toolbar) &&
+ toolbar->buttons != NULL);
+
+ ro_gui_menu_set_entry_shaded(menu, TOOLBAR_ADDRESS_BAR,
+ ro_toolbar_menu_edit_shade(toolbar) ||
+ toolbar->url == NULL);
+ ro_gui_menu_set_entry_ticked(menu, TOOLBAR_ADDRESS_BAR,
+ ro_toolbar_menu_url_tick(toolbar) &&
+ toolbar->url != NULL);
+
+ ro_gui_menu_set_entry_shaded(menu, TOOLBAR_THROBBER,
+ ro_toolbar_menu_edit_shade(toolbar) ||
+ toolbar->throbber == NULL);
+ ro_gui_menu_set_entry_ticked(menu, TOOLBAR_THROBBER,
+ ro_toolbar_menu_throbber_tick(toolbar) &&
+ toolbar->throbber != NULL);
+
+ return true;
+}
+
+
+/**
+ * Handle submenu warnings for the toolbar menu
+ *
+ * \param w The window owning the menu.
+ * \param i The icon owning the menu.
+ * \param *menu The menu to which the warning applies.
+ * \param *selection The wimp menu selection data.
+ * \param action The selected menu action.
+ */
+
+void ro_toolbar_menu_warning(wimp_w w, wimp_i i, wimp_menu *menu,
+ wimp_selection *selection, menu_action action)
+{
+ /* Do nothing */
+}
+
+
+/**
+ * Handle selections from the toolbar menu
+ *
+ * \param w The window owning the menu.
+ * \param i The icon owning the menu.
+ * \param *menu The menu from which the selection was made.
+ * \param *selection The wimp menu selection data.
+ * \param action The selected menu action.
+ * \return true if action accepted; else false.
+ */
+
+bool ro_toolbar_menu_select(wimp_w w, wimp_i i, wimp_menu *menu,
+ wimp_selection *selection, menu_action action)
+{
+ struct toolbar *toolbar;
+
+ toolbar = (struct toolbar *) ro_gui_wimp_event_get_user_data(w);
+
+ if (toolbar == NULL)
+ return false;
+
+ /* Pass the event on to potentially interested widgets. */
+
+ if (toolbar->url != NULL && ro_gui_url_bar_menu_select(toolbar->url,
+ i, menu, selection, action))
+ return true;
+
+ /* Try to process the event as a toolbar menu. */
+
+ if (menu != toolbar_menu)
+ return false;
+
+ switch (action) {
+ case TOOLBAR_BUTTONS:
+ ro_toolbar_set_display_buttons(toolbar,
+ !ro_toolbar_get_display_buttons(toolbar));
+ break;
+ case TOOLBAR_ADDRESS_BAR:
+ ro_toolbar_set_display_url(toolbar,
+ !ro_toolbar_get_display_url(toolbar));
+ if (ro_toolbar_get_display_url(toolbar))
+ ro_toolbar_take_caret(toolbar);
+ break;
+ case TOOLBAR_THROBBER:
+ ro_toolbar_set_display_throbber(toolbar,
+ !ro_toolbar_get_display_throbber(toolbar));
+ break;
+ case TOOLBAR_EDIT:
+ ro_toolbar_toggle_edit(toolbar);
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+
+/**
+ * Translate the contents of a message_HELP_REQUEST into a suffix for a
+ * NetSurf message token. The help system will then add this to whatever
+ * prefix the current toolbar has registered with WimpEvent.
+ *
+ * \param w The window handle under the mouse.
+ * \param i The icon handle under the mouse.
+ * \param *pos The mouse position.
+ * \param buttons The mouse button state.
+ * \return The required help token suffix.
+ */
+
+const char *ro_toolbar_get_help_suffix(wimp_w w, wimp_i i, os_coord *pos,
+ wimp_mouse_state buttons)
+{
+ struct toolbar *toolbar;
+ wimp_window_state state;
+ os_error *error;
+ const char *suffix;
+
+ toolbar = (struct toolbar *) ro_gui_wimp_event_get_user_data(w);
+
+ if (toolbar == NULL || toolbar->toolbar_handle != w)
+ return NULL;
+
+ state.w = toolbar->toolbar_handle;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return NULL;
+ }
+
+ /* Pass the help request around the toolbar widgets. */
+
+ if (toolbar->throbber != NULL && toolbar->throbber_display &&
+ ro_gui_throbber_help_suffix(toolbar->throbber, i,
+ pos, &state, buttons, &suffix))
+ return suffix;
+
+ if (toolbar->url != NULL && toolbar->url_display &&
+ ro_gui_url_bar_help_suffix(toolbar->url, i,
+ pos, &state, buttons, &suffix))
+ return suffix;
+
+ if (toolbar->buttons != NULL && toolbar->buttons_display &&
+ ro_gui_button_bar_help_suffix(toolbar->buttons, i,
+ pos, &state, buttons, &suffix))
+ return suffix;
+
+ return "";
+}
+
+
+/* This is an exported interface documented in toolbar.h */
+
+void ro_toolbar_update_client_data(struct toolbar *toolbar, void *client_data)
+{
+ if (toolbar != NULL)
+ toolbar->client_data = client_data;
+}
+
+
+/* This is an exported interface documented in toolbar.h */
+
+void ro_toolbar_update_all_buttons(void)
+{
+ struct toolbar *bar;
+
+ bar = ro_toolbar_bars;
+ while (bar != NULL) {
+ ro_toolbar_update_buttons(bar);
+
+ bar = bar->next;
+ }
+}
+
+
+/**
+ * Update the state of a toolbar's buttons.
+ *
+ * \param toolbar the toolbar to update
+ */
+
+void ro_toolbar_update_buttons(struct toolbar *toolbar)
+{
+ assert(toolbar != NULL);
+
+ if (toolbar->callbacks != NULL &&
+ toolbar->callbacks->update_buttons != NULL)
+ toolbar->callbacks->update_buttons(toolbar->client_data);
+}
+
+/* This is an exported interface documented in toolbar.h */
+
+void ro_toolbar_refresh(struct toolbar *toolbar)
+{
+ assert(toolbar != NULL);
+
+ ro_toolbar_process(toolbar, -1, true);
+ if (toolbar->callbacks != NULL &&
+ toolbar->callbacks->change_size != NULL)
+ toolbar->callbacks->change_size(toolbar->client_data);
+
+ if (toolbar->toolbar_handle != NULL)
+ xwimp_force_redraw(toolbar->toolbar_handle, 0, 0,
+ toolbar->current_width,
+ toolbar->current_height);
+}
+
+
+/* This is an exported interface documented in toolbar.h */
+
+void ro_toolbar_theme_update(void)
+{
+ struct toolbar *bar, *next;
+ bool ok;
+
+ bar = ro_toolbar_bars;
+ while (bar != NULL) {
+ /* Take the next bar address now, as *bar may become invalid
+ * during the update process (if an update fails and
+ * ro_toolbar_destroy() is called) and we don't want to lose
+ * the link to the rest of the chain.
+ */
+
+ next = bar->next;
+
+ /* Only process the bar if the theme is set to the default.
+ * Otherwise, it's up to the owner to do whatever they need
+ * to do for themselves.
+ */
+
+ if (bar->theme == NULL) {
+ ok = ro_toolbar_rebuild(bar);
+
+ if (!ok)
+ ro_toolbar_destroy(bar);
+ } else {
+ ok = true;
+ }
+
+ if (bar->callbacks != NULL &&
+ bar->callbacks->theme_update != NULL)
+ bar->callbacks->theme_update(bar->client_data, ok);
+
+ bar = next;
+ }
+}
+
+
+/* This is an exported interface documented in toolbar.h */
+
+struct toolbar *ro_toolbar_parent_window_lookup(wimp_w w)
+{
+ struct toolbar *toolbar;
+
+ toolbar = ro_toolbar_bars;
+ while (toolbar != NULL && toolbar->parent_handle != w)
+ toolbar = toolbar->next;
+
+ return toolbar;
+}
+
+
+/* This is an exported interface documented in toolbar.h */
+
+struct toolbar *ro_toolbar_window_lookup(wimp_w w)
+{
+ struct toolbar *toolbar;
+
+ toolbar = ro_toolbar_bars;
+ while (toolbar != NULL && toolbar->toolbar_handle != w)
+ toolbar = toolbar->next;
+
+ return toolbar;
+}
+
+
+/* This is an exported interface documented in toolbar.h */
+
+wimp_w ro_toolbar_get_parent_window(struct toolbar *toolbar)
+{
+ return (toolbar != NULL) ? toolbar->parent_handle : 0;
+}
+
+
+/* This is an exported interface documented in toolbar.h */
+
+wimp_w ro_toolbar_get_window(struct toolbar *toolbar)
+{
+ return (toolbar != NULL) ? toolbar->toolbar_handle : 0;
+}
+
+
+/* This is an exported interface documented in toolbar.h */
+
+int ro_toolbar_height(struct toolbar *toolbar)
+{
+ return (toolbar == NULL) ? 0 : toolbar->current_height;
+}
+
+
+/* This is an exported interface documented in toolbar.h */
+
+int ro_toolbar_full_height(struct toolbar *toolbar)
+{
+ return (toolbar == NULL) ? 0 : toolbar->full_height;
+}
+
+
+/* This is an exported interface documented in toolbar.h */
+
+void ro_toolbar_start_throbbing(struct toolbar *toolbar)
+{
+ if (toolbar != NULL && toolbar->throbber != NULL)
+ ro_gui_throbber_animate(toolbar->throbber);
+}
+
+
+/* This is an exported interface documented in toolbar.h */
+
+void ro_toolbar_stop_throbbing(struct toolbar *toolbar)
+{
+ if (toolbar != NULL && toolbar->throbber != NULL)
+ ro_gui_throbber_stop(toolbar->throbber);
+}
+
+
+/* This is an exported interface documented in toolbar.h */
+
+void ro_toolbar_throb(struct toolbar *toolbar)
+{
+ if (toolbar != NULL && toolbar->throbber != NULL)
+ ro_gui_throbber_animate(toolbar->throbber);
+}
+
+
+/* This is an exported interface documented in toolbar.h */
+
+bool ro_toolbar_set_button_order(struct toolbar *toolbar, char order[])
+{
+ if (toolbar == NULL || toolbar->buttons == NULL)
+ return false;
+
+ if (!ro_gui_button_bar_arrange_buttons(toolbar->buttons, order))
+ return false;
+
+ ro_toolbar_refresh_widget_dimensions(toolbar);
+
+ return ro_toolbar_process(toolbar, -1, true);
+}
+
+
+/* This is an exported interface documented in toolbar.h */
+
+void ro_toolbar_set_button_shaded_state(struct toolbar *toolbar,
+ button_bar_action action, bool shaded)
+{
+ if (toolbar == NULL || toolbar->buttons == NULL)
+ return;
+
+ ro_gui_button_bar_shade_button(toolbar->buttons, action, shaded);
+}
+
+
+/* This is an exported interface documented in toolbar.h */
+
+bool ro_toolbar_take_caret(struct toolbar *toolbar)
+{
+ if (toolbar == NULL || toolbar->url == NULL || !toolbar->url_display)
+ return false;
+
+ return ro_gui_url_bar_take_caret(toolbar->url);
+}
+
+
+/* This is an exported interface documented in toolbar.h */
+
+void ro_toolbar_set_url(struct toolbar *toolbar, const char *url,
+ bool is_utf8, bool set_caret)
+{
+ if (toolbar != NULL && toolbar->url != NULL)
+ ro_gui_url_bar_set_url(toolbar->url, url, is_utf8, set_caret);
+}
+
+
+/* This is an exported interface documented in toolbar.h */
+
+const char *ro_toolbar_get_url(struct toolbar *toolbar)
+{
+ if (toolbar == NULL || toolbar->url == NULL)
+ return NULL;
+
+ return ro_gui_url_bar_get_url(toolbar->url);
+}
+
+
+/* This is an exported interface documented in toolbar.h */
+
+void ro_toolbar_update_all_hotlists(void)
+{
+ struct toolbar *bar;
+
+ bar = ro_toolbar_bars;
+ while (bar != NULL) {
+ ro_toolbar_update_hotlist(bar);
+
+ bar = bar->next;
+ }
+}
+
+
+/* This is an exported interface documented in toolbar.h */
+
+void ro_toolbar_update_hotlist(struct toolbar *toolbar)
+{
+ if (toolbar == NULL || toolbar->url == NULL)
+ return;
+
+ ro_gui_url_bar_update_hotlist(toolbar->url);
+}
+
+
+/* This is an exported interface documented in toolbar.h */
+
+bool ro_toolbar_get_url_field_extent(struct toolbar *toolbar, os_box *extent)
+{
+ if (toolbar == NULL || toolbar->url == NULL)
+ return false;
+
+ if (extent == NULL)
+ return true;
+
+ return ro_gui_url_bar_get_url_extent(toolbar->url, extent);
+}
+
+
+/* This is an exported interface documented in toolbar.h */
+
+void ro_toolbar_set_site_favicon(struct toolbar *toolbar,
+ struct hlcache_handle *h)
+{
+ if (toolbar == NULL || toolbar->url == NULL)
+ return;
+
+ ro_gui_url_bar_set_site_favicon(toolbar->url, h);
+}
+
+
+/* This is an exported interface documented in toolbar.h */
+
+void ro_toolbar_set_content_favicon(struct toolbar *toolbar,
+ struct gui_window *g)
+{
+ if (toolbar == NULL || toolbar->url == NULL)
+ return;
+
+ ro_gui_url_bar_set_content_favicon(toolbar->url, g);
+}
+
+
+/* This is an exported interface documented in toolbar.h */
+
+void ro_toolbar_update_urlsuggest(struct toolbar *toolbar)
+{
+ if (toolbar == NULL || toolbar->url == NULL)
+ return;
+
+ ro_gui_url_bar_update_urlsuggest(toolbar->url);
+}
+
+
+/* This is an exported interface documented in toolbar.h */
+
+void ro_toolbar_set_display_buttons(struct toolbar *toolbar, bool display)
+{
+ if (toolbar == NULL || toolbar->buttons == NULL)
+ return;
+
+ toolbar->buttons_display = display;
+ ro_gui_button_bar_hide(toolbar->buttons, !display);
+ ro_toolbar_refresh_widget_dimensions(toolbar);
+ ro_toolbar_refresh(toolbar);
+}
+
+
+/* This is an exported interface documented in toolbar.h */
+
+void ro_toolbar_set_display_url(struct toolbar *toolbar, bool display)
+{
+ if (toolbar == NULL || toolbar->url == NULL)
+ return;
+
+ toolbar->url_display = display;
+ ro_gui_url_bar_hide(toolbar->url, !display);
+ ro_toolbar_refresh_widget_dimensions(toolbar);
+ ro_toolbar_refresh(toolbar);
+}
+
+
+/* This is an exported interface documented in toolbar.h */
+
+void ro_toolbar_set_display_throbber(struct toolbar *toolbar, bool display)
+{
+ if (toolbar == NULL || toolbar->throbber == NULL)
+ return;
+
+ toolbar->throbber_display = display;
+ ro_gui_throbber_hide(toolbar->throbber, !display);
+ ro_toolbar_refresh_widget_dimensions(toolbar);
+ ro_toolbar_refresh(toolbar);
+}
+
+
+/* This is an exported interface documented in toolbar.h */
+
+bool ro_toolbar_get_display_buttons(struct toolbar *toolbar)
+{
+ return (toolbar == NULL || toolbar->buttons == NULL) ?
+ false : toolbar->buttons_display;
+}
+
+
+/* This is an exported interface documented in toolbar.h */
+
+bool ro_toolbar_get_display_url(struct toolbar *toolbar)
+{
+ return (toolbar == NULL || toolbar->url == NULL) ?
+ false : toolbar->url_display;
+}
+
+
+/* This is an exported interface documented in toolbar.h */
+
+bool ro_toolbar_get_display_throbber(struct toolbar *toolbar)
+{
+ return (toolbar == NULL || toolbar->throbber == NULL) ?
+ false : toolbar->throbber_display;
+}
+
+
+/* This is an exported interface documented in toolbar.h */
+
+bool ro_toolbar_get_editing(struct toolbar *toolbar)
+{
+ return (toolbar == NULL || !toolbar->editing) ? false : true;
+}
+
+
+/* This is an exported interface documented in toolbar.h */
+
+bool ro_toolbar_toggle_edit(struct toolbar *toolbar)
+{
+ if (toolbar == NULL || toolbar->editor == NULL)
+ return false;
+
+ toolbar->editing = !toolbar->editing;
+
+ ro_gui_button_bar_hide(toolbar->editor, !toolbar->editing);
+ ro_gui_button_bar_hide(toolbar->buttons,
+ !toolbar->buttons_display && !toolbar->editing);
+
+ if (!ro_toolbar_rebuild(toolbar)) {
+ ro_toolbar_destroy(toolbar);
+ return false;
+ }
+
+ ro_toolbar_refresh(toolbar);
+
+ /* If there's a callback registered and an edit has finished,
+ * tell out client what the new button state is.
+ */
+
+ if (!toolbar->editing && toolbar->buttons != NULL &&
+ toolbar->callbacks != NULL &&
+ toolbar->callbacks->save_buttons != NULL) {
+ char *new_buttons;
+ new_buttons = ro_gui_button_bar_get_config(toolbar->buttons);
+ toolbar->callbacks->save_buttons(toolbar->client_data,
+ new_buttons);
+ }
+
+ return true;
+}
+
diff --git a/frontends/riscos/toolbar.h b/frontends/riscos/toolbar.h
new file mode 100644
index 000000000..41f1af728
--- /dev/null
+++ b/frontends/riscos/toolbar.h
@@ -0,0 +1,542 @@
+/*
+ * Copyright 2005 Richard Wilson <info@tinct.net>
+ * Copyright 2010, 2011 Stephen Fryatt <stevef@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Window toolbars (interface).
+ */
+
+#include <stdbool.h>
+#include "riscos/theme.h"
+#include "riscos/gui/button_bar.h"
+#include "riscos/gui/throbber.h"
+#include "riscos/gui/url_bar.h"
+
+#ifndef _NETSURF_RISCOS_TOOLBAR_H_
+#define _NETSURF_RISCOS_TOOLBAR_H_
+
+typedef enum {
+ TOOLBAR_FLAGS_NONE = 0x00,
+ TOOLBAR_FLAGS_DISPLAY = 0x01,
+ TOOLBAR_FLAGS_EDIT = 0x02,
+} toolbar_flags;
+
+/**
+ * Widget action types that the toolbar can pass on to clients.
+ */
+
+typedef enum {
+ TOOLBAR_ACTION_NONE = 0,
+ TOOLBAR_ACTION_BUTTON,
+ TOOLBAR_ACTION_URL
+} toolbar_action_type;
+
+/**
+ * Union to hold the different widget action data that can be passed
+ * from widget via toolbar to client.
+ */
+
+union toolbar_action {
+ button_bar_action button;
+ url_bar_action url;
+};
+
+struct toolbar;
+
+struct toolbar_callbacks {
+ /** Call on theme update */
+ void (*theme_update)(void *, bool);
+
+ /** Call on bar size change */
+ void (*change_size)(void *);
+
+ /** Call to update button states */
+ void (*update_buttons)(void *);
+
+ /** Call to handle user actions */
+ void (*user_action)(void *, toolbar_action_type, union toolbar_action);
+
+ /** Call to handle keypresses. */
+ bool (*key_press)(void *, wimp_key *);
+
+ /** Call on change to button order. */
+ void (*save_buttons)(void *, char *);
+};
+
+
+#define ro_toolbar_menu_option_shade(toolbar) \
+ (((toolbar) == NULL) || ro_toolbar_get_editing(toolbar))
+
+#define ro_toolbar_menu_buttons_tick(toolbar) \
+ (ro_toolbar_get_display_buttons(toolbar) || \
+ ro_toolbar_get_editing(toolbar))
+
+#define ro_toolbar_menu_url_tick(toolbar) \
+ (ro_toolbar_get_display_url(toolbar))
+
+#define ro_toolbar_menu_throbber_tick(toolbar) \
+ (ro_toolbar_get_display_throbber(toolbar))
+
+#define ro_toolbar_menu_edit_shade(toolbar) ((toolbar) == NULL)
+
+#define ro_toolbar_menu_edit_tick(toolbar) (ro_toolbar_get_editing(toolbar))
+
+
+/* The new toolbar API */
+
+
+/**
+ * Initialise the RISC OS toolbar widget.
+ */
+
+void ro_toolbar_init(void);
+
+
+/**
+ * Create a new toolbar, ready to have widgets added and to be attached to
+ * a window. If a parent window is supplied, then the toolbar module will
+ * handle the window attachments; if NULL, it is up to the client to sort this
+ * out for itself.
+ *
+ * \param *descriptor The theme to apply, or NULL for the default.
+ * \param parent The window to attach the toolbar to, or NULL.
+ * \param style The theme style to apply.
+ * \param bar_flags Toolbar flags for the new bar.
+ * \param *callbacks A client callback block, or NULL for none.
+ * \param *client_data A data pointer to pass to callbacks, or NULL.
+ * \param *help The Help token prefix for interactive help.
+ * \return The handle of the new bar, or NULL on failure.
+ */
+
+struct toolbar *ro_toolbar_create(struct theme_descriptor *descriptor,
+ wimp_w parent, theme_style style, toolbar_flags bar_flags,
+ const struct toolbar_callbacks *callbacks, void *client_data,
+ const char *help);
+
+
+/**
+ * Add a button bar to a toolbar, and configure the buttons.
+ *
+ * \param *toolbar The toolbar to take the button bar.
+ * \param buttons[] The button definitions.
+ * \param *button_order The initial button order to use.
+ * \return true if the action completed; else false.
+ */
+
+bool ro_toolbar_add_buttons(struct toolbar *toolbar,
+ const struct button_bar_buttons buttons[], char *button_order);
+
+
+/**
+ * Add a throbber to a toolbar.
+ *
+ * \param *toolbar The toolbar to take the throbber.
+ * \return true if the action completed; else false.
+ */
+
+bool ro_toolbar_add_throbber(struct toolbar *toolbar);
+
+
+/**
+ * Add a URL bar to a toolbar.
+ *
+ * \param *toolbar The toolbar to take the URL bar.
+ * \return true if the action completed; else false.
+ */
+
+bool ro_toolbar_add_url(struct toolbar *toolbar);
+
+
+/**
+ * (Re-)build a toolbar to use the specified (or current) theme. If false
+ * is returned, the toolbar may not be complete and should be deleted.
+ *
+ * \param *toolbar The toolbar to rebuild.
+ * \return true if the action was successful; else false.
+ */
+
+bool ro_toolbar_rebuild(struct toolbar *toolbar);
+
+
+/**
+ * Attach or re-attach a toolbar to its parent window.
+ *
+ * \param *toolbar The toolbar to attach.
+ * \param parent The window to attach the toolbar to.
+ * \return true if the operation succeeded; else false.
+ */
+
+bool ro_toolbar_attach(struct toolbar *toolbar, wimp_w parent);
+
+
+/**
+ * Process a toolbar, updating its contents for a size or content change.
+ *
+ * \param *toolbar The toolbar to update.
+ * \param width The width to reformat to, or -1 to use parent.
+ * \param reformat true to force a widget reflow; else false.
+ * \return true if the operation succeeded; else false.
+ */
+
+bool ro_toolbar_process(struct toolbar *toolbar, int width, bool reformat);
+
+
+/**
+ * Destroy a toolbar after use.
+ *
+ * \param *toolbar The toolbar to destroy.
+ */
+
+void ro_toolbar_destroy(struct toolbar *toolbar);
+
+
+/**
+ * Change the client data associated with a toolbar's callbacks.
+ *
+ * \param *toolbar the toolbar whose data is to be updated.
+ * \param *client_data the new client data, or NULL for none.
+ */
+
+void ro_toolbar_update_client_data(struct toolbar *toolbar, void *client_data);
+
+
+/**
+ * Force the update of all toolbars buttons to reflect the current state.
+ */
+
+void ro_toolbar_update_all_buttons(void);
+
+
+/**
+ * Refresh a toolbar after it has been updated
+ *
+ * \param toolbar the toolbar to update
+ */
+
+void ro_toolbar_refresh(struct toolbar *toolbar);
+
+
+/**
+ * Force the update of all toolbars to reflect the application of a new theme.
+ */
+
+void ro_toolbar_theme_update(void);
+
+
+/**
+ * Find the toolbar associated with a given RO window handle.
+ *
+ * \param w the window handle to look up.
+ * \return the toolbar handle, or NULL if a match wasn't found.
+ */
+
+struct toolbar *ro_toolbar_parent_window_lookup(wimp_w w);
+
+
+/**
+ * Find the toolbar using a given RO window handle for its pane.
+ *
+ * \param w the window (pane) handle to look up.
+ * \return the toolbar handle, or NULL if a match wasn't found.
+ */
+
+struct toolbar *ro_toolbar_window_lookup(wimp_w w);
+
+
+/**
+ * Return the RO window handle of the parent window for a toolbar.
+ *
+ * \param *toolbar the toolbar to look up.
+ * \return the RO window handle of the parent.
+ */
+
+wimp_w ro_toolbar_get_parent_window(struct toolbar *toolbar);
+
+
+/**
+ * Return the RO window handle of a toolbar.
+ *
+ * \param *toolbar the toolbar to look up.
+ * \return the RO window handle of the bar.
+ */
+
+wimp_w ro_toolbar_get_window(struct toolbar *toolbar);
+
+
+/**
+ * Return the current height of a toolbar, allowing for available window
+ * space.
+ *
+ * \param *toolbar The toolbar of interest.
+ * \return The current toolbar height in OS units.
+ */
+
+int ro_toolbar_height(struct toolbar *toolbar);
+
+
+/**
+ * Return the full height that a toolbar could grow to, if space is available.
+ *
+ * \param *toolbar The toolbar of interest.
+ * \return The full toolbar height in OS units.
+ */
+
+int ro_toolbar_full_height(struct toolbar *toolbar);
+
+
+/**
+ * Starts a toolbar throbber, if there is one active.
+ *
+ * \param *toolbar the toolbar to start throbbing.
+ */
+
+void ro_toolbar_start_throbbing(struct toolbar *toolbar);
+
+
+/**
+ * Stops a toolbar throbber, if there is one active.
+ *
+ * \param *toolbar the toolbar to stop throbbing.
+ */
+
+void ro_toolbar_stop_throbbing(struct toolbar *toolbar);
+
+
+/**
+ * Animate a toolbar throbber, if there is one active.
+ *
+ * \param *toolbar the toolbar to throb.
+ */
+
+void ro_toolbar_throb(struct toolbar *toolbar);
+
+/**
+ * Change the arrangement of buttons and spacers on a button bar within a
+ * toolbar.
+ *
+ * \param *toolbar The toolbar to change.
+ * \param order[] The new button configuration.
+ * \return true of the order was updated; else false.
+ */
+
+bool ro_toolbar_set_button_order(struct toolbar *toolbar, char order[]);
+
+
+/**
+ * Set the shaded state of a toolbar button.
+ *
+ * \param *toolbar the toolbar to update.
+ * \param action the button action to update.
+ * \param shaded true if the button should be shaded; else false.
+ */
+
+void ro_toolbar_set_button_shaded_state(struct toolbar *toolbar,
+ button_bar_action action, bool shaded);
+
+/**
+ * Give a toolbar input focus, placing the caret into the URL bar if one is
+ * present. Currently a toolbar can only accept focus if it has a URL bar.
+ *
+ * \param *toolbar The toolbar to take the caret.
+ * \return true if the caret was taken; else false.
+ */
+
+bool ro_toolbar_take_caret(struct toolbar *toolbar);
+
+
+/**
+ * Set the content of a toolbar's URL field.
+ *
+ * \param *toolbar the toolbar to update.
+ * \param *url the new url to insert.
+ * \param is_utf8 true if the string is in utf8 encoding; false
+ * if it is in local encoding.
+ * \param set_caret true if the caret should be placed in the field;
+ * else false.
+ */
+
+void ro_toolbar_set_url(struct toolbar *toolbar, const char *url,
+ bool is_utf8, bool set_caret);
+
+
+/**
+ * Return a pointer to the URL contained in a browser toolbar. If the toolbar
+ * doesn't have a URL field, then NULL is returned instead.
+ *
+ * \param *toolbar The toolbar to look up the URL from.
+ * \return pointer to the URL, or NULL.
+ */
+
+const char *ro_toolbar_get_url(struct toolbar *toolbar);
+
+
+/**
+ * Update the state of the URL Bar hotlist icons in all open toolbars.
+ */
+
+void ro_toolbar_update_all_hotlists(void);
+
+
+/**
+ * Update the state of a toolbar's URL Bar hotlist icon to reflect any changes
+ * to the URL or the hotlist contents.
+ *
+ * \param *toolbar The toolbar to update.
+ */
+
+void ro_toolbar_update_hotlist(struct toolbar *toolbar);
+
+
+/**
+ * Return the current work area coordinates of the URL and favicon field's
+ * bounding box.
+ *
+ * \param *toolbar The toolbar to look up.
+ * \param *extent Return the coordinates.
+ * \return true if successful; else false.
+ */
+
+bool ro_toolbar_get_url_field_extent(struct toolbar *toolbar, os_box *extent);
+
+
+/**
+ * Update the favicon in a browser window toolbar to the supplied content, or
+ * revert to using filetype-based icons.
+ *
+ * \param *toolbar The toolbar to refresh.
+ * \param *h The new favicon to use, or NULL for none.
+ */
+
+void ro_toolbar_set_site_favicon(struct toolbar *toolbar,
+ struct hlcache_handle *h);
+
+
+/**
+ * Update the favicon in a browser window toolbar to reflect the RISC OS
+ * filetype of the content within the supplied window. If the toolbar
+ * currently has a site favicon set, then this call will be ignored.
+ *
+ * \param *toolbar The toolbar to refresh.
+ * \param *g The gui window to set content favicon for.
+ */
+
+void ro_toolbar_set_content_favicon(struct toolbar *toolbar,
+ struct gui_window *g);
+
+
+/**
+ * Update the state of the URL suggestion pop-up menu icon on a toolbar.
+ *
+ * \param *toolbar The toolbar to update.
+ */
+
+void ro_toolbar_update_urlsuggest(struct toolbar *toolbar);
+
+
+/**
+ * Set the display button bar state for a toolbar.
+ *
+ * \param *toolbar the toolbar to update.
+ * \param display true to display the button bar; else false.
+ */
+
+void ro_toolbar_set_display_buttons(struct toolbar *toolbar, bool display);
+
+
+/**
+ * Set the display URL bar state for a toolbar.
+ *
+ * \param *toolbar the toolbar to update.
+ * \param display true to display the URL bar; else false.
+ */
+
+void ro_toolbar_set_display_url(struct toolbar *toolbar, bool display);
+
+
+/**
+ * Set the display throbber state for a toolbar.
+ *
+ * \param *toolbar the toolbar to update.
+ * \param display true to display the throbber; else false.
+ */
+
+void ro_toolbar_set_display_throbber(struct toolbar *toolbar, bool display);
+
+
+/**
+ * Return true or false depending on whether the given toolbar is set to
+ * display the button bar.
+ *
+ * \param *toolbar the toolbar of interest.
+ * \return true if the toolbar exists and the button bar is
+ * shown; else false.
+ */
+
+bool ro_toolbar_get_display_buttons(struct toolbar *toolbar);
+
+
+/**
+ * Return true or false depending on whether the given toolbar is set to
+ * display the URL bar.
+ *
+ * \param *toolbar the toolbar of interest.
+ * \return true if the toolbar exists and the URL bar is
+ * shown; else false.
+ */
+
+bool ro_toolbar_get_display_url(struct toolbar *toolbar);
+
+
+/**
+ * Return true or false depending on whether the given toolbar is set to
+ * display the throbber.
+ *
+ * \param *toolbar the toolbar of interest.
+ * \return true if the toolbar exists and the throbber is
+ * shown; else false.
+ */
+
+bool ro_toolbar_get_display_throbber(struct toolbar *toolbar);
+
+
+/**
+ * Return true or false depending on whether the given toolbar is currently
+ * being edited.
+ *
+ * \param *toolbar the toolbar of interest.
+ * \return true if the toolbar exists and is beng edited;
+ * else false.
+ */
+
+bool ro_toolbar_get_editing(struct toolbar *toolbar);
+
+
+/**
+ * Toggle toolbar edit mode on the given toolbar. Only a button bar can be
+ * edited, so edit mode can only be toggled if there's an editor button
+ * bar defined.
+ *
+ * \param *toolbar The toolbar to be toggled.
+ * \return true if the action was successful; false if
+ * the action failed and the toolbar was destroyed.
+ */
+
+bool ro_toolbar_toggle_edit(struct toolbar *toolbar);
+
+#endif
+
diff --git a/frontends/riscos/treeview.c b/frontends/riscos/treeview.c
new file mode 100644
index 000000000..3428ad3d4
--- /dev/null
+++ b/frontends/riscos/treeview.c
@@ -0,0 +1,1279 @@
+/*
+ * Copyright 2005 Richard Wilson <info@tinct.net>
+ * Copyright 2010 Stephen Fryatt <stevef@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Generic tree handling (implementation).
+ */
+
+#include <oslib/os.h>
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <swis.h>
+#include <time.h>
+#include "oslib/colourtrans.h"
+#include "oslib/dragasprite.h"
+#include "oslib/osbyte.h"
+#include "oslib/osspriteop.h"
+#include "oslib/wimp.h"
+
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/utils.h"
+#include "content/urldb.h"
+#include "desktop/browser.h"
+#include "desktop/plotters.h"
+#include "desktop/textinput.h"
+#include "desktop/tree.h"
+
+#include "riscos/bitmap.h"
+#include "riscos/dialog.h"
+#include "riscos/gui.h"
+#include "riscos/image.h"
+#include "riscos/menus.h"
+#include "riscos/mouse.h"
+#include "riscos/toolbar.h"
+#include "riscos/tinct.h"
+#include "riscos/textarea.h"
+#include "riscos/treeview.h"
+#include "riscos/wimp.h"
+#include "riscos/wimp_event.h"
+#include "riscos/wimputils.h"
+
+#ifndef wimp_KEY_END
+#define wimp_KEY_END wimp_KEY_COPY
+#endif
+
+struct ro_treeview
+{
+ struct tree *tree; /*< Pointer to treeview tree block. */
+ wimp_w w; /*< RO Window Handle for tree window. */
+ struct toolbar *tb; /*< Pointer to toolbar block. */
+ struct {
+ int x; /*< X origin of tree, to RO work area. */
+ int y; /*< Y origin of tree, to RO work area. */
+ } origin;
+ struct {
+ int x; /*< X dimension of the tree, in RO units. */
+ int y; /*< Y dimension of the tree, in RO units. */
+ } size; /* (Dimensions are 0 until set correctly). */
+ struct {
+ int x; /*< X extent of the window, in RO units. */
+ int y; /*< Y extent of the window, in RO units. */
+ } extent; /* (Extents are 0 until set correctly). */
+ struct {
+ int x; /*< X coordinate of drag start */
+ int y; /*< Y coordinate of drag start */
+ } drag_start;
+ tree_drag_type drag; /*< The current drag type for the tree */
+ struct ro_treeview_callbacks *callbacks; /*< Callback handlers */
+};
+
+static void ro_treeview_redraw_request(int x, int y, int width, int height,
+ void *pw);
+static void ro_treeview_resized(struct tree *tree, int width, int height,
+ void *pw);
+static void ro_treeview_scroll_visible(int y, int height, void *pw);
+static void ro_treeview_get_window_dimensions(int *width, int *height,
+ void *pw);
+
+static void ro_treeview_redraw(wimp_draw *redraw);
+static void ro_treeview_scroll(wimp_scroll *scroll);
+static void ro_treeview_redraw_loop(wimp_draw *redraw, ro_treeview *tv,
+ osbool more);
+static void ro_treeview_open(wimp_open *open);
+static bool ro_treeview_mouse_click(wimp_pointer *pointer);
+static void ro_treeview_pointer_entering(wimp_entering *entering);
+static void ro_treeview_drag_start(ro_treeview *tv, wimp_pointer *pointer,
+ wimp_window_state *state);
+static void ro_treeview_drag_end(wimp_dragged *drag, void *data);
+static bool ro_treeview_keypress(wimp_key *key);
+
+static void ro_treeview_set_window_extent(ro_treeview *tv,
+ int width, int height);
+
+static void ro_treeview_update_theme(void *data, bool ok);
+static void ro_treeview_update_toolbar(void *data);
+static void ro_treeview_button_update(void *data);
+static void ro_treeview_save_toolbar_buttons(void *data, char *config);
+static void ro_treeview_button_click(void *data,
+ toolbar_action_type action_type, union toolbar_action action);
+
+static const struct treeview_table ro_tree_callbacks = {
+ ro_treeview_redraw_request,
+ ro_treeview_resized,
+ ro_treeview_scroll_visible,
+ ro_treeview_get_window_dimensions
+};
+
+static const struct toolbar_callbacks ro_treeview_toolbar_callbacks = {
+ ro_treeview_update_theme,
+ ro_treeview_update_toolbar,
+ ro_treeview_button_update,
+ ro_treeview_button_click,
+ NULL, /* No toolbar keypress handler */
+ ro_treeview_save_toolbar_buttons
+};
+
+
+/**
+ * Create a RISC OS GUI implementation of a treeview tree.
+ *
+ * \param window The window to create the tree in.
+ * \param *toolbar A toolbar to attach to the window.
+ * \param *callbacks Callbacks to service the treeview.
+ * \param flags The treeview flags.
+ *
+ * \return The RISC OS treeview pointer.
+ */
+
+ro_treeview *ro_treeview_create(wimp_w window, struct toolbar *toolbar,
+ struct ro_treeview_callbacks *callbacks, unsigned int flags)
+{
+ ro_treeview *tv;
+
+ /* Claim memory for the treeview block, and create a tree. */
+
+ tv = malloc(sizeof(ro_treeview));
+ if (tv == NULL)
+ return NULL;
+
+ tv->w = window;
+ tv->tb = toolbar;
+
+ /* Set the tree redraw origin at a default 0,0 RO units. */
+
+ tv->origin.x = 0;
+ tv->origin.y = 0;
+
+ /* Set the tree size as 0,0 to indicate that we don't know. */
+
+ tv->size.x = 0;
+ tv->size.y = 0;
+
+ /* Set the tree window extent to 0,0, to indicate that we
+ * don't know. */
+
+ tv->extent.x = 0;
+ tv->extent.y = 0;
+
+ /* Set that there is no drag opperation at the moment */
+
+ tv->drag = TREE_NO_DRAG;
+
+ tv->tree = tree_create(flags, &ro_tree_callbacks, tv);
+ if (tv->tree == NULL) {
+ free(tv);
+ return NULL;
+ }
+
+ /* Record the callback info. */
+
+ tv->callbacks = callbacks;
+
+ /* Register wimp events to handle the supplied window. */
+
+ ro_gui_wimp_event_register_redraw_window(tv->w, ro_treeview_redraw);
+ ro_gui_wimp_event_register_scroll_window(tv->w, ro_treeview_scroll);
+ ro_gui_wimp_event_register_pointer_entering_window(tv->w,
+ ro_treeview_pointer_entering);
+ ro_gui_wimp_event_register_open_window(tv->w, ro_treeview_open);
+ ro_gui_wimp_event_register_mouse_click(tv->w, ro_treeview_mouse_click);
+ ro_gui_wimp_event_register_keypress(tv->w, ro_treeview_keypress);
+ ro_gui_wimp_event_set_user_data(tv->w, tv);
+
+ return tv;
+}
+
+/**
+ * Delete a RISC OS GUI implementation of a treeview tree. The window is
+ * *not* destroyed -- this must be done by the caller.
+ *
+ * \param tv The RISC OS treeview to delete.
+ */
+
+void ro_treeview_destroy(ro_treeview *tv)
+{
+ ro_gui_wimp_event_finalise(tv->w);
+
+ tree_delete(tv->tree);
+
+ free(tv);
+}
+
+/**
+ * Return a pointer to a toolbar callbacks structure with the handlers to be
+ * used by any treeview window toolbars.
+ *
+ * \return A pointer to the callback structure.
+ */
+
+const struct toolbar_callbacks *ro_treeview_get_toolbar_callbacks(void)
+{
+ return &ro_treeview_toolbar_callbacks;
+}
+
+/**
+ * Change the redraw origin of a treeview tree in RISC OS graphics units.
+ *
+ * \param *tv The ro_treeview object to update.
+ * \param x The X position, in terms of the RO window work area.
+ * \param y The Y position, in terms of the RO window work area.
+ *
+ * \todo -- this probably needs a rework.
+ */
+
+void ro_treeview_set_origin(ro_treeview *tv, int x, int y)
+{
+ if (tv != NULL) {
+ tv->origin.x = x;
+ tv->origin.y = y;
+
+ /* Assuming that we know how big the tree currently is, then
+ * adjust the window work area extent to match. If we don't,
+ * then presumably the tree isn't in an open window yet and
+ * a subsequent Open Window Event should pick it up.
+ */
+
+ if (tv->size.x != 0 && tv->size.y != 0)
+ ro_treeview_set_window_extent(tv,
+ tv->origin.x + tv->size.x,
+ tv->origin.y + tv->size.y);
+ }
+}
+
+/**
+ * Return details of the tree block associated with an ro_treeview object.
+ *
+ * \param *tv The ro_treeview object of interest.
+ * \return A pointer to the associated tree block.
+ */
+
+struct tree *ro_treeview_get_tree(ro_treeview *tv)
+{
+ return (tv != NULL) ? (tv->tree) : (NULL);
+}
+
+/**
+ * Return details of the RISC OS window handle associated with an
+ * ro_treeview object.
+ *
+ * \param *tv The ro_treeview object of interest.
+ * \return The associated RISC OS window handle.
+ */
+
+wimp_w ro_treeview_get_window(ro_treeview *tv)
+{
+ return (tv != NULL) ? (tv->w) : (NULL);
+}
+
+/**
+ * Callback to force a redraw of part of the treeview window.
+ *
+ * \param x Min X Coordinate of area to be redrawn.
+ * \param y Min Y Coordinate of area to be redrawn.
+ * \param width Width of area to be redrawn.
+ * \param height Height of area to be redrawn.
+ * \param pw The treeview object to be redrawn.
+ */
+
+void ro_treeview_redraw_request(int x, int y, int width, int height,
+ void *pw)
+{
+ if (pw != NULL) {
+ ro_treeview *tv = (ro_treeview *) pw;
+ os_error *error;
+ wimp_draw update;
+ osbool more;
+
+ update.w = tv->w;
+ update.box.x0 = (2 * x) + tv->origin.x;
+ update.box.y0 = (-2 * (y + height)) + tv->origin.y;
+ update.box.x1 = (2 * (x + width)) + tv->origin.x;
+ update.box.y1 = (-2 * y) + tv->origin.y;
+
+ error = xwimp_update_window(&update, &more);
+ if (error) {
+ LOG("xwimp_update_window: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+ ro_treeview_redraw_loop(&update, tv, more);
+ }
+}
+
+/**
+ * Pass RISC OS redraw events on to the treeview widget.
+ *
+ * \param *redraw Pointer to Redraw Event block.
+ */
+
+void ro_treeview_redraw(wimp_draw *redraw)
+{
+ osbool more;
+ os_error *error;
+ ro_treeview *tv;
+
+ tv = (ro_treeview *) ro_gui_wimp_event_get_user_data(redraw->w);
+ if (tv == NULL) {
+ LOG("NULL treeview block for window: 0x%x", (unsigned int)redraw->w);
+ /* Don't return, as not servicing redraw events isn't a good
+ * idea. The following code must handle (tv == NULL)
+ * gracefully while clearing the redraw queue.
+ */
+ }
+
+ error = xwimp_redraw_window(redraw, &more);
+ if (error) {
+ LOG("xwimp_redraw_window: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ ro_treeview_redraw_loop(redraw, tv, more);
+}
+
+/**
+ * Handle scroll events in treeview windows.
+ *
+ * \param *scroll Pointer to Scroll Event block.
+ */
+
+void ro_treeview_scroll(wimp_scroll *scroll)
+{
+ os_error *error;
+ int x = scroll->visible.x1 - scroll->visible.x0 - 32;
+ int y = scroll->visible.y1 - scroll->visible.y0 - 32;
+ ro_treeview *tv;
+
+ tv = (ro_treeview *) ro_gui_wimp_event_get_user_data(scroll->w);
+ if (tv == NULL)
+ return;
+
+ if (tv->tb != NULL)
+ y -= ro_toolbar_full_height(tv->tb);
+
+ switch (scroll->xmin) {
+ case wimp_SCROLL_PAGE_LEFT:
+ scroll->xscroll -= x;
+ break;
+ case wimp_SCROLL_COLUMN_LEFT:
+ scroll->xscroll -= 32;
+ break;
+ case wimp_SCROLL_COLUMN_RIGHT:
+ scroll->xscroll += 32;
+ break;
+ case wimp_SCROLL_PAGE_RIGHT:
+ scroll->xscroll += x;
+ break;
+ default:
+ scroll->xscroll += (x * (scroll->xmin>>2)) >> 2;
+ break;
+ }
+
+ switch (scroll->ymin) {
+ case wimp_SCROLL_PAGE_UP:
+ scroll->yscroll += y;
+ break;
+ case wimp_SCROLL_LINE_UP:
+ scroll->yscroll += 32;
+ break;
+ case wimp_SCROLL_LINE_DOWN:
+ scroll->yscroll -= 32;
+ break;
+ case wimp_SCROLL_PAGE_DOWN:
+ scroll->yscroll -= y;
+ break;
+ default:
+ scroll->yscroll += (y * (scroll->ymin>>2)) >> 2;
+ break;
+ }
+
+ error = xwimp_open_window((wimp_open *) scroll);
+ if (error) {
+ LOG("xwimp_open_window: 0x%x: %s", error->errnum, error->errmess);
+ }
+}
+
+
+/**
+ * Redraw a treeview window, once the initial readraw block has been collected.
+ *
+ * /param *redraw Pointer to redraw block.
+ * /param *tv The treeview object being redrawn.
+ * /param more Flag to show if more actions are required.
+ */
+
+void ro_treeview_redraw_loop(wimp_draw *redraw, ro_treeview *tv, osbool more)
+{
+ struct redraw_context ctx = {
+ .interactive = true,
+ .background_images = true,
+ .plot = &ro_plotters
+ };
+
+ while (more) {
+ os_error *error;
+
+ if (tv != NULL && tv->tree != NULL) {
+ struct rect clip;
+
+ ro_plot_origin_x = redraw->box.x0 + tv->origin.x -
+ redraw->xscroll;
+ ro_plot_origin_y = redraw->box.y1 + tv->origin.y -
+ redraw->yscroll;
+
+ clip.x0 = (redraw->clip.x0 - ro_plot_origin_x) / 2;
+ clip.y0 = (ro_plot_origin_y - redraw->clip.y1) / 2;
+
+ /* Treeview text alwyas has flat background colour,
+ * so disable unnecessary background blending */
+ no_font_blending = true;
+ tree_draw(tv->tree, 0, 0,
+ clip.x0, clip.y0,
+ (redraw->clip.x1 - redraw->clip.x0)/2,
+ (redraw->clip.y1 - redraw->clip.y0)/2,
+ &ctx);
+ no_font_blending = false;
+ }
+
+ error = xwimp_get_rectangle(redraw, &more);
+ if (error) {
+ LOG("xwimp_redraw_window: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+ }
+}
+
+/**
+ * Callback to notify us of a new overall tree size.
+ *
+ * \param tree The tree being resized.
+ * \param width The new width of the window.
+ * \param height The new height of the window.
+ * \param *pw The treeview object to be resized.
+ */
+
+void ro_treeview_resized(struct tree *tree, int width, int height,
+ void *pw)
+{
+ if (pw != NULL) {
+ ro_treeview *tv = (ro_treeview *) pw;
+
+ /* Store the width and height in terms of RISC OS work area. */
+
+ tv->size.x = width * 2;
+ tv->size.y = -(height * 2);
+
+ /* Resize the window. */
+
+ ro_treeview_set_window_extent(tv, tv->size.x, tv->size.y);
+ }
+}
+
+/**
+ * Callback to request that a section of the tree is scrolled into view.
+ *
+ * \param y The Y coordinate of top of the area in NS units.
+ * \param height The height of the area in NS units.
+ * \param *pw The treeview object affected.
+ */
+
+void ro_treeview_scroll_visible(int y, int height, void *pw)
+{
+ if (pw != NULL) {
+ ro_treeview *tv = (ro_treeview *) pw;
+ os_error *error;
+ wimp_window_state state;
+ int visible_t, visible_b;
+ int request_t, request_b;
+
+ state.w = tv->w;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ /* Work out top and bottom of both the currently visible and
+ * the required areas, in terms of the RO work area.
+ */
+
+ visible_t = state.yscroll;
+ visible_b = state.yscroll
+ - (state.visible.y1 - state.visible.y0);
+
+ request_t = -(2 * y);// - tv->origin.y;
+ request_b = -(2 * (y + height));// - tv->origin.y;
+
+ /* If the area is outside the visible window, then scroll it
+ * in to view.
+ */
+
+ if (request_t > visible_t || request_b < visible_b) {
+ if (request_t > visible_t) {
+ state.yscroll = request_t;
+ } else if (request_b < visible_b) {
+ state.yscroll = request_b + tv->origin.y
+ + (state.visible.y1 - state.visible.y0);
+
+ /* If the required area is bigger than the
+ * visible extent, then align to the top and
+ * let the bottom disappear out of view.
+ */
+
+ if (state.yscroll < request_t)
+ state.yscroll = request_t;
+ }
+
+ error = xwimp_open_window((wimp_open *) &state);
+ if (error) {
+ LOG("xwimp_open_window: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+ }
+ }
+}
+
+/**
+ * Callback to return the tree window dimensions to the treeview system.
+ *
+ * \param *width Return the window width.
+ * \param *height Return the window height.
+ * \param *pw The treeview object to use.
+ */
+
+void ro_treeview_get_window_dimensions(int *width, int *height,
+ void *pw)
+{
+ if (pw != NULL && (width != NULL || height != NULL)) {
+ ro_treeview *tv = (ro_treeview *) pw;
+ os_error *error;
+ wimp_window_state state;
+
+ state.w = tv->w;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ if (width != NULL)
+ *width = (state.visible.x1 - state.visible.x0) / 2;
+
+ if (height != NULL)
+ *height = (state.visible.y1 - state.visible.y0) / 2;
+ }
+}
+
+/**
+ * Resize the RISC OS window extent of a treeview.
+ *
+ * \param *tv The RISC OS treeview object to resize.
+ * \param width The new width of the work area, in RO units.
+ * \param height The new height of the work area, in RO units.
+ */
+
+void ro_treeview_set_window_extent(ro_treeview *tv, int width, int height)
+{
+ if (tv != NULL) {
+ os_error *error;
+ os_box extent;
+ wimp_window_state state;
+ int new_x, new_y;
+ int visible_x, visible_y;
+
+ /* Calculate the new window extents, in RISC OS units. */
+
+ new_x = width + tv->origin.x;
+ new_y = height + tv->origin.y;
+
+ /* Get details of the existing window, and start to sanity
+ * check the new extents.
+ */
+
+ state.w = tv->w;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ /* If the extent is smaller than the current visible area,
+ * then extend it so that it matches the visible area.
+ */
+
+ if (new_x < (state.visible.x1 - state.visible.x0))
+ new_x = state.visible.x1 - state.visible.x0;
+
+ if (new_y > (state.visible.y0 - state.visible.y1))
+ new_y = state.visible.y0 - state.visible.y1;
+
+ /* Calculate the maximum visible coordinates of the existing
+ * window.
+ */
+
+ visible_x = state.xscroll +
+ (state.visible.x1 - state.visible.x0);
+ visible_y = state.yscroll +
+ (state.visible.y0 - state.visible.y1);
+
+ /* If the window is currently open, and the exising visible
+ * area is bigger than the new extent, then we need to reopen
+ * the window in an appropriare position before setting the
+ * new extent.
+ */
+
+ if ((state.flags & wimp_WINDOW_OPEN) &&
+ (visible_x > new_x || visible_y < new_y)) {
+ int new_x_scroll = state.xscroll;
+ int new_y_scroll = state.yscroll;
+
+ if (visible_x > new_x)
+ new_x_scroll = new_x - (state.visible.x1
+ - state.visible.x0);
+
+ if (visible_y < new_y)
+ new_y_scroll = new_y - (state.visible.y0
+ - state.visible.y1);
+
+ if (new_x_scroll < 0) {
+ state.visible.x1 -= new_x_scroll;
+ state.xscroll = 0;
+ } else {
+ state.xscroll = new_x_scroll;
+ }
+
+ if (new_y_scroll > 0) {
+ state.visible.y0 += new_y_scroll;
+ state.yscroll = 0;
+ } else {
+ state.yscroll = new_y_scroll;
+ }
+
+ error = xwimp_open_window((wimp_open *) &state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ /* \todo -- Not sure if we need to reattach the
+ * toolbar here: the nested wimp seems to take care
+ * of it for us?
+ */
+ }
+
+ /* Now that the new extent fits into the visible window, we
+ * can resize the work area. If we succeed, the values are
+ * recorded to save having to ask the Wimp for them
+ * each time.
+ */
+
+ extent.x0 = 0;
+ extent.y0 = new_y;
+ extent.x1 = new_x;
+ extent.y1 = 0;
+
+ error = xwimp_set_extent(tv->w, &extent);
+ if (error) {
+ LOG("xwimp_set_extent: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ tv->extent.x = new_x;
+ tv->extent.y = new_y;
+ }
+}
+
+/**
+ * Handle RISC OS Window Open events for a treeview window.
+ *
+ * \param *open Pointer to the Window Open Event block.
+ */
+
+static void ro_treeview_open(wimp_open *open)
+{
+ ro_treeview *tv;
+ os_error *error;
+ os_box extent;
+ int width, height;
+
+ tv = (ro_treeview *) ro_gui_wimp_event_get_user_data(open->w);
+ if (tv == NULL) {
+ LOG("NULL treeview block for window: ox%x", (unsigned int)open->w);
+ return;
+ }
+
+ /* Calculate the window work area. It must be at least the same as
+ * the current visible area of the window, and needs to contain the
+ * tree as defined by size.x + offset.x and size.y + offset.y (note
+ * that the offset.y should be set to cover any toolbar, so we can
+ * ignore the size of that).
+ */
+
+ width = open->visible.x1 - open->visible.x0;
+ height = open->visible.y0 - open->visible.y1;
+
+ if (tv->size.x != 0 && width < (tv->origin.x + tv->size.x))
+ width = (tv->origin.x + tv->size.x);
+
+ if (tv->size.y != 0 && height > (tv->size.y + tv->origin.y))
+ height = (tv->size.y + tv->origin.y);
+
+ if (width != tv->extent.x || height != tv->extent.y) {
+ extent.x0 = 0;
+ extent.y0 = height;
+ extent.x1 = width;
+ extent.y1 = 0;
+
+ error = xwimp_set_extent(tv->w, &extent);
+ if (error) {
+ LOG("xwimp_set_extent: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ tv->extent.x = width;
+ tv->extent.y = height;
+ }
+
+ /* \todo -- Might need to add vertical scrollbar hiding back in here? */
+
+ error = xwimp_open_window(open);
+ if (error) {
+ LOG("xwimp_open_window: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+
+ if (tv->tb)
+ ro_toolbar_process(tv->tb, -1, false);
+}
+
+
+/**
+ * Pass RISC OS Mouse Click events on to the treeview widget.
+ *
+ * \param *pointer Pointer to the Mouse Click Event block.
+ * \return Return true if click handled; else false.
+ */
+
+static bool ro_treeview_mouse_click(wimp_pointer *pointer)
+{
+ os_error *error;
+ ro_treeview *tv;
+ wimp_window_state state;
+ int xpos, ypos;
+ browser_mouse_state mouse;
+ bool handled = false;
+
+ tv = (ro_treeview *) ro_gui_wimp_event_get_user_data(pointer->w);
+ if (tv == NULL) {
+ LOG("NULL treeview block for window: 0x%x", (unsigned int)pointer->w);
+ return false;
+ }
+
+ state.w = tv->w;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return false;
+ }
+
+ /* Convert the returned mouse coordinates into NetSurf's internal
+ * units.
+ */
+
+ xpos = ((pointer->pos.x - state.visible.x0) +
+ state.xscroll - tv->origin.x) / 2;
+ ypos = ((state.visible.y1 - pointer->pos.y) -
+ state.yscroll + tv->origin.y) / 2;
+
+ /* Start to process the mouse click.
+ *
+ * Select and Adjust are processed normally. To get filer-like operation
+ * with selections, Menu clicks are passed to the treeview first as
+ * Select if there are no selected nodes in the tree.
+ */
+
+ mouse = 0;
+
+ if (pointer->buttons == wimp_CLICK_MENU) {
+ /* TODO: test for no selection, and pass click to select node */
+ /* mouse |= BROWSER_MOUSE_CLICK_1; */
+ } else {
+ mouse = ro_gui_mouse_click_state(pointer->buttons,
+ wimp_BUTTON_DOUBLE_CLICK_DRAG);
+
+ /* Give the window input focus on Select-clicks. This wouldn't
+ * be necessary if the core used the RISC OS caret.
+ */
+
+ if (mouse & BROWSER_MOUSE_CLICK_1)
+ xwimp_set_caret_position(tv->w, -1, -100, -100, 32, -1);
+ }
+
+ if (mouse != 0) {
+ handled = tree_mouse_action(tv->tree, mouse, xpos, ypos);
+
+ tv->drag = tree_drag_status(tv->tree);
+ if (tv->drag != TREE_NO_DRAG) {
+ tv->drag_start.x = xpos;
+ tv->drag_start.y = ypos;
+ }
+
+ /* If it's a visible drag, start the RO side of the visible
+ * effects.
+ */
+
+ if (tv->drag == TREE_SELECT_DRAG ||
+ tv->drag == TREE_MOVE_DRAG)
+ ro_treeview_drag_start(tv, pointer, &state);
+
+
+ if (tv->callbacks != NULL &&
+ tv->callbacks->toolbar_button_update != NULL)
+ tv->callbacks->toolbar_button_update();
+ }
+
+ /* Special actions for some mouse buttons. Adjust closes the dialog;
+ * Menu opens a menu. For the latter, we assume that the owning module
+ * will have attached a window menu to our parent window with the auto
+ * flag unset (so that we can fudge the selection above). If it hasn't,
+ * the call will quietly fail.
+ *
+ * \TODO -- Adjust-click close isn't a perfect copy of what the RO
+ * version did: adjust clicks anywhere close the tree, and
+ * selections persist.
+ */
+
+ switch(pointer->buttons) {
+ case wimp_CLICK_ADJUST:
+ if (handled)
+ ro_gui_dialog_close(tv->w);
+ break;
+
+ case wimp_CLICK_MENU:
+ ro_gui_wimp_event_process_window_menu_click(pointer);
+ break;
+ }
+
+ return true;
+}
+
+
+/**
+ * Handle Pointer Entering Window events for treeview windows.
+ *
+ * \param *entering The Wimp_PointerEnteringWindow block.
+ */
+
+void ro_treeview_pointer_entering(wimp_entering *entering)
+{
+ ro_treeview *tv;
+
+ tv = (ro_treeview *) ro_gui_wimp_event_get_user_data(entering->w);
+ if (tv == NULL)
+ return;
+
+ ro_mouse_track_start(NULL, ro_treeview_mouse_at, NULL);
+}
+
+/**
+ * Track the mouse under Null Polls from the wimp, to support dragging.
+ *
+ * \param *pointer Pointer to a Wimp Pointer block.
+ * \param *data NULL to allow use as a ro_mouse callback.
+ */
+
+void ro_treeview_mouse_at(wimp_pointer *pointer, void *data)
+{
+ os_error *error;
+ ro_treeview *tv;
+ wimp_window_state state;
+ int xpos, ypos;
+ browser_mouse_state mouse;
+
+ if (pointer->buttons & (wimp_CLICK_MENU))
+ return;
+
+ tv = (ro_treeview *) ro_gui_wimp_event_get_user_data(pointer->w);
+ if (tv == NULL) {
+ LOG("NULL treeview block for window: 0x%x", (unsigned int)pointer->w);
+ return;
+ }
+
+ if (tv->drag == TREE_NO_DRAG)
+ return;
+
+ /* We know now that it's not a Menu click and the treeview thinks
+ * that a drag is in progress.
+ */
+
+ state.w = tv->w;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ /* Convert the returned mouse coordinates into NetSurf's internal
+ * units.
+ */
+
+ xpos = ((pointer->pos.x - state.visible.x0) +
+ state.xscroll - tv->origin.x) / 2;
+ ypos = ((state.visible.y1 - pointer->pos.y) -
+ state.yscroll + tv->origin.y) / 2;
+
+ /* Start to process the mouse click. */
+
+ mouse = ro_gui_mouse_drag_state(pointer->buttons,
+ wimp_BUTTON_DOUBLE_CLICK_DRAG);
+
+ tree_mouse_action(tv->tree, mouse, xpos, ypos);
+
+ if (!(mouse & BROWSER_MOUSE_DRAG_ON)) {
+ tree_drag_end(tv->tree, mouse, tv->drag_start.x,
+ tv->drag_start.y, xpos, ypos);
+ tv->drag = TREE_NO_DRAG;
+ }
+
+ if (tv->callbacks != NULL &&
+ tv->callbacks->toolbar_button_update != NULL)
+ tv->callbacks->toolbar_button_update();
+}
+
+
+/**
+ * Start a RISC OS drag event to reflect on screen what is happening
+ * during the core tree drag.
+ *
+ * \param *tv The RO treeview to which the drag is attached.
+ * \param *pointer The RO pointer event data block starting the drag.
+ * \param *state The RO window state block for the treeview window.
+ */
+
+static void ro_treeview_drag_start(ro_treeview *tv, wimp_pointer *pointer,
+ wimp_window_state *state)
+{
+ os_error *error;
+ wimp_drag drag;
+ wimp_auto_scroll_info auto_scroll;
+
+ drag.w = tv->w;
+ drag.bbox.x0 = state->visible.x0;
+ drag.bbox.y0 = state->visible.y0;
+ drag.bbox.x1 = state->visible.x1;
+ drag.bbox.y1 = state->visible.y1 - ro_toolbar_height(tv->tb) - 2;
+
+ switch (tv->drag) {
+ case TREE_SELECT_DRAG:
+ drag.type = wimp_DRAG_USER_RUBBER;
+
+ drag.initial.x0 = pointer->pos.x;
+ drag.initial.y0 = pointer->pos.y;
+ drag.initial.x1 = pointer->pos.x;
+ drag.initial.y1 = pointer->pos.y;
+ break;
+
+ case TREE_MOVE_DRAG:
+ drag.type = wimp_DRAG_USER_POINT;
+
+ drag.initial.x0 = pointer->pos.x - 4;
+ drag.initial.y0 = pointer->pos.y - 48;
+ drag.initial.x1 = pointer->pos.x + 48;
+ drag.initial.y1 = pointer->pos.y + 4;
+ break;
+
+ default:
+ /* No other drag types are supported. */
+ break;
+ }
+
+ LOG("Drag start...");
+
+ error = xwimp_drag_box_with_flags(&drag,
+ wimp_DRAG_BOX_KEEP_IN_LINE | wimp_DRAG_BOX_CLIP);
+ if (error) {
+ LOG("xwimp_drag_box: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ } else {
+ auto_scroll.w = tv->w;
+ auto_scroll.pause_zone_sizes.x0 = 80;
+ auto_scroll.pause_zone_sizes.y0 = 80;
+ auto_scroll.pause_zone_sizes.x1 = 80;
+ auto_scroll.pause_zone_sizes.y1 = 80 +
+ ro_toolbar_height(tv->tb);
+ auto_scroll.pause_duration = 0;
+ auto_scroll.state_change = (void *) 1;
+
+ error = xwimp_auto_scroll(wimp_AUTO_SCROLL_ENABLE_VERTICAL,
+ &auto_scroll, NULL);
+ if (error) {
+ LOG("xwimp_auto_scroll: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+
+ ro_mouse_drag_start(ro_treeview_drag_end, ro_treeview_mouse_at,
+ NULL, NULL);
+ }
+}
+
+
+/**
+ * Process RISC OS User Drag Box events which relate to us: in effect, drags
+ * started by ro_treeview_drag_start().
+ *
+ * \param *drag Pointer to the User Drag Box Event block.
+ * \param *data NULL to allow use as a ro_mouse callback.
+ */
+
+static void ro_treeview_drag_end(wimp_dragged *drag, void *data)
+{
+ os_error *error;
+
+ error = xwimp_drag_box((wimp_drag *) -1);
+ if (error) {
+ LOG("xwimp_drag_box: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+
+ error = xwimp_auto_scroll(0, NULL, NULL);
+ if (error) {
+ LOG("xwimp_auto_scroll: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+}
+
+
+/**
+ * Pass RISC OS keypress events on to the treeview widget.
+ *
+ * \param *key Pointer to the Key Pressed Event block.
+ * \return Return true if keypress handled; else false.
+ */
+
+static bool ro_treeview_keypress(wimp_key *key)
+{
+ ro_treeview *tv;
+ uint32_t c;
+
+ tv = (ro_treeview *) ro_gui_wimp_event_get_user_data(key->w);
+ if (tv == NULL) {
+ LOG("NULL treeview block for window: 0x%x", (unsigned int)key->w);
+ return false;
+ }
+
+ c = (uint32_t) key->c;
+
+ if ((unsigned)c < 0x20 || (0x7f <= c && c <= 0x9f) ||
+ (c & IS_WIMP_KEY)) {
+ /* Munge control keys into unused control chars */
+ /* We can't map onto 1->26 (reserved for ctrl+<qwerty>
+ That leaves 27->31 and 128->159 */
+ switch (c & ~IS_WIMP_KEY) {
+ case wimp_KEY_TAB: c = 9; break;
+ case wimp_KEY_SHIFT | wimp_KEY_TAB: c = 11; break;
+
+ /* cursor movement keys */
+ case wimp_KEY_HOME:
+ case wimp_KEY_CONTROL | wimp_KEY_LEFT:
+ c = NS_KEY_LINE_START;
+ break;
+ case wimp_KEY_END:
+ if (os_version >= RISCOS5)
+ c = NS_KEY_LINE_END;
+ else
+ c = NS_KEY_DELETE_RIGHT;
+ break;
+ case wimp_KEY_CONTROL | wimp_KEY_RIGHT: c = NS_KEY_LINE_END; break;
+ case wimp_KEY_CONTROL | wimp_KEY_UP: c = NS_KEY_TEXT_START; break;
+ case wimp_KEY_CONTROL | wimp_KEY_DOWN: c = NS_KEY_TEXT_END; break;
+ case wimp_KEY_SHIFT | wimp_KEY_LEFT: c = NS_KEY_WORD_LEFT ; break;
+ case wimp_KEY_SHIFT | wimp_KEY_RIGHT: c = NS_KEY_WORD_RIGHT; break;
+ case wimp_KEY_SHIFT | wimp_KEY_UP: c = NS_KEY_PAGE_UP; break;
+ case wimp_KEY_SHIFT | wimp_KEY_DOWN: c = NS_KEY_PAGE_DOWN; break;
+ case wimp_KEY_LEFT: c = NS_KEY_LEFT; break;
+ case wimp_KEY_RIGHT: c = NS_KEY_RIGHT; break;
+ case wimp_KEY_UP: c = NS_KEY_UP; break;
+ case wimp_KEY_DOWN: c = NS_KEY_DOWN; break;
+
+ /* editing */
+ case wimp_KEY_CONTROL | wimp_KEY_END:
+ c = NS_KEY_DELETE_LINE_END;
+ break;
+ case wimp_KEY_DELETE:
+ if (ro_gui_ctrl_pressed())
+ c = NS_KEY_DELETE_LINE_START;
+ else if (os_version < RISCOS5)
+ c = NS_KEY_DELETE_LEFT;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (!(c & IS_WIMP_KEY)) {
+ if (tree_keypress(tv->tree, c)) {
+ if (tv->callbacks &&
+ tv->callbacks->toolbar_button_update
+ != NULL)
+ tv->callbacks->toolbar_button_update();
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+/**
+ * Update a treeview to use a new theme.
+ *
+ * \param *data Pointer to the treeview to update.
+ * \param ok true if the bar still exists; else false.
+ */
+
+void ro_treeview_update_theme(void *data, bool ok)
+{
+ ro_treeview *tv = (ro_treeview *) data;
+
+ if (tv != NULL && tv->tb != NULL){
+ if (ok) {
+ ro_treeview_update_toolbar(tv);
+ } else {
+ tv->tb = NULL;
+ }
+ }
+}
+
+
+/**
+ * Change the size of a treeview's toolbar and redraw the window.
+ *
+ * \param *data The treeview to update.
+ */
+
+void ro_treeview_update_toolbar(void *data)
+{
+ ro_treeview *tv = (ro_treeview *) data;
+
+ if (tv != NULL && tv->tb != NULL) {
+ ro_treeview_set_origin(tv, 0,
+ -(ro_toolbar_height(tv->tb)));
+
+ xwimp_force_redraw(tv->w, 0, tv->extent.y, tv->extent.x, 0);
+ }
+}
+
+
+/**
+ * Update the toolbar icons in a treeview window's toolbar. As we're just
+ * an intermediate widget, we pass the details on down the chain.
+ *
+ * \param *data The treeview owning the toolbar.
+ */
+
+void ro_treeview_button_update(void *data)
+{
+ ro_treeview *tv = (ro_treeview *) data;
+
+ if (tv == NULL || tv->callbacks == NULL)
+ return;
+
+ if (tv->callbacks->toolbar_button_update != NULL)
+ tv->callbacks->toolbar_button_update();
+}
+
+
+/**
+ * Save a new button configuration from a treeview window's toolbar. As
+ * we're just an intermediate widget, we pass the details on.
+ *
+ * \param *data The treeview owning the toolbar.
+ * \param *config The new button config string.
+ */
+
+void ro_treeview_save_toolbar_buttons(void *data, char *config)
+{
+ ro_treeview *tv = (ro_treeview *) data;
+
+ if (tv == NULL || tv->callbacks == NULL)
+ return;
+
+ if (tv->callbacks->toolbar_button_save != NULL)
+ tv->callbacks->toolbar_button_save(config);
+}
+
+
+/**
+ * Process clicks on buttons in a treeview window's toolbar. As we're just
+ * an intermediate widget, we just pass the details on down the chain.
+ *
+ * \param *data The treeview owning the click.
+ * \param action_type The action type to be handled.
+ * \param action The action to handle.
+ */
+
+void ro_treeview_button_click(void *data,
+ toolbar_action_type action_type, union toolbar_action action)
+{
+ ro_treeview *tv = (ro_treeview *) data;
+
+ if (tv == NULL || tv->callbacks == NULL ||
+ action_type != TOOLBAR_ACTION_BUTTON)
+ return;
+
+ if (tv->callbacks->toolbar_button_click != NULL)
+ tv->callbacks->toolbar_button_click(action.button);
+
+ if (tv->callbacks->toolbar_button_update != NULL)
+ tv->callbacks->toolbar_button_update();
+}
+
+
+/**
+ * Return a token identifying the interactive help message for a given cursor
+ * position.
+ *
+ * Currently this is inimplemented.
+ *
+ * \param *message_data Pointer to the Wimp's help message block.
+ * \return Token value (-1 indicates no help available).
+ */
+
+int ro_treeview_get_help(help_full_message_request *message_data)
+{
+ return -1;
+}
+
diff --git a/frontends/riscos/treeview.h b/frontends/riscos/treeview.h
new file mode 100644
index 000000000..80ff7660f
--- /dev/null
+++ b/frontends/riscos/treeview.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2004 Richard Wilson <not_ginger_matt@users.sourceforge.net>
+ * Copyright 2010 Stephen Fryatt <stevef@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Generic tree handling (interface).
+ */
+
+#ifndef _NETSURF_RISCOS_TREEVIEW_H_
+#define _NETSURF_RISCOS_TREEVIEW_H_
+
+#include <stdbool.h>
+#include <oslib/help.h>
+#include <oslib/wimp.h>
+
+#include "desktop/tree.h"
+#include "riscos/toolbar.h"
+
+typedef struct ro_treeview ro_treeview;
+
+struct ro_treeview_callbacks {
+ void (*toolbar_button_click)(button_bar_action action);
+ void (*toolbar_button_update)(void);
+ void (*toolbar_button_save)(char *);
+};
+
+ro_treeview *ro_treeview_create(wimp_w window, struct toolbar *toolbar,
+ struct ro_treeview_callbacks *callbacks, unsigned int flags);
+void ro_treeview_destroy(ro_treeview *tv);
+const struct toolbar_callbacks *ro_treeview_get_toolbar_callbacks(void);
+
+struct tree *ro_treeview_get_tree(ro_treeview *tv);
+wimp_w ro_treeview_get_window(ro_treeview *tv);
+
+void ro_treeview_set_origin(ro_treeview *tv, int x, int y);
+void ro_treeview_mouse_at(wimp_pointer *pointer, void *data);
+int ro_treeview_get_help(help_full_message_request *message_data);
+
+#endif
+
diff --git a/frontends/riscos/ucstables.c b/frontends/riscos/ucstables.c
new file mode 100644
index 000000000..7ac685df2
--- /dev/null
+++ b/frontends/riscos/ucstables.c
@@ -0,0 +1,697 @@
+/*
+ * Copyright 2005 John M Bell <jmb202@ecs.soton.ac.uk>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * UCS conversion tables and RISC OS-specific UTF-8 text handling
+ */
+
+#include <assert.h>
+#include <limits.h>
+#include <string.h>
+#include <stdlib.h>
+#include <oslib/osbyte.h>
+#include <oslib/territory.h>
+
+#include "utils/config.h"
+#include "utils/errors.h"
+#include "utils/log.h"
+#include "utils/utf8.h"
+#include "utils/utils.h"
+#include "desktop/gui_utf8.h"
+
+#include "riscos/ucstables.h"
+
+/* Common values (ASCII) */
+#define common \
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, \
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, \
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, \
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, \
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, \
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, \
+ 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, \
+ 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127 \
+
+/* 0x8c->0x9F, used by many of the encodings */
+#define common2 \
+ 0x2026, 0x2122, 0x2030, 0x2022, 0x2018, 0x2019, 0x2039, 0x203a, \
+ 0x201c, 0x201d, 0x201e, 0x2013, 0x2014, 0x2212, 0x0152, 0x0153, \
+ 0x2020, 0x2021, 0xfb01, 0xfb02
+
+static const int latin1_table[256] =
+{
+ common,
+ 0x20ac, 0x0174, 0x0175, -1, -1, 0x0176, 0x0177, -1, -1, -1, -1, -1,
+ common2,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+static const int latin2_table[256] =
+{
+ common,
+ 0x20ac, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ common2,
+ 0x00A0, 0x0104, 0x02D8, 0x0141, 0x00A4, 0x013D, 0x015A, 0x00A7,
+ 0x00A8, 0x0160, 0x015E, 0x0164, 0x0179, 0x00AD, 0x017D, 0x017B,
+ 0x00B0, 0x0105, 0x02DB, 0x0142, 0x00B4, 0x013E, 0x015B, 0x02C7,
+ 0x00B8, 0x0161, 0x015F, 0x0165, 0x017A, 0x02DD, 0x017E, 0x017C,
+ 0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7,
+ 0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E,
+ 0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7,
+ 0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF,
+ 0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7,
+ 0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F,
+ 0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7,
+ 0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9
+};
+
+static const int latin3_table[256] =
+{
+ common,
+ 0x20ac, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ common2,
+ 0x00A0, 0x0126, 0x02D8, 0x00A3, 0x00A4, -1, 0x0124, 0x00A7,
+ 0x00A8, 0x0130, 0x015E, 0x011E, 0x0134, 0x00AD, -1, 0x017B,
+ 0x00B0, 0x0127, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x0125, 0x00B7,
+ 0x00B8, 0x0131, 0x015F, 0x011F, 0x0135, 0x00BD, -1, 0x017C,
+ 0x00C0, 0x00C1, 0x00C2, -1, 0x00C4, 0x010A, 0x0108, 0x00C7,
+ 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+ -1, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x0120, 0x00D6, 0x00D7,
+ 0x011C, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x016C, 0x015C, 0x00DF,
+ 0x00E0, 0x00E1, 0x00E2, -1, 0x00E4, 0x010B, 0x0109, 0x00E7,
+ 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+ -1, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x0121, 0x00F6, 0x00F7,
+ 0x011D, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x016D, 0x015D, 0x02D9
+};
+
+static const int latin4_table[256] =
+{
+ common,
+ 0x20ac, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ common2,
+ 0x00A0, 0x0104, 0x0138, 0x0156, 0x00A4, 0x0128, 0x013B, 0x00A7,
+ 0x00A8, 0x0160, 0x0112, 0x0122, 0x0166, 0x00AD, 0x017D, 0x00AF,
+ 0x00B0, 0x0105, 0x02DB, 0x0157, 0x00B4, 0x0129, 0x013C, 0x02C7,
+ 0x00B8, 0x0161, 0x0113, 0x0123, 0x0167, 0x014A, 0x017E, 0x014B,
+ 0x0100, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E,
+ 0x010C, 0x00C9, 0x0118, 0x00CB, 0x0116, 0x00CD, 0x00CE, 0x012A,
+ 0x0110, 0x0145, 0x014C, 0x0136, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
+ 0x00D8, 0x0172, 0x00DA, 0x00DB, 0x00DC, 0x0168, 0x016A, 0x00DF,
+ 0x0101, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x012F,
+ 0x010D, 0x00E9, 0x0119, 0x00EB, 0x0117, 0x00ED, 0x00EE, 0x012B,
+ 0x0111, 0x0146, 0x014D, 0x0137, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
+ 0x00F8, 0x0173, 0x00FA, 0x00FB, 0x00FC, 0x0169, 0x016B, 0x02D9
+};
+
+static const int latin5_table[256] =
+{
+ common,
+ 0x20ac, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ common2,
+ 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
+ 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+ 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
+ 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
+ 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+ 0x011E, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
+ 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0130, 0x015E, 0x00DF,
+ 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
+ 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+ 0x011F, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
+ 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0131, 0x015F, 0x00FF
+};
+
+static const int latin6_table[256] =
+{
+ common,
+ 0x20ac, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ common2,
+ 0x00A0, 0x0104, 0x0112, 0x0122, 0x012A, 0x0128, 0x0136, 0x00A7,
+ 0x013B, 0x0110, 0x0160, 0x0166, 0x017D, 0x00AD, 0x016A, 0x014A,
+ 0x00B0, 0x0105, 0x0113, 0x0123, 0x012B, 0x0129, 0x0137, 0x00B7,
+ 0x013C, 0x0111, 0x0161, 0x0167, 0x017E, 0x2015, 0x016B, 0x014B,
+ 0x0100, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E,
+ 0x010C, 0x00C9, 0x0118, 0x00CB, 0x0116, 0x00CD, 0x00CE, 0x00CF,
+ 0x00D0, 0x0145, 0x014C, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x0168,
+ 0x00D8, 0x0172, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
+ 0x0101, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x012F,
+ 0x010D, 0x00E9, 0x0119, 0x00EB, 0x0117, 0x00ED, 0x00EE, 0x00EF,
+ 0x00F0, 0x0146, 0x014D, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x0169,
+ 0x00F8, 0x0173, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x0138
+};
+
+static const int latin7_table[256] =
+{
+ common,
+ 0x20ac, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 0x2026, 0x2122, 0x2030, 0x2022, 0x2018, -1, 0x2039, 0x203a,
+ -1, -1, -1, 0x2013, 0x2014, 0x2212, 0x0152, 0x0153,
+ 0x2020, 0x2021, 0xfb01, 0xfb02,
+ 0x00A0, 0x201D, 0x00A2, 0x00A3, 0x00A4, 0x201E, 0x00A6, 0x00A7,
+ 0x00D8, 0x00A9, 0x0156, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00C6,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x201C, 0x00B5, 0x00B6, 0x00B7,
+ 0x00F8, 0x00B9, 0x0157, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00E6,
+ 0x0104, 0x012E, 0x0100, 0x0106, 0x00C4, 0x00C5, 0x0118, 0x0112,
+ 0x010C, 0x00C9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012A, 0x013B,
+ 0x0160, 0x0143, 0x0145, 0x00D3, 0x014C, 0x00D5, 0x00D6, 0x00D7,
+ 0x0172, 0x0141, 0x015A, 0x016A, 0x00DC, 0x017B, 0x017D, 0x00DF,
+ 0x0105, 0x012F, 0x0101, 0x0107, 0x00E4, 0x00E5, 0x0119, 0x0113,
+ 0x010D, 0x00E9, 0x017A, 0x0117, 0x0123, 0x0137, 0x012B, 0x013C,
+ 0x0161, 0x0144, 0x0146, 0x00F3, 0x014D, 0x00F5, 0x00F6, 0x00F7,
+ 0x0173, 0x0142, 0x015B, 0x016B, 0x00FC, 0x017C, 0x017E, 0x2019
+};
+
+static const int latin8_table[256] =
+{
+ common,
+ 0x20ac, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ common2,
+ 0x00A0, 0x1E02, 0x1E03, 0x00A3, 0x010A, 0x010B, 0x1E0A, 0x00A7,
+ 0x1E80, 0x00A9, 0x1E82, 0x1E0B, 0x1EF2, 0x00AD, 0x00AE, 0x0178,
+ 0x1E1E, 0x1E1F, 0x0120, 0x0121, 0x1E40, 0x1E41, 0x00B6, 0x1E56,
+ 0x1E81, 0x1E57, 0x1E83, 0x1E60, 0x1EF3, 0x1E84, 0x1E85, 0x1E61,
+ 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
+ 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+ 0x0174, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x1E6A,
+ 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x0176, 0x00DF,
+ 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
+ 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+ 0x0175, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x1E6B,
+ 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x0177, 0x00FF
+};
+
+static const int latin9_table[256] =
+{
+ common,
+ -1, 0x0174, 0x0175, -1, -1, 0x0176, 0x0177, -1, -1, -1, -1, -1,
+ 0x2026, 0x2122, 0x2030, 0x2022, 0x2018, 0x2019, 0x2039, 0x203a,
+ 0x201c, 0x201d, 0x201e, 0x2013, 0x2014, 0x2212, -1, -1,
+ 0x2020, 0x2021, 0xfb01, 0xfb02,
+ 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x20AC, 0x00A5, 0x0160, 0x00A7,
+ 0x0161, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x017D, 0x00B5, 0x00B6, 0x00B7,
+ 0x017E, 0x00B9, 0x00BA, 0x00BB, 0x0152, 0x0153, 0x0178, 0x00BF,
+ 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
+ 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+ 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
+ 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
+ 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
+ 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+ 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
+ 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF
+};
+
+static const int latin10_table[256] =
+{
+ common,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 0x2026, 0x2122, 0x2030, 0x2022, 0x2018, 0x2019, 0x2039, 0x203a,
+ 0x201c, -1, -1, 0x2013, 0x2014, 0x2212, -1, -1,
+ 0x2020, 0x2021, 0xfb01, 0xfb02,
+ 0x00A0, 0x0104, 0x0105, 0x0141, 0x20AC, 0x201E, 0x0160, 0x00a7,
+ 0x0161, 0x00A9, 0x0218, 0x00AB, 0x0179, 0x00AD, 0x017A, 0x017B,
+ 0x00B0, 0x00B1, 0x010C, 0x0142, 0x017D, 0x201D, 0x00B6, 0x00B7,
+ 0x017E, 0x010D, 0x0219, 0x00BB, 0x0152, 0x0153, 0x0178, 0x017C,
+ 0x00C0, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0106, 0x00C6, 0x00C7,
+ 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+ 0x0110, 0x0143, 0x00D2, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x015A,
+ 0x0170, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0118, 0x021A, 0x00DF,
+ 0x00E0, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x0107, 0x00E6, 0x00E7,
+ 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+ 0x0111, 0x0144, 0x00F2, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x015B,
+ 0x0171, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0119, 0x021B, 0x00FF
+};
+
+static const int welsh_table[256] =
+{
+ common,
+ 0x20ac, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ common2,
+ 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
+ 0x1E80, 0x00A9, 0x1E82, 0x00AB, 0x1EF2, 0x00AD, 0x00AE, 0x0178,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+ 0x1E81, 0x00B9, 0x1E83, 0x00BB, 0x1EF3, 0x1E84, 0x1E85, 0x00BF,
+ 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
+ 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+ 0x0174, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
+ 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x0176, 0x00DF,
+ 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
+ 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+ 0x0175, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
+ 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x0177, 0x00FF
+};
+
+static const int greek_table[256] =
+{
+ common,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 0x00A0, 0x2018, 0x2019, 0x00A3, 0x20AC, 0x20AF, 0x00A6, 0x00A7,
+ 0x00A8, 0x00A9, 0x037A, 0x00AB, 0x00AC, 0x00AD, 0x037E, 0x2015,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x0384, 0x0385, 0x0386, 0x0387,
+ 0x0388, 0x0389, 0x038A, 0x00BB, 0x038C, 0x00BD, 0x038E, 0x038F,
+ 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
+ 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
+ 0x03A0, 0x03A1, -1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7,
+ 0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF,
+ 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
+ 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
+ 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
+ 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, -1
+};
+
+static const int cyrillic_table[256] =
+{
+ common,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 0x00A0, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407,
+ 0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x00AD, 0x040E, 0x040F,
+ 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
+ 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
+ 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
+ 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
+ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
+ 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
+ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
+ 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
+ 0x2116, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457,
+ 0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x00A7, 0x045E, 0x045F
+};
+
+static const int hebrew_table[256] =
+{
+ common,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 0x00A0, -1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
+ 0x00A8, 0x00A9, 0x00D7, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x203E,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+ 0x00B8, 0x00B9, 0x00F7, 0x00BB, 0x00BC, 0x00BD, 0x00BE, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 0x2017,
+ 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7,
+ 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
+ 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7,
+ 0x05E8, 0x05E9, 0x05EA, -1, -1, 0x200E, 0x200F, -1
+};
+
+/**
+ * Retrieve UCS table (above), given alphabet number
+ *
+ * \param alphabet The RISC OS alphabet number
+ * \return pointer to table, or NULL if not found
+ */
+const int *ucstable_from_alphabet(int alphabet)
+{
+ const int *ucstable = NULL;
+
+ switch (alphabet) {
+ case territory_ALPHABET_LATIN1:
+ ucstable = latin1_table;
+ break;
+ case territory_ALPHABET_LATIN2:
+ ucstable = latin2_table;
+ break;
+ case territory_ALPHABET_LATIN3:
+ ucstable = latin3_table;
+ break;
+ case territory_ALPHABET_LATIN4:
+ ucstable = latin4_table;
+ break;
+ case territory_ALPHABET_LATIN5:
+ ucstable = latin5_table;
+ break;
+ case territory_ALPHABET_LATIN6:
+ ucstable = latin6_table;
+ break;
+ case 114: /* Latin7 */
+ ucstable = latin7_table;
+ break;
+ case 115: /* Latin8 */
+ ucstable = latin8_table;
+ break;
+ case 116: /* Latin10 */
+ ucstable = latin10_table;
+ break;
+ case territory_ALPHABET_LATIN9:
+ ucstable = latin9_table;
+ break;
+ case territory_ALPHABET_WELSH:
+ ucstable = welsh_table;
+ break;
+ case territory_ALPHABET_GREEK:
+ ucstable = greek_table;
+ break;
+ case territory_ALPHABET_CYRILLIC:
+ ucstable = cyrillic_table;
+ break;
+ case territory_ALPHABET_HEBREW:
+ ucstable = hebrew_table;
+ break;
+ default:
+ ucstable = NULL;
+ break;
+ }
+
+ return ucstable;
+}
+
+
+static const char *localencodings[] = {
+ "ISO-8859-1//TRANSLIT", /* BFont - 100 - just use Latin1, instead */
+ "ISO-8859-1//TRANSLIT",
+ "ISO-8859-2//TRANSLIT",
+ "ISO-8859-3//TRANSLIT",
+ "ISO-8859-4//TRANSLIT",
+ "ISO-8859-5//TRANSLIT",
+ "ISO-8859-6//TRANSLIT",
+ "ISO-8859-7//TRANSLIT",
+ "ISO-8859-8//TRANSLIT",
+ "ISO-8859-9//TRANSLIT",
+ "ISO-IR-182//TRANSLIT",
+ "UTF-8",
+ "ISO-8859-15//TRANSLIT",
+ "ISO-8859-10//TRANSLIT",
+ "ISO-8859-13//TRANSLIT",
+ "ISO-8859-14//TRANSLIT",
+ "ISO-8859-16//TRANSLIT",
+#define CONT_ENC_END 116 /* RISC OS alphabet numbers lie in a
+ * contiguous range [100,CONT_ENC_END]
+ * _except_ for Cyrillic2, which doesn't.
+ */
+ "CP866//TRANSLIT" /* Cyrillic2 - 120 */
+};
+
+static const struct special {
+ char local; /**< Local 8bit representation */
+ char len; /**< Length (in bytes) of UTF-8 character */
+ const char *utf; /**< UTF-8 representation */
+} special_chars[] = {
+ { 0x80, 3, "\xE2\x82\xAC" }, /* EURO SIGN */
+ { 0x81, 2, "\xC5\xB4" }, /* LATIN CAPITAL LETTER W WITH CIRCUMFLEX */
+ { 0x82, 2, "\xC5\xB5" }, /* LATIN SMALL LETTER W WITH CIRCUMFLEX */
+ { 0x84, 3, "\xE2\x9C\x98" }, /* HEAVY BALLOT X */
+ { 0x85, 2, "\xC5\xB6" }, /* LATIN CAPITAL LETTER Y WITH CIRCUMFLEX */
+ { 0x86, 2, "\xC5\xB7" }, /* LATIN SMALL LETTER Y WITH CIRCUMFLEX */
+ { 0x88, 3, "\xE2\x87\x90" }, /* LEFTWARDS DOUBLE ARROW */
+ { 0x89, 3, "\xE2\x87\x92" }, /* RIGHTWARDS DOUBLE ARROW */
+ { 0x8a, 3, "\xE2\x87\x93" }, /* DOWNWARDS DOUBLE ARROW */
+ { 0x8b, 3, "\xE2\x87\x91" }, /* UPWARDS DOUBLE ARROW */
+ { 0x8c, 3, "\xE2\x80\xA6" }, /* HORIZONTAL ELLIPSIS */
+ { 0x8d, 3, "\xE2\x84\xA2" }, /* TRADE MARK SIGN */
+ { 0x8e, 3, "\xE2\x80\xB0" }, /* PER MILLE SIGN */
+ { 0x8f, 3, "\xE2\x80\xA2" }, /* BULLET */
+ { 0x90, 3, "\xE2\x80\x98" }, /* LEFT SINGLE QUOTATION MARK */
+ { 0x91, 3, "\xE2\x80\x99" }, /* RIGHT SINGLE QUOTATION MARK */
+ { 0x92, 3, "\xE2\x80\xB9" }, /* SINGLE LEFT-POINTING ANGLE QUOTATION MARK */
+ { 0x93, 3, "\xE2\x80\xBA" }, /* SINGLE RIGHT-POINTING ANGLE QUOTATION MARK */
+ { 0x94, 3, "\xE2\x80\x9C" }, /* LEFT DOUBLE QUOTATION MARK */
+ { 0x95, 3, "\xE2\x80\x9D" }, /* RIGHT DOUBLE QUOTATION MARK */
+ { 0x96, 3, "\xE2\x80\x9E" }, /* DOUBLE LOW-9 QUOTATION MARK */
+ { 0x97, 3, "\xE2\x80\x93" }, /* EN DASH */
+ { 0x98, 3, "\xE2\x80\x94" }, /* EM DASH */
+ { 0x99, 3, "\xE2\x88\x92" }, /* MINUS SIGN */
+ { 0x9a, 2, "\xC5\x92" }, /* LATIN CAPITAL LIGATURE OE */
+ { 0x9b, 2, "\xC5\x93" }, /* LATIN SMALL LIGATURE OE */
+ { 0x9c, 3, "\xE2\x80\xA0" }, /* DAGGER */
+ { 0x9d, 3, "\xE2\x80\xA1" }, /* DOUBLE DAGGER */
+ { 0x9e, 3, "\xEF\xAC\x81" }, /* LATIN SMALL LIGATURE FI */
+ { 0x9f, 3, "\xEF\xAC\x82" } /* LATIN SMALL LIGATURE FL */
+};
+
+
+/**
+ * Convert a UTF-8 encoded string into the system local encoding
+ *
+ * \param string The string to convert
+ * \param len The length (in bytes) of the string, or 0
+ * \param result Pointer to location in which to store result
+ * \return An nserror code
+ */
+nserror utf8_to_local_encoding(const char *string, size_t len, char **result)
+{
+ os_error *error;
+ int alphabet, i;
+ size_t off, prev_off;
+ char *temp, *cur_pos;
+ const char *enc;
+ nserror err;
+
+ assert(string);
+ assert(result);
+
+ /* get length, if necessary */
+ if (len == 0)
+ len = strlen(string);
+
+ /* read system alphabet */
+ error = xosbyte1(osbyte_ALPHABET_NUMBER, 127, 0, &alphabet);
+ if (error)
+ alphabet = territory_ALPHABET_LATIN1;
+
+ /* UTF-8 -> simply copy string */
+ if (alphabet == 111 /* UTF-8 */) {
+ *result = strndup(string, len);
+ return NSERROR_OK;
+ }
+
+ /* get encoding name */
+ enc = (alphabet <= CONT_ENC_END ? localencodings[alphabet - 100]
+ : (alphabet == 120 ?
+ localencodings[CONT_ENC_END - 100 + 1]
+ : localencodings[0]));
+
+ /* create output buffer */
+ *(result) = malloc(len + 1);
+ if (!(*result))
+ return NSERROR_NOMEM;
+ *(*result) = '\0';
+
+ prev_off = 0;
+ cur_pos = (*result);
+
+ /* Iterate over string, converting input between unconvertable
+ * characters and inserting appropriate output for characters
+ * that iconv can't handle. */
+ for (off = 0; off < len; off = utf8_next(string, len, off)) {
+ if (string[off] != 0xE2 &&
+ string[off] != 0xC5 && string[off] != 0xEF)
+ continue;
+
+ for (i = 0; i != NOF_ELEMENTS(special_chars); i++) {
+ if (strncmp(string + off, special_chars[i].utf,
+ special_chars[i].len) != 0)
+ continue;
+
+ /* 0 length has a special meaning to utf8_to_enc */
+ if (off - prev_off > 0) {
+ err = utf8_to_enc(string + prev_off, enc,
+ off - prev_off, &temp);
+ if (err != NSERROR_OK) {
+ assert(err != NSERROR_BAD_ENCODING);
+ free(*result);
+ return NSERROR_NOMEM;
+ }
+
+ strcat(cur_pos, temp);
+
+ cur_pos += strlen(temp);
+
+ free(temp);
+ }
+
+ *cur_pos = special_chars[i].local;
+ *(++cur_pos) = '\0';
+ prev_off = off + special_chars[i].len;
+ }
+ }
+
+ /* handle last chunk
+ * NB. 0 length has a special meaning to utf8_to_enc */
+
+ if (prev_off < len) {
+ err = utf8_to_enc(string + prev_off, enc, len - prev_off,
+ &temp);
+ if (err != NSERROR_OK) {
+ assert(err != NSERROR_BAD_ENCODING);
+ free(*result);
+ return NSERROR_NOMEM;
+ }
+
+ strcat(cur_pos, temp);
+
+ free(temp);
+ }
+
+ return NSERROR_OK;
+}
+
+/**
+ * Convert a string encoded in the system local encoding to UTF-8
+ *
+ * \param string The string to convert
+ * \param len The length (in bytes) of the string, or 0
+ * \param result Pointer to location in which to store result
+ * \return An nserror code
+ */
+nserror utf8_from_local_encoding(const char *string, size_t len, char **result)
+{
+ os_error *error;
+ int alphabet, i, num_specials = 0, result_alloc;
+#define SPECIAL_CHUNK_SIZE 255
+ size_t off, prev_off, cur_off;
+ char *temp;
+ const char *enc;
+ nserror err;
+
+ assert(string && result);
+
+ /* get length, if necessary */
+ if (len == 0)
+ len = strlen(string);
+
+ /* read system alphabet */
+ error = xosbyte1(osbyte_ALPHABET_NUMBER, 127, 0, &alphabet);
+ if (error)
+ alphabet = territory_ALPHABET_LATIN1;
+
+ /* UTF-8 -> simply copy string */
+ if (alphabet == 111 /* UTF-8 */) {
+ temp = strndup(string, len);
+ if (!temp)
+ return NSERROR_NOMEM;
+
+ *result = temp;
+ return NSERROR_OK;
+ }
+
+ /* get encoding name */
+ enc = (alphabet <= CONT_ENC_END ? localencodings[alphabet - 100]
+ : (alphabet == 120 ?
+ localencodings[CONT_ENC_END - 100 + 1]
+ : localencodings[0]));
+
+ /* create output buffer (oversized) */
+ result_alloc = (len * 4) + (3 * SPECIAL_CHUNK_SIZE) + 1;
+
+ *(result) = malloc(result_alloc);
+ if (!(*result))
+ return NSERROR_NOMEM;
+ *(*result) = '\0';
+
+ prev_off = 0;
+ cur_off = 0;
+
+ /* Iterate over string, converting input between unconvertable
+ * characters and inserting appropriate output for characters
+ * that iconv can't handle. */
+ for (off = 0; off < len; off++) {
+ if (string[off] < 0x80 || string[off] > 0x9f)
+ continue;
+
+ for (i = 0; i != NOF_ELEMENTS(special_chars); i++) {
+ if (string[off] != special_chars[i].local)
+ continue;
+
+ /* 0 length has a special meaning to utf8_from_enc */
+ if (off - prev_off > 0) {
+ err = utf8_from_enc(string + prev_off, enc,
+ off - prev_off, &temp, NULL);
+ if (err != NSERROR_OK) {
+ assert(err != NSERROR_BAD_ENCODING);
+ LOG("utf8_from_enc failed");
+ free(*result);
+ return NSERROR_NOMEM;
+ }
+
+ strcat((*result) + cur_off, temp);
+
+ cur_off += strlen(temp);
+
+ free(temp);
+ }
+
+ strcat((*result) + cur_off, special_chars[i].utf);
+
+ cur_off += special_chars[i].len;
+
+ prev_off = off + 1;
+
+ num_specials++;
+ if (num_specials % SPECIAL_CHUNK_SIZE ==
+ SPECIAL_CHUNK_SIZE - 1) {
+ char *temp = realloc((*result),
+ result_alloc +
+ (3 * SPECIAL_CHUNK_SIZE));
+ if (!temp) {
+ free(*result);
+ return NSERROR_NOMEM;
+ }
+
+ *result = temp;
+ result_alloc += (3 * SPECIAL_CHUNK_SIZE);
+ }
+ }
+ }
+
+ /* handle last chunk
+ * NB. 0 length has a special meaning to utf8_from_enc */
+ if (prev_off < len) {
+ err = utf8_from_enc(string + prev_off, enc, len - prev_off,
+ &temp, NULL);
+ if (err != NSERROR_OK) {
+ assert(err != NSERROR_BAD_ENCODING);
+ LOG("utf8_from_enc failed");
+ free(*result);
+ return NSERROR_NOMEM;
+ }
+
+ strcat((*result) + cur_off, temp);
+
+ cur_off += strlen(temp);
+
+ free(temp);
+ }
+
+ /* and copy into more reasonably-sized buffer */
+ temp = realloc((*result), cur_off + 1);
+ if (!temp) {
+ LOG("realloc failed");
+ free(*result);
+ return NSERROR_NOMEM;
+ }
+ *result = temp;
+
+ return NSERROR_OK;
+}
+
+static struct gui_utf8_table utf8_table = {
+ .utf8_to_local = utf8_to_local_encoding,
+ .local_to_utf8 = utf8_from_local_encoding,
+};
+
+struct gui_utf8_table *riscos_utf8_table = &utf8_table;
diff --git a/frontends/riscos/ucstables.h b/frontends/riscos/ucstables.h
new file mode 100644
index 000000000..e5d838249
--- /dev/null
+++ b/frontends/riscos/ucstables.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2005 John M Bell <jmb202@ecs.soton.ac.uk>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * UCS conversion tables (interface)
+ * This is only used if nothing claims Service_International,8
+ */
+
+struct gui_utf8_table *riscos_utf8_table;
+
+nserror utf8_to_local_encoding(const char *string, size_t len, char **result);
+nserror utf8_from_local_encoding(const char *string, size_t len, char **result);
+
+const int *ucstable_from_alphabet(int alphabet);
diff --git a/frontends/riscos/uri.c b/frontends/riscos/uri.c
new file mode 100644
index 000000000..9c384c9c0
--- /dev/null
+++ b/frontends/riscos/uri.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2003 Rob Jackson <jacko@xms.ms>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "utils/config.h"
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "oslib/uri.h"
+#include "oslib/wimp.h"
+
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/nsurl.h"
+#include "content/fetch.h"
+#include "desktop/browser.h"
+
+#include "riscos/gui.h"
+#include "riscos/uri.h"
+#include "riscos/url_protocol.h"
+
+void ro_uri_message_received(wimp_message *msg)
+{
+ uri_full_message_process *uri_message = (uri_full_message_process *)msg;
+ uri_h uri_handle;
+ char* uri_requested;
+ int uri_length;
+ nsurl *url;
+ nserror error;
+
+ uri_handle = uri_message->handle;
+
+ if (nsurl_create(uri_message->uri, &url) != NSERROR_OK) {
+ return;
+ }
+
+ if (!fetch_can_fetch(url)) {
+ nsurl_unref(url);
+ return;
+ }
+
+ nsurl_unref(url);
+
+ uri_message->your_ref = uri_message->my_ref;
+ uri_message->action = message_URI_PROCESS_ACK;
+
+ xwimp_send_message(wimp_USER_MESSAGE, (wimp_message*)uri_message,
+ uri_message->sender);
+
+ xuri_request_uri(0, 0, 0, uri_handle, &uri_length);
+ uri_requested = calloc((unsigned int)uri_length, sizeof(char));
+ if (uri_requested == NULL)
+ return;
+
+ xuri_request_uri(0, uri_requested, uri_length, uri_handle, NULL);
+
+ error = nsurl_create(uri_requested, &url);
+ free(uri_requested);
+ if (error == NSERROR_OK) {
+ error = browser_window_create(BW_CREATE_HISTORY,
+ url,
+ NULL,
+ NULL,
+ NULL);
+ nsurl_unref(url);
+ }
+ if (error != NSERROR_OK) {
+ ro_warn_user(messages_get_errorcode(error), 0);
+ }
+}
+
+bool ro_uri_launch(const char *uri)
+{
+ uri_h uri_handle;
+ wimp_t handle_task;
+ uri_dispatch_flags returned;
+ os_error *e;
+
+ e = xuri_dispatch(uri_DISPATCH_INFORM_CALLER, uri, task_handle,
+ &returned, &handle_task, &uri_handle);
+
+ if (e || returned & 1) {
+ return false;
+ }
+
+ return true;
+}
+
+void ro_uri_bounce(wimp_message *msg)
+{
+ uri_full_message_process *message = (uri_full_message_process *)msg;
+ int size;
+ char *uri_buf;
+ os_error *e;
+
+ if ((message->flags & 1) == 0)
+ return;
+
+ /* Get required buffer size */
+ e = xuri_request_uri(0, NULL, 0, message->handle, &size);
+ if (e) {
+ LOG("xuri_request_uri: %d: %s", e->errnum, e->errmess);
+ return;
+ }
+
+ uri_buf = malloc(size);
+ if (uri_buf == NULL)
+ return;
+
+ /* Get URI */
+ e = xuri_request_uri(0, uri_buf, size, message->handle, 0);
+ if (e) {
+ LOG("xuri_request_uri: %d: %s", e->errnum, e->errmess);
+ free(uri_buf);
+ return;
+ }
+
+ ro_url_load(uri_buf);
+
+ free(uri_buf);
+
+ return;
+}
diff --git a/frontends/riscos/uri.h b/frontends/riscos/uri.h
new file mode 100644
index 000000000..d538ea914
--- /dev/null
+++ b/frontends/riscos/uri.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2003 Rob Jackson <jacko@xms.ms>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _NETSURF_RISCOS_URI_H_
+#define _NETSURF_RISCOS_URI_H_
+
+#include "utils/config.h"
+
+#include "oslib/wimp.h"
+
+void ro_uri_message_received(wimp_message *message);
+bool ro_uri_launch(const char *uri);
+void ro_uri_bounce(wimp_message *message);
+
+#endif
diff --git a/frontends/riscos/url_complete.c b/frontends/riscos/url_complete.c
new file mode 100644
index 000000000..3cf7f9228
--- /dev/null
+++ b/frontends/riscos/url_complete.c
@@ -0,0 +1,740 @@
+/*
+ * Copyright 2005 Richard Wilson <info@tinct.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * GUI URL auto-completion (implementation).
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <oslib/wimp.h>
+
+#include "utils/log.h"
+#include "utils/nsoption.h"
+#include "content/urldb.h"
+#include "desktop/browser.h"
+
+#include "riscos/global_history.h"
+#include "riscos/gui.h"
+#include "riscos/mouse.h"
+#include "riscos/toolbar.h"
+#include "riscos/url_complete.h"
+#include "riscos/wimp.h"
+#include "riscos/wimp_event.h"
+#include "riscos/wimputils.h"
+#include "riscos/filetype.h"
+
+#define MAXIMUM_VISIBLE_LINES 7
+
+static nsurl **url_complete_matches = NULL;
+static int url_complete_matches_allocated = 0;
+static int url_complete_matches_available = 0;
+static char *url_complete_matched_string = NULL;
+static int url_complete_matches_selection = -1;
+static int url_complete_keypress_selection = -1;
+static wimp_w url_complete_parent = 0;
+static bool url_complete_matches_reset = false;
+static char *url_complete_original_url = NULL;
+static bool url_complete_memory_exhausted = false;
+
+static nsurl *url_complete_redraw[MAXIMUM_VISIBLE_LINES];
+static char url_complete_icon_null[] = "";
+static char url_complete_icon_sprite[12];
+static wimp_icon url_complete_icon;
+static wimp_icon url_complete_sprite;
+static int mouse_x;
+static int mouse_y;
+
+static bool url_complete_callback(nsurl *url,
+ const struct url_data *data);
+static void ro_gui_url_complete_mouse_at(wimp_pointer *pointer, void *data);
+
+
+/* This is an exported interface documented in url_complete.h */
+
+void ro_gui_url_complete_start(struct toolbar *toolbar)
+{
+ const char *url;
+ wimp_w parent;
+
+ assert(toolbar != NULL);
+ parent = ro_toolbar_get_parent_window(toolbar);
+
+ if (!ro_toolbar_get_display_url(toolbar) ||
+ (parent == url_complete_parent))
+ return;
+
+ ro_gui_url_complete_close();
+ url = ro_toolbar_get_url(toolbar);
+ if (url != NULL) {
+ url_complete_matched_string = strdup(url);
+ if (url_complete_matched_string)
+ url_complete_parent = parent;
+ }
+}
+
+
+/* This is an exported interface documented in url_complete.h */
+
+bool ro_gui_url_complete_keypress(struct toolbar *toolbar, uint32_t key)
+{
+ wimp_w parent;
+ wimp_window_state state;
+ char *match_url;
+ const char *url;
+ int old_selection;
+ int height;
+ os_error *error;
+ bool currently_open;
+
+ assert(toolbar != NULL);
+ parent = ro_toolbar_get_parent_window(toolbar);
+
+ /* we must have a toolbar/url bar */
+ if (!ro_toolbar_get_display_url(toolbar) ||
+ (!nsoption_bool(url_suggestion))) {
+ ro_gui_url_complete_close();
+ return false;
+ }
+
+ /* if we are currently active elsewhere, remove the previous window */
+ currently_open = ((parent == url_complete_parent) &&
+ (url_complete_matches_available > 0));
+ if (parent != url_complete_parent)
+ ro_gui_url_complete_close();
+
+ /* forcibly open on down keys */
+ if ((!currently_open) && (url_complete_matched_string)) {
+ switch (key) {
+ case IS_WIMP_KEY | wimp_KEY_DOWN:
+ case IS_WIMP_KEY | wimp_KEY_PAGE_DOWN:
+ case IS_WIMP_KEY | wimp_KEY_CONTROL | wimp_KEY_DOWN:
+ free(url_complete_matched_string);
+ url_complete_matched_string = NULL;
+ }
+ }
+
+
+ /* get the text to match */
+ url_complete_parent = parent;
+ url = ro_toolbar_get_url(toolbar);
+ match_url = (url != NULL) ? strdup(url) : NULL;
+ if (match_url == NULL) {
+ ro_gui_url_complete_close();
+ return false;
+ }
+
+ /* if the text to match has changed then update it */
+ if ((!url_complete_matched_string) ||
+ (strcmp(match_url, url_complete_matched_string))) {
+
+ /* memorize the current matches */
+ int i;
+ int lines = MAXIMUM_VISIBLE_LINES;
+ if (lines > url_complete_matches_available)
+ lines = url_complete_matches_available;
+ if (url_complete_matches) {
+ for (i = 0; i < MAXIMUM_VISIBLE_LINES; i++) {
+ if (i < lines) {
+ url_complete_redraw[i] =
+ url_complete_matches[i];
+ } else {
+ url_complete_redraw[i] = NULL;
+ }
+ }
+ }
+
+ /* our selection gets wiped */
+ error = xwimp_force_redraw(dialog_url_complete,
+ 0,
+ -(url_complete_matches_selection + 1) * 44,
+ 65536, -url_complete_matches_selection * 44);
+ if (error) {
+ LOG("xwimp_force_redraw: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+
+ /* clear our state */
+ free(url_complete_original_url);
+ free(url_complete_matched_string);
+ url_complete_matched_string = match_url;
+ url_complete_original_url = NULL;
+ url_complete_matches_available = 0;
+ url_complete_matches_selection = -1;
+ url_complete_keypress_selection = -1;
+
+ /* get some initial memory */
+ if (!url_complete_matches) {
+ url_complete_matches = malloc(64 * sizeof(char *));
+ if (!url_complete_matches) {
+ ro_gui_url_complete_close();
+ return false;
+ }
+ url_complete_matches_allocated = 64;
+ }
+
+ /* find matches */
+ url_complete_memory_exhausted = false;
+ if (strlen(match_url) == 0)
+ urldb_iterate_entries(url_complete_callback);
+ else
+ urldb_iterate_partial(match_url, url_complete_callback);
+ if ((url_complete_memory_exhausted) ||
+ (url_complete_matches_available == 0)) {
+ ro_gui_url_complete_close();
+ return false;
+ }
+
+ /* update the window */
+ state.w = parent;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return false;
+ }
+ url_complete_matches_reset = true;
+ ro_gui_url_complete_resize(toolbar, PTR_WIMP_OPEN(&state));
+ url_complete_matches_reset = false;
+
+ /* redraw the relevant bits of the window */
+ lines = MAXIMUM_VISIBLE_LINES;
+ if (lines > url_complete_matches_available)
+ lines = url_complete_matches_available;
+ for (i = 0; i < lines; i++) {
+ if (url_complete_redraw[i] !=
+ url_complete_matches[i]) {
+ error = xwimp_force_redraw(dialog_url_complete,
+ 0, -(i + 1) * 44, 65536, -i * 44);
+ if (error) {
+ LOG("xwimp_force_redraw: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError",
+ error->errmess);
+ }
+ }
+ }
+ } else {
+ free(match_url);
+ }
+
+ /* handle keypresses */
+ if (!currently_open)
+ return false;
+
+ old_selection = url_complete_matches_selection;
+
+ switch (key) {
+ case IS_WIMP_KEY | wimp_KEY_UP:
+ url_complete_matches_selection--;
+ break;
+ case IS_WIMP_KEY | wimp_KEY_DOWN:
+ url_complete_matches_selection++;
+ break;
+ case IS_WIMP_KEY | wimp_KEY_PAGE_UP:
+ url_complete_matches_selection -=
+ MAXIMUM_VISIBLE_LINES;
+ break;
+ case IS_WIMP_KEY | wimp_KEY_PAGE_DOWN:
+ url_complete_matches_selection +=
+ MAXIMUM_VISIBLE_LINES;
+ break;
+ case IS_WIMP_KEY | wimp_KEY_CONTROL | wimp_KEY_UP:
+ url_complete_matches_selection = 0;
+ break;
+ case IS_WIMP_KEY | wimp_KEY_CONTROL | wimp_KEY_DOWN:
+ url_complete_matches_selection = 65536;
+ break;
+ }
+
+ if (url_complete_matches_selection >
+ url_complete_matches_available - 1)
+ url_complete_matches_selection =
+ url_complete_matches_available - 1;
+ else if (url_complete_matches_selection < -1)
+ url_complete_matches_selection = -1;
+
+ if (old_selection == url_complete_matches_selection)
+ return false;
+
+ error = xwimp_force_redraw(dialog_url_complete,
+ 0, -(old_selection + 1) * 44,
+ 65536, -old_selection * 44);
+ if (error) {
+ LOG("xwimp_force_redraw: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+
+ error = xwimp_force_redraw(dialog_url_complete,
+ 0, -(url_complete_matches_selection + 1) * 44,
+ 65536, -url_complete_matches_selection * 44);
+ if (error) {
+ LOG("xwimp_force_redraw: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+
+ if (old_selection == -1) {
+ free(url_complete_original_url);
+ url_complete_original_url = malloc(strlen(url) + 1);
+ if (!url_complete_original_url)
+ return false;
+ strcpy(url_complete_original_url, url);
+ }
+
+ if (url_complete_matches_selection == -1) {
+ ro_toolbar_set_url(toolbar,
+ url_complete_original_url, true, false);
+ } else {
+ ro_toolbar_set_url(toolbar,
+ nsurl_access(url_complete_matches[
+ url_complete_matches_selection]),
+ true, false);
+ free(url_complete_matched_string);
+ url_complete_matched_string = strdup(nsurl_access(
+ url_complete_matches[
+ url_complete_matches_selection]));
+ }
+ url_complete_keypress_selection = url_complete_matches_selection;
+
+ /* auto-scroll */
+ state.w = dialog_url_complete;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return true;
+ }
+
+ if (state.yscroll < -(url_complete_matches_selection * 44))
+ state.yscroll = -(url_complete_matches_selection * 44);
+ height = state.visible.y1 - state.visible.y0;
+ if (state.yscroll - height >
+ -((url_complete_matches_selection + 1) * 44))
+ state.yscroll =
+ -((url_complete_matches_selection + 1) * 44) + height;
+
+ error = xwimp_open_window(PTR_WIMP_OPEN(&state));
+ if (error) {
+ LOG("xwimp_open_window: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return true;
+ }
+
+ return true;
+}
+
+
+/**
+ * Callback function for urldb_iterate_partial
+ *
+ * \param url URL which matches
+ * \param data Data associated with URL
+ * \return true to continue iteration, false otherwise
+ */
+
+bool url_complete_callback(nsurl *url, const struct url_data *data)
+{
+ nsurl **array_extend;
+
+ /* Ignore unvisited URLs */
+ if (data->visits == 0)
+ return true;
+
+ url_complete_matches_available++;
+
+ if (url_complete_matches_available >
+ url_complete_matches_allocated) {
+
+ array_extend = (nsurl **)realloc(url_complete_matches,
+ (url_complete_matches_allocated + 64) *
+ sizeof(nsurl *));
+ if (!array_extend) {
+ url_complete_memory_exhausted = true;
+ return false;
+ }
+ url_complete_matches = array_extend;
+ url_complete_matches_allocated += 64;
+ }
+
+ url_complete_matches[url_complete_matches_available - 1] = url;
+
+ return true;
+}
+
+
+/* This is an exported interface documented in url_complete.h */
+
+void ro_gui_url_complete_resize(struct toolbar *toolbar, wimp_open *open)
+{
+ os_box extent = { 0, 0, 0, 0 };
+ os_box url_extent;
+ wimp_window_state toolbar_state;
+ wimp_window_state state;
+ os_error *error;
+ int lines;
+ int scroll_v = 0;
+
+ /* only react to our window */
+ if (open->w != url_complete_parent)
+ return;
+
+ /* if there is no toolbar, or there is no URL bar shown,
+ * or there are no URL matches, close it */
+ if (!ro_toolbar_get_display_url(toolbar) ||
+ (!url_complete_matches) ||
+ (url_complete_matches_available == 0)) {
+ ro_gui_url_complete_close();
+ return;
+ }
+
+ /* get our current auto-complete window state for the scroll values */
+ state.w = dialog_url_complete;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ if (url_complete_matches_reset)
+ state.yscroll = 0;
+
+ /* move the window to the correct position */
+ toolbar_state.w = ro_toolbar_get_window(toolbar);
+ error = xwimp_get_window_state(&toolbar_state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ if (!ro_toolbar_get_url_field_extent(toolbar, &url_extent)) {
+ LOG("Failed to read URL field extent.");
+ return;
+ }
+
+ lines = url_complete_matches_available;
+ extent.y0 = -(lines * 44);
+ extent.x1 = 65536;
+ error = xwimp_set_extent(dialog_url_complete, &extent);
+ if (error) {
+ LOG("xwimp_set_extent: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ state.next = open->next;
+ state.flags &= ~wimp_WINDOW_VSCROLL;
+ state.flags &= ~(4095 << 16); /* clear bits 16-27 */
+ if (lines > MAXIMUM_VISIBLE_LINES) {
+ lines = MAXIMUM_VISIBLE_LINES;
+ scroll_v = ro_get_vscroll_width(NULL) - 2;
+ state.flags |= wimp_WINDOW_VSCROLL;
+ }
+ state.visible.x0 = open->visible.x0 + 2 + url_extent.x0;
+ state.visible.x1 = open->visible.x0 - 2 + url_extent.x1 - scroll_v;
+ state.visible.y1 = open->visible.y1 - url_extent.y1 + 2;
+ state.visible.y0 = state.visible.y1 - (lines * 44);
+ if (state.visible.x1 + scroll_v > toolbar_state.visible.x1)
+ state.visible.x1 = toolbar_state.visible.x1 - scroll_v;
+ if (state.visible.x1 - state.visible.x0 < 0) {
+ error = xwimp_close_window(dialog_url_complete);
+ if (error) {
+ LOG("xwimp_close_window: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+ } else {
+ error = xwimp_open_window_nested_with_flags(&state,
+ (wimp_w)-1, 0);
+ if (error) {
+ LOG("xwimp_open_window: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+ open->next = dialog_url_complete;
+ }
+}
+
+
+/* This is an exported interface documented in url_complete.h */
+
+bool ro_gui_url_complete_close(void)
+{
+ os_error *error;
+ bool currently_open;
+
+ /* There used to be a check here to see if the icon clicked was the
+ * URL text field in the toolbar. Since this only applied to clicks
+ * originating from the toolbar module following the restructuring,
+ * and this check was better done within the toolbar, it has been
+ * removed from this function and the associated parameters removed.
+ */
+
+ currently_open = ((url_complete_parent != NULL) &&
+ (url_complete_matches_available > 0));
+
+ free(url_complete_matches);
+ free(url_complete_matched_string);
+ free(url_complete_original_url);
+ url_complete_matches = NULL;
+ url_complete_matched_string = NULL;
+ url_complete_original_url = NULL;
+ url_complete_matches_allocated = 0;
+ url_complete_matches_available = 0;
+ url_complete_keypress_selection = -1;
+ url_complete_matches_selection = -1;
+ url_complete_parent = 0;
+
+ error = xwimp_close_window(dialog_url_complete);
+ if (error) {
+ LOG("xwimp_close_window: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+
+ return currently_open;
+}
+
+
+/* This is an exported interface documented in url_complete.h */
+
+void ro_gui_url_complete_redraw(wimp_draw *redraw)
+{
+ osbool more;
+ os_error *error;
+ int line;
+ const struct url_data *data;
+ int type;
+
+ /* initialise our icon */
+ url_complete_icon.flags = wimp_ICON_INDIRECTED | wimp_ICON_VCENTRED |
+ wimp_ICON_TEXT | wimp_ICON_FILLED |
+ (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) |
+ (wimp_COLOUR_WHITE << wimp_ICON_BG_COLOUR_SHIFT);
+ url_complete_icon.extent.x0 = 50;
+ url_complete_icon.extent.x1 = 16384;
+ url_complete_icon.data.indirected_text.validation =
+ url_complete_icon_null;
+ url_complete_sprite.flags = wimp_ICON_TEXT | wimp_ICON_SPRITE |
+ wimp_ICON_INDIRECTED | wimp_ICON_FILLED |
+ wimp_ICON_HCENTRED | wimp_ICON_VCENTRED;
+ url_complete_sprite.extent.x0 = 0;
+ url_complete_sprite.extent.x1 = 50;
+ url_complete_sprite.data.indirected_text.text =
+ url_complete_icon_null;
+ url_complete_sprite.data.indirected_text.validation =
+ url_complete_icon_sprite;
+ url_complete_sprite.data.indirected_text.size = 1;
+
+ /* no matches? no redraw */
+ if (!url_complete_matches) {
+ LOG("Attempt to redraw with no matches made");
+ /* Fill is never used, so make it something obvious */
+ ro_gui_user_redraw(redraw, false, os_COLOUR_BLACK);
+ return;
+ }
+
+ /* redraw */
+ more = wimp_redraw_window(redraw);
+ while (more) {
+ int first_line, last_line;
+ int origin_y = redraw->box.y1 - redraw->yscroll;
+ int clip_y0 = redraw->clip.y0 - origin_y;
+ int clip_y1 = redraw->clip.y1 - origin_y;
+
+ first_line = (-clip_y1) / 44;
+ last_line = (-clip_y0 + 43) / 44;
+
+ for (line = first_line; line < last_line; line++) {
+ if (line == url_complete_matches_selection)
+ url_complete_icon.flags |=
+ wimp_ICON_SELECTED;
+ else
+ url_complete_icon.flags &=
+ ~wimp_ICON_SELECTED;
+ url_complete_icon.extent.y1 = -line * 44;
+ url_complete_icon.extent.y0 = -(line + 1) * 44;
+ url_complete_icon.data.indirected_text.text =
+ (char *)nsurl_access(
+ url_complete_matches[line]);
+ url_complete_icon.data.indirected_text.size =
+ nsurl_length(
+ url_complete_matches[line]);
+
+ error = xwimp_plot_icon(&url_complete_icon);
+ if (error) {
+ LOG("xwimp_plot_icon: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+
+ data = urldb_get_url_data(url_complete_matches[line]);
+ if (data)
+ type = ro_content_filetype_from_type(
+ data->type);
+ else
+ type = 0;
+
+ sprintf(url_complete_icon_sprite, "Ssmall_%.3x",
+ type);
+
+ if (!ro_gui_wimp_sprite_exists(
+ url_complete_icon_sprite + 1))
+ sprintf(url_complete_icon_sprite,
+ "Ssmall_xxx");
+ url_complete_sprite.extent.y1 = -line * 44;
+ url_complete_sprite.extent.y0 = -(line + 1) * 44;
+ error = xwimp_plot_icon(&url_complete_sprite);
+ if (error) {
+ LOG("xwimp_plot_icon: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+ }
+ more = wimp_get_rectangle(redraw);
+ }
+}
+
+
+/* This is an exported interface documented in url_complete.h */
+
+void ro_gui_url_complete_entering(wimp_entering *entering)
+{
+ ro_mouse_track_start(NULL, ro_gui_url_complete_mouse_at, NULL);
+}
+
+
+/**
+ * Handle mouse movement over the URL completion window.
+ *
+ * \param *pointer The pointer state
+ * \param *data NULL data pointer expected by mouse tracker
+ */
+
+void ro_gui_url_complete_mouse_at(wimp_pointer *pointer, void *data)
+{
+ wimp_mouse_state current;
+
+ current = pointer->buttons;
+ pointer->buttons = 0;
+ ro_gui_url_complete_click(pointer);
+ pointer->buttons = current;
+}
+
+
+/* This is an exported interface documented in url_complete.h */
+
+bool ro_gui_url_complete_click(wimp_pointer *pointer)
+{
+ wimp_window_state state;
+ os_error *error;
+ int selection;
+ struct gui_window *g;
+
+ if ((mouse_x == pointer->pos.x) && (mouse_y == pointer->pos.y) &&
+ (!pointer->buttons))
+ return false;
+
+ mouse_x = pointer->pos.x;
+ mouse_y = pointer->pos.y;
+
+ state.w = dialog_url_complete;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return false;
+ }
+
+ selection = (state.visible.y1 - pointer->pos.y - state.yscroll) / 44;
+ if (selection != url_complete_matches_selection) {
+ int old_selection;
+
+ if (url_complete_matches_selection == -1) {
+ const char *url;
+
+ g = ro_gui_window_lookup(url_complete_parent);
+ if (!g)
+ return false;
+ url = ro_toolbar_get_url(g->toolbar);
+ free(url_complete_original_url);
+ url_complete_original_url = strdup(url);
+ if (!url_complete_original_url)
+ return false;
+ }
+ old_selection = url_complete_matches_selection;
+ url_complete_matches_selection = selection;
+ error = xwimp_force_redraw(dialog_url_complete,
+ 0, -(old_selection + 1) * 44,
+ 65536, -old_selection * 44);
+ if (error) {
+ LOG("xwimp_force_redraw: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+ error = xwimp_force_redraw(dialog_url_complete,
+ 0, -(url_complete_matches_selection + 1) * 44,
+ 65536, -url_complete_matches_selection * 44);
+ if (error) {
+ LOG("xwimp_force_redraw: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+ }
+ if (!pointer->buttons)
+ return true;
+
+ /* find owning window */
+ g = ro_gui_window_lookup(url_complete_parent);
+ if (!g)
+ return false;
+
+ /* Select sets the text and launches */
+ if (pointer->buttons == wimp_CLICK_SELECT) {
+ ro_toolbar_set_url(g->toolbar,
+ nsurl_access(url_complete_matches[
+ url_complete_matches_selection]),
+ true, false);
+
+ /** \todo The interaction of components here is hideous */
+ /* Do NOT make any attempt to use any of the global url
+ * completion variables after this call to browser_window_navigate.
+ * They will be invalidated by (at least):
+ * + ro_gui_window_set_url
+ * + destruction of (i)frames within the current page
+ * Any attempt to use them will probably result in a crash.
+ */
+
+ browser_window_navigate(g->bw,
+ url_complete_matches[url_complete_matches_selection],
+ NULL,
+ BW_NAVIGATE_HISTORY,
+ NULL,
+ NULL,
+ NULL);
+
+ ro_gui_url_complete_close();
+
+ /* Adjust just sets the text */
+ } else if (pointer->buttons == wimp_CLICK_ADJUST) {
+ ro_toolbar_set_url(g->toolbar,
+ nsurl_access(url_complete_matches[
+ url_complete_matches_selection]),
+ true, false);
+ ro_gui_url_complete_keypress(g->toolbar, 0);
+ }
+ return true;
+}
+
diff --git a/frontends/riscos/url_complete.h b/frontends/riscos/url_complete.h
new file mode 100644
index 000000000..6a4660e4a
--- /dev/null
+++ b/frontends/riscos/url_complete.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2005 Richard Wilson <info@tinct.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Central repository for URL data (interface).
+ */
+
+#ifndef _NETSURF_RISCOS_URLCOMPLETE_H_
+#define _NETSURF_RISCOS_URLCOMPLETE_H_
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include "oslib/wimp.h"
+
+struct gui_window;
+
+/**
+ * Should be called when the caret is placed into a URL completion icon.
+ *
+ * \param *toolbar The toolbar to initialise URL completion for.
+ */
+
+void ro_gui_url_complete_start(struct toolbar *toolbar);
+
+
+/**
+ * Handles a keypress for URL completion
+ *
+ * \param *toolbar The toolbar to be updated.
+ * \param key the key pressed (as UTF32 code or
+ * wimp key + bit31 set)
+ * \return true to indicate keypress handled; else false.
+ */
+
+bool ro_gui_url_complete_keypress(struct toolbar *toolbar, uint32_t key);
+
+
+/**
+ * Move and resize the url completion window to match the toolbar.
+ *
+ * \param *toolbar The toolbar to update
+ * \param *open the wimp_open request (updated on exit)
+ */
+
+void ro_gui_url_complete_resize(struct toolbar *toolbar, wimp_open *open);
+
+
+/**
+ * Try to close the current url completion window
+ *
+ * \return whether the window was closed
+ */
+
+bool ro_gui_url_complete_close(void);
+
+
+/**
+ * Redraws a section of the URL completion window
+ *
+ * \param redraw the area to redraw
+ */
+
+void ro_gui_url_complete_redraw(wimp_draw *redraw);
+
+
+/**
+ * Handle the pointer entering the URL completion window.
+ *
+ * \param *entering The pointer entering data block.
+ */
+
+void ro_gui_url_complete_entering(wimp_entering *entering);
+
+
+/**
+ * Handle mouse clicks in the URL completion window.
+ *
+ * \param pointer the pointer state
+ * \return whether the click was handled
+ */
+
+bool ro_gui_url_complete_click(wimp_pointer *pointer);
+
+#endif
+
diff --git a/frontends/riscos/url_protocol.c b/frontends/riscos/url_protocol.c
new file mode 100644
index 000000000..2b9ef3556
--- /dev/null
+++ b/frontends/riscos/url_protocol.c
@@ -0,0 +1,226 @@
+/*
+ * Copyright 2003 John M Bell <jmb202@ecs.soton.ac.uk>
+ * Copyright 2003 Rob Jackson <jacko@xms.ms>
+ * Copyright 2004 James Bursa <bursa@users.sourceforge.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * ANT URL launching protocol (implementation).
+ *
+ * See http://www.vigay.com/inet/inet_url.html
+ */
+
+#include "utils/config.h"
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <oslib/inetsuite.h>
+#include <oslib/wimp.h>
+
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/nsurl.h"
+#include "utils/config.h"
+#include "content/fetch.h"
+#include "desktop/browser.h"
+
+#include "riscos/gui.h"
+#include "riscos/uri.h"
+#include "riscos/url_protocol.h"
+
+/**
+ * Handle a Message_InetSuiteOpenURL.
+ */
+
+void ro_url_message_received(wimp_message *message)
+{
+ char *url;
+ int i;
+ inetsuite_message_open_url *url_message =
+ (inetsuite_message_open_url*) &message->data;
+ os_error *error;
+ nsurl *nsurl;
+ nserror errorns;
+
+ /* If the url_message->indirect.tag is non-zero,
+ * then the message data is contained within the message block.
+ */
+ if (url_message->indirect.tag != 0) {
+ url = strndup(url_message->url, 236);
+ if (!url) {
+ ro_warn_user("NoMemory", 0);
+ return;
+ }
+ /* terminate at first control character */
+ for (i = 0; !iscntrl(url[i]); i++)
+ ;
+ url[i] = 0;
+
+ } else {
+ if (!url_message->indirect.url.offset) {
+ LOG("no URL in message");
+ return;
+ }
+ if (28 < message->size &&
+ url_message->indirect.body_file.offset) {
+ LOG("POST for URL message not implemented");
+ return;
+ }
+ if (url_message->indirect.url.offset < 28 ||
+ 236 <= url_message->indirect.url.offset) {
+ LOG("external pointers in URL message unimplemented");
+ /* these messages have never been seen in the wild,
+ * and there is the problem of invalid addresses which
+ * would cause an abort */
+ return;
+ }
+
+ url = strndup((char *) url_message +
+ url_message->indirect.url.offset,
+ 236 - url_message->indirect.url.offset);
+ if (!url) {
+ ro_warn_user("NoMemory", 0);
+ return;
+ }
+ for (i = 0; !iscntrl(url[i]); i++)
+ ;
+ url[i] = 0;
+ }
+
+ if (nsurl_create(url, &nsurl) != NSERROR_OK) {
+ free(url);
+ return;
+ }
+
+ if (!fetch_can_fetch(nsurl)) {
+ nsurl_unref(nsurl);
+ free(url);
+ return;
+ }
+
+ free(url);
+
+ /* send ack */
+ message->your_ref = message->my_ref;
+ error = xwimp_send_message(wimp_USER_MESSAGE_ACKNOWLEDGE, message,
+ message->sender);
+ if (error) {
+ LOG("xwimp_send_message: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+
+ /* create new browser window */
+ errorns = browser_window_create(BW_CREATE_HISTORY,
+ nsurl,
+ NULL,
+ NULL,
+ NULL);
+
+
+ nsurl_unref(nsurl);
+ if (errorns != NSERROR_OK) {
+ ro_warn_user(messages_get_errorcode(errorns), 0);
+ }
+}
+
+
+/**
+ * Broadcast an ANT URL message.
+ */
+
+void ro_url_broadcast(const char *url)
+{
+ inetsuite_full_message_open_url_direct message;
+ os_error *error;
+ int len = strlen(url) + 1;
+
+ /* If URL is too long, then forget ANT and try URI, instead */
+ if (236 < len) {
+ ro_uri_launch(url);
+ return;
+ }
+
+ message.size = ((20+len+3) & ~3);
+ message.your_ref = 0;
+ message.action = message_INET_SUITE_OPEN_URL;
+ strncpy(message.url, url, 235);
+ message.url[235] = 0;
+ error = xwimp_send_message(wimp_USER_MESSAGE_RECORDED,
+ (wimp_message *) &message, 0);
+ if (error) {
+ LOG("xwimp_send_message: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+}
+
+
+/**
+ * Launch a program to handle an URL, using the ANT protocol
+ * Alias$URLOpen_ system.
+ */
+
+void ro_url_load(const char *url)
+{
+ char *command;
+ char *colon;
+ os_error *error;
+
+ colon = strchr(url, ':');
+ if (!colon) {
+ LOG("invalid url '%s'", url);
+ return;
+ }
+
+ command = malloc(40 + (colon - url) + strlen(url));
+ if (!command) {
+ ro_warn_user("NoMemory", 0);
+ return;
+ }
+
+ sprintf(command, "Alias$URLOpen_%.*s", (int) (colon - url), url);
+ if (!getenv(command)) {
+ free(command);
+ return;
+ }
+
+ sprintf(command, "URLOpen_%.*s %s", (int) (colon - url), url, url);
+
+ error = xwimp_start_task(command, 0);
+ if (error) {
+ LOG("xwimp_start_task: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+
+ free(command);
+}
+
+
+/**
+ * Handle a bounced Message_InetSuiteOpenURL.
+ */
+
+void ro_url_bounce(wimp_message *message)
+{
+ inetsuite_message_open_url *url_message =
+ (inetsuite_message_open_url*) &message->data;
+
+ /* ant broadcast bounced -> try uri broadcast / load */
+ ro_uri_launch(url_message->url);
+}
+
diff --git a/frontends/riscos/url_protocol.h b/frontends/riscos/url_protocol.h
new file mode 100644
index 000000000..c066981f7
--- /dev/null
+++ b/frontends/riscos/url_protocol.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2003 John M Bell <jmb202@ecs.soton.ac.uk>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * ANT URL launching protocol (interface).
+ */
+
+#ifndef _NETSURF_RISCOS_URL_H_
+#define _NETSURF_RISCOS_URL_H_
+
+#include "utils/config.h"
+
+#include "oslib/wimp.h"
+
+void ro_url_message_received(wimp_message *message);
+void ro_url_broadcast(const char *url);
+void ro_url_load(const char *url);
+void ro_url_bounce(wimp_message *message);
+
+#endif
diff --git a/frontends/riscos/url_suggest.c b/frontends/riscos/url_suggest.c
new file mode 100644
index 000000000..3f6b6b54d
--- /dev/null
+++ b/frontends/riscos/url_suggest.c
@@ -0,0 +1,239 @@
+/*
+ * Copyright 2010 Stephen Fryatt <stevef@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * URL Suggestion Menu (implementation).
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "oslib/wimp.h"
+#include "content/content_type.h"
+#include "content/urldb.h"
+
+#include "riscos/menus.h"
+#include "riscos/url_suggest.h"
+#include "utils/messages.h"
+
+struct url_suggest_item {
+ const char *url; /*< The URL being stored. */
+ unsigned int weight; /*< A weight assigned to the URL. */
+ struct url_suggest_item *next; /*< The next URL in the list. */
+};
+
+static bool ro_gui_url_suggest_callback(nsurl *url,
+ const struct url_data *data);
+
+static int suggest_entries;
+static time_t suggest_time;
+static struct url_suggest_item *suggest_list;
+
+static wimp_MENU(URL_SUGGEST_MAX_URLS) url_suggest_menu_block;
+wimp_menu *ro_gui_url_suggest_menu = (wimp_menu *) &url_suggest_menu_block;
+
+
+/**
+ * Initialise the URL suggestion menu. This MUST be called before anything
+ * tries to use the URL menu.
+ *
+ * \return true if initialisation was OK; else false.
+ */
+
+bool ro_gui_url_suggest_init(void)
+{
+ ro_gui_url_suggest_menu->title_data.indirected_text.text =
+ (char *) messages_get("URLSuggest");
+ ro_gui_menu_init_structure((wimp_menu *) ro_gui_url_suggest_menu,
+ URL_SUGGEST_MAX_URLS);
+
+ suggest_entries = 0;
+
+ return true;
+}
+
+
+/**
+ * Check if there is a URL suggestion menu available for use.
+ *
+ * \todo Ideally this should be able to decide if there's a menu
+ * available without actually having to build it all.
+ *
+ * \return true if the menu has entries; else false.
+ */
+
+bool ro_gui_url_suggest_get_menu_available(void)
+{
+ return ro_gui_url_suggest_prepare_menu();
+}
+
+
+/**
+ * Builds the URL suggestion menu. This is called by ro_gui_menu_create() when
+ * it is asked to display the url_suggest_menu.
+ *
+ * /return true if the menu has entries; else false.
+ */
+
+bool ro_gui_url_suggest_prepare_menu(void)
+{
+ struct url_suggest_item *list, *next;
+
+ /* Fetch the URLs we want to include from URLdb. */
+
+ suggest_entries = 0;
+ suggest_list = NULL;
+ suggest_time = time(NULL);
+
+ urldb_iterate_entries(ro_gui_url_suggest_callback);
+
+ /* If any menu entries were found, put them into the menu. The list
+ * is in reverse order, last to first, so the menu is filled backwards.
+ * Entries from the list are freed as we go.
+ */
+
+ assert(suggest_entries <= URL_SUGGEST_MAX_URLS);
+
+ if (suggest_entries > 0) {
+ int i = suggest_entries;
+
+ list = suggest_list;
+ suggest_list = NULL;
+
+ while (list != NULL && i > 0) {
+ i--;
+
+ ro_gui_url_suggest_menu->entries[i].menu_flags = 0;
+ ro_gui_url_suggest_menu->
+ entries[i].data.indirected_text.text =
+ (char *) list->url;
+ ro_gui_url_suggest_menu->
+ entries[i].data.indirected_text.size =
+ strlen(list->url) + 1;
+
+ next = list->next;
+ free(list);
+ list = next;
+ }
+
+ assert(i == 0);
+
+ ro_gui_url_suggest_menu->entries[0].menu_flags |=
+ wimp_MENU_TITLE_INDIRECTED;
+ ro_gui_url_suggest_menu->
+ entries[suggest_entries - 1].menu_flags |=
+ wimp_MENU_LAST;
+
+ return true;
+ }
+
+ return false;
+}
+
+
+/**
+ * Callback function for urldb_iterate_entries
+ *
+ * \param url URL which matches
+ * \param data Data associated with URL
+ * \return true to continue iteration, false otherwise
+ */
+
+bool ro_gui_url_suggest_callback(nsurl *url, const struct url_data *data)
+{
+ int count;
+ unsigned int weight;
+ struct url_suggest_item **list, *new;
+
+ /* Ignore unvisited URLs, and those that don't apply to HTML or Text. */
+
+ if (data->visits == 0 || (data->type != CONTENT_HTML &&
+ data->type != CONTENT_TEXTPLAIN))
+ return true;
+
+ /* Calculate a weight for the URL. */
+
+ weight = (suggest_time - data->last_visit) / data->visits;
+
+ /* Hunt through those URLs already found to see if we want to add
+ * this one. Smaller weights carry higher priority.
+ *
+ * The list is sorted into reverse order, so that lowest weight
+ * items are nearest the head. Therefore, items are dropped from
+ * the head, making things simpler.
+ */
+
+ list = &suggest_list;
+ count = 0;
+
+ while (*list != NULL && weight < (*list)->weight) {
+ list = &((*list)->next);
+ count++;
+ }
+
+ if (count > 0 || suggest_entries < URL_SUGGEST_MAX_URLS) {
+ new = (struct url_suggest_item *)
+ malloc(sizeof(struct url_suggest_item));
+
+ if (new != NULL) {
+ suggest_entries++;
+ /* TODO: keeping pointers to URLdb data is bad.
+ * should be nsurl_ref(url) or
+ * take a copy of the string. */
+ new->url = nsurl_access(url);
+ new->weight = weight;
+ new->next = *list;
+
+ *list = new;
+ }
+ }
+
+ /* If adding the URL gave us too many menu items, drop the lowest
+ * priority ones until the list is the right length again.
+ */
+
+ while (suggest_list != NULL && suggest_entries > URL_SUGGEST_MAX_URLS) {
+ struct url_suggest_item *old = suggest_list;
+ suggest_list = suggest_list->next;
+
+ free(old);
+ suggest_entries--;
+ }
+
+ return true;
+}
+
+
+/**
+ * Process a selection from the URL Suggest menu.
+ *
+ * \param *selection The menu selection.
+ * \return Pointer to the URL that was selected, or NULL for none.
+ */
+
+const char *ro_gui_url_suggest_get_selection(wimp_selection *selection)
+{
+ const char *url = NULL;
+
+ if (selection->items[0] >= 0)
+ url = ro_gui_url_suggest_menu->entries[selection->items[0]].
+ data.indirected_text.text;
+
+ return url;
+}
diff --git a/frontends/riscos/url_suggest.h b/frontends/riscos/url_suggest.h
new file mode 100644
index 000000000..738cb9bf7
--- /dev/null
+++ b/frontends/riscos/url_suggest.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2010 Stephen Fryatt <stevef@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * URL Suggestion Menu (interface).
+ */
+
+#ifndef _NETSURF_RISCOS_URL_SUGGEST_H_
+#define _NETSURF_RISCOS_URL_SUGGEST_H_
+
+#include "oslib/wimp.h"
+
+#define URL_SUGGEST_MAX_URLS 16
+
+extern wimp_menu *ro_gui_url_suggest_menu;
+
+bool ro_gui_url_suggest_init(void);
+bool ro_gui_url_suggest_get_menu_available(void);
+bool ro_gui_url_suggest_prepare_menu(void);
+const char *ro_gui_url_suggest_get_selection(wimp_selection *selection);
+
+#endif
+
diff --git a/frontends/riscos/wimp.c b/frontends/riscos/wimp.c
new file mode 100644
index 000000000..2579c672e
--- /dev/null
+++ b/frontends/riscos/wimp.c
@@ -0,0 +1,1134 @@
+/*
+ * Copyright 2004, 2005 Richard Wilson <info@tinct.net>
+ * Copyright 2008 John Tytgat <joty@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * General RISC OS WIMP/OS library functions (implementation).
+ */
+
+#include <assert.h>
+#include <locale.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include "oslib/colourtrans.h"
+#include "oslib/os.h"
+#include "oslib/osfile.h"
+#include "oslib/wimp.h"
+#include "oslib/wimpextend.h"
+#include "oslib/wimpspriteop.h"
+
+#include "utils/log.h"
+#include "utils/utf8.h"
+
+#include "riscos/gui.h"
+#include "riscos/oslib_pre7.h"
+#include "riscos/wimp.h"
+#include "riscos/ucstables.h"
+
+
+static void ro_gui_wimp_cache_furniture_sizes(wimp_w w);
+static size_t ro_gui_strlen(const char *str);
+static int ro_gui_strncmp(const char *s1, const char *s2, size_t len);
+
+static wimpextend_furniture_sizes furniture_sizes;
+static wimp_w furniture_window = NULL;
+
+/**
+ * Gets the horizontal scrollbar height
+ *
+ * \param w the window to read (or NULL to read a cached value)
+ */
+int ro_get_hscroll_height(wimp_w w)
+{
+ ro_gui_wimp_cache_furniture_sizes(w);
+ return furniture_sizes.border_widths.y0;
+}
+
+
+/**
+ * Gets the vertical scrollbar width
+ *
+ * \param w the window to read (or NULL to read a cached value)
+ */
+int ro_get_vscroll_width(wimp_w w)
+{
+ ro_gui_wimp_cache_furniture_sizes(w);
+ return furniture_sizes.border_widths.x1;
+}
+
+
+/**
+ * Gets the title bar height
+ *
+ * \param w the window to read (or NULL to read a cached value)
+ */
+int ro_get_title_height(wimp_w w)
+{
+ ro_gui_wimp_cache_furniture_sizes(w);
+ return furniture_sizes.border_widths.y1;
+}
+
+/**
+ * Caches window furniture information
+ *
+ * \param w the window to cache information from
+ * \return true on success, false on error (default values cached)
+ */
+void ro_gui_wimp_cache_furniture_sizes(wimp_w w)
+{
+ os_error *error;
+
+ if (furniture_window == w)
+ return;
+ furniture_window = w;
+ furniture_sizes.w = w;
+ furniture_sizes.border_widths.y0 = 40;
+ furniture_sizes.border_widths.x1 = 40;
+ error = xwimpextend_get_furniture_sizes(&furniture_sizes);
+ if (error) {
+ LOG("xwimpextend_get_furniture_sizes: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+}
+
+
+/**
+ * Reads a modes EIG factors.
+ *
+ * \param[in] mode mode to read EIG factors for, or -1 for current
+ * \param[out] xeig The x eig value
+ * \param[out] yeig The y eig value
+ * \return true on success else false.
+ */
+bool ro_gui_wimp_read_eig_factors(os_mode mode, int *xeig, int *yeig)
+{
+ os_error *error;
+
+ error = xos_read_mode_variable(mode, os_MODEVAR_XEIG_FACTOR, xeig, 0);
+ if (error) {
+ LOG("xos_read_mode_variable: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("MiscError", error->errmess);
+ return false;
+ }
+ error = xos_read_mode_variable(mode, os_MODEVAR_YEIG_FACTOR, yeig, 0);
+ if (error) {
+ LOG("xos_read_mode_variable: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("MiscError", error->errmess);
+ return false;
+ }
+ return true;
+}
+
+
+/**
+ * Converts the supplied os_coord from OS units to pixels.
+ *
+ * \param os_units values to convert
+ * \param mode mode to use EIG factors for, or -1 for current
+ */
+void ro_convert_os_units_to_pixels(os_coord *os_units, os_mode mode)
+{
+ int xeig = 1, yeig = 1;
+
+ ro_gui_wimp_read_eig_factors(mode, &xeig, &yeig);
+ os_units->x = ((os_units->x + (1 << xeig) - 1) >> xeig);
+ os_units->y = ((os_units->y + (1 << yeig) - 1) >> yeig);
+}
+
+
+/**
+ * Converts the supplied os_coord from pixels to OS units.
+ *
+ * \param pixels values to convert
+ * \param mode mode to use EIG factors for, or -1 for current
+ */
+void ro_convert_pixels_to_os_units(os_coord *pixels, os_mode mode)
+{
+ int xeig = 1, yeig = 1;
+
+ ro_gui_wimp_read_eig_factors(mode, &xeig, &yeig);
+ pixels->x = (pixels->x << xeig);
+ pixels->y = (pixels->y << yeig);
+}
+
+
+/**
+ * Redraws an icon
+ *
+ * \param w window handle
+ * \param i icon handle
+ */
+
+#define ro_gui_redraw_icon(w, i) xwimp_set_icon_state(w, i, 0, 0)
+
+
+/**
+ * Forces an icon to be redrawn entirely (ie not just updated).
+ *
+ * \param w window handle
+ * \param i icon handle
+ */
+void ro_gui_force_redraw_icon(wimp_w w, wimp_i i)
+{
+ wimp_icon_state ic;
+ os_error *error;
+
+ /* Get the icon data
+ */
+ ic.w = w;
+ ic.i = i;
+ error = xwimp_get_icon_state(&ic);
+ if (error) {
+ LOG("xwimp_get_icon_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+ error = xwimp_force_redraw(w, ic.icon.extent.x0, ic.icon.extent.y0,
+ ic.icon.extent.x1, ic.icon.extent.y1);
+ if (error) {
+ LOG("xwimp_force_redraw: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+}
+
+
+/**
+ * Read the contents of a text or sprite icon.
+ *
+ * \param w window handle
+ * \param i icon handle
+ * \return NUL terminated string in icon
+ *
+ * If the icon contains direct text then the returned data will
+ * be invalidated by the next call to this function. Therefore,
+ * all client calls to this function must either copy the string or
+ * ensure that this function is not called again until they are
+ * finished with the string data returned.
+ *
+ * \todo this doesn't do local encoding -> UTF-8 to match what is done in
+ * ro_gui_set_icon_string.
+ */
+const char *ro_gui_get_icon_string(wimp_w w, wimp_i i)
+{
+ static wimp_icon_state ic;
+ os_error *error;
+ char *itext;
+
+ ic.w = w;
+ ic.i = i;
+ error = xwimp_get_icon_state(&ic);
+ if (error) {
+ LOG("xwimp_get_icon_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return NULL;
+ }
+ itext = (ic.icon.flags & wimp_ICON_INDIRECTED)
+ ? ic.icon.data.indirected_text.text : ic.icon.data.text;
+ /* Guarantee NUL termination. */
+ itext[ro_gui_strlen(itext)] = '\0';
+
+ return itext;
+}
+
+
+/**
+ * Set the contents of a text or sprite icon to a string.
+ *
+ * \param w window handle
+ * \param i icon handle
+ * \param text NUL terminated string (copied)
+ * \param is_utf8 When true, the given string is UTF-8 encoded and will be
+ * converted to local encoding currently used by the Wimp. When false, the
+ * given string is assumed to be in local encoding in use by the Wimp.
+ */
+void ro_gui_set_icon_string(wimp_w w, wimp_i i, const char *text, bool is_utf8)
+{
+ wimp_caret caret;
+ wimp_icon_state ic;
+ os_error *error;
+ size_t old_len, new_len;
+ char *local_text = NULL;
+ const char *text_for_icon;
+ char *dst_text;
+ size_t dst_max_len;
+ unsigned int button_type;
+
+ if (is_utf8) {
+ nserror err;
+ /* convert text to local encoding */
+ err = utf8_to_local_encoding(text, 0, &local_text);
+ if (err != NSERROR_OK) {
+ /* A bad encoding should never happen, so assert this */
+ assert(err != NSERROR_BAD_ENCODING);
+ LOG("utf8_to_enc failed");
+ /* Paranoia */
+ local_text = NULL;
+ }
+ text_for_icon = local_text ? local_text : text;
+ }
+ else
+ text_for_icon = text;
+ new_len = strlen(text_for_icon);
+
+ /* get the icon data */
+ ic.w = w;
+ ic.i = i;
+ error = xwimp_get_icon_state(&ic);
+ if (error) {
+ LOG("xwimp_get_icon_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ goto exit;
+ }
+
+ if (ic.icon.flags & wimp_ICON_INDIRECTED) {
+ dst_text = ic.icon.data.indirected_text.text;
+ dst_max_len = ic.icon.data.indirected_text.size;
+ }
+ else {
+ dst_text = ic.icon.data.text;
+ dst_max_len = sizeof(ic.icon.data.text);
+ }
+ old_len = ro_gui_strlen(dst_text);
+ assert(old_len < dst_max_len);
+
+ /* check that the existing text is not the same as the updated text
+ * to stop flicker */
+ if (dst_max_len) {
+ if (!ro_gui_strncmp(dst_text, text_for_icon, dst_max_len))
+ goto exit;
+
+ /* copy the text across */
+ strncpy(dst_text, text_for_icon, dst_max_len - 1);
+ dst_text[dst_max_len - 1] = '\0';
+
+ /* handle the caret being in the icon */
+ button_type = (ic.icon.flags & wimp_ICON_BUTTON_TYPE)
+ >> wimp_ICON_BUTTON_TYPE_SHIFT;
+ if ((button_type == wimp_BUTTON_WRITABLE) ||
+ (button_type == wimp_BUTTON_WRITE_CLICK_DRAG)) {
+ error = xwimp_get_caret_position(&caret);
+ if (error) {
+ LOG("xwimp_get_caret_position: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ goto exit;
+ }
+ if ((caret.w == w) && (caret.i == i)) {
+ if ((size_t)caret.index > new_len
+ || (size_t)caret.index == old_len)
+ caret.index = new_len;
+ error = xwimp_set_caret_position(w, i, caret.pos.x,
+ caret.pos.y, -1, caret.index);
+ if (error) {
+ LOG("xwimp_set_caret_position: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+ }
+ }
+ ro_gui_redraw_icon(w, i);
+ }
+
+exit:
+ free(local_text);
+}
+
+
+/**
+ * Set the contents of an icon to a number.
+ *
+ * \param w window handle
+ * \param i icon handle
+ * \param value value
+ */
+void ro_gui_set_icon_integer(wimp_w w, wimp_i i, int value)
+{
+ char buffer[20]; // Big enough for 64-bit int
+
+ setlocale(LC_NUMERIC, "");
+
+ sprintf(buffer, "%d", value);
+
+ setlocale(LC_NUMERIC, "C");
+
+ ro_gui_set_icon_string(w, i, buffer, true);
+}
+
+
+/**
+ * Set the contents of an icon to a number.
+ *
+ * \param w window handle
+ * \param i icon handle
+ * \param value value to use in icon.
+ * \param decimal_places The number of decimal places to use.
+ */
+void ro_gui_set_icon_decimal(wimp_w w, wimp_i i, int value, int decimal_places)
+{
+ char buffer[20]; // Big enough for 64-bit int
+
+ setlocale(LC_NUMERIC, "");
+
+ switch (decimal_places) {
+ case 0:
+ sprintf(buffer, "%d", value);
+ break;
+ case 1:
+ sprintf(buffer, "%.1f", (float)value / 10);
+ break;
+ case 2:
+ sprintf(buffer, "%.2f", (float)value / 100);
+ break;
+ default:
+ assert(!"Unsupported decimal format");
+ break;
+ }
+
+ setlocale(LC_NUMERIC, "C");
+
+ ro_gui_set_icon_string(w, i, buffer, true);
+}
+
+
+/**
+ * Get the contents of an icon as a number.
+ *
+ * \param w window handle
+ * \param i icon handle
+ * \param decimal_places number of places to show.
+ * \return value used.
+ */
+int ro_gui_get_icon_decimal(wimp_w w, wimp_i i, int decimal_places)
+{
+ double value;
+ int multiple = 1;
+
+ for (; decimal_places > 0; decimal_places--)
+ multiple *= 10;
+
+ setlocale(LC_NUMERIC, "");
+
+ value = atof(ro_gui_get_icon_string(w, i)) * multiple;
+
+ setlocale(LC_NUMERIC, "C");
+
+ return (int)value;
+}
+
+
+/**
+ * Set the selected state of an icon.
+ *
+ * \param w window handle
+ * \param i icon handle
+ * \param state selected state
+ */
+void ro_gui_set_icon_selected_state(wimp_w w, wimp_i i, bool state)
+{
+ os_error *error;
+ if (ro_gui_get_icon_selected_state(w, i) == state) return;
+ error = xwimp_set_icon_state(w, i,
+ (state ? wimp_ICON_SELECTED : 0), wimp_ICON_SELECTED);
+ if (error) {
+ LOG("xwimp_set_icon_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+}
+
+/**
+ * Gets the selected state of an icon.
+ *
+ * \param w window handle
+ * \param i icon handle
+ */
+bool ro_gui_get_icon_selected_state(wimp_w w, wimp_i i)
+{
+ os_error *error;
+ wimp_icon_state ic;
+ ic.w = w;
+ ic.i = i;
+ error = xwimp_get_icon_state(&ic);
+ if (error) {
+ LOG("xwimp_get_icon_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return false;
+ }
+ return ((ic.icon.flags & wimp_ICON_SELECTED) != 0);
+}
+
+
+/**
+ * Set the shaded state of an icon.
+ *
+ * \param w window handle
+ * \param i icon handle
+ * \param state shaded state
+ */
+void ro_gui_set_icon_shaded_state(wimp_w w, wimp_i i, bool state)
+{
+ wimp_caret caret;
+ os_error *error;
+
+ /* update the state */
+ if (ro_gui_get_icon_shaded_state(w, i) == state)
+ return;
+ error = xwimp_set_icon_state(w, i,
+ (state ? wimp_ICON_SHADED : 0), wimp_ICON_SHADED);
+ if (error) {
+ LOG("xwimp_get_icon_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+ if (!state)
+ return;
+
+ /* ensure the caret is not in a shaded icon */
+ error = xwimp_get_caret_position(&caret);
+ if (error) {
+ LOG("xwimp_get_caret_position: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+ if ((caret.w != w) || (caret.i != i))
+ return;
+ /* move the caret to the first avaiable writable */
+ if (ro_gui_set_caret_first(w))
+ return;
+ /* lose the caret */
+ error = xwimp_set_caret_position((wimp_w)-1, (wimp_i)-1, -1, -1, -1, -1);
+ if (error) {
+ LOG("xwimp_set_caret_position: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+}
+
+
+/**
+ * Gets the shaded state of an icon.
+ *
+ * \param w window handle
+ * \param i icon handle
+ */
+bool ro_gui_get_icon_shaded_state(wimp_w w, wimp_i i)
+{
+ wimp_icon_state ic;
+ ic.w = w;
+ ic.i = i;
+ xwimp_get_icon_state(&ic);
+ return (ic.icon.flags & wimp_ICON_SHADED) != 0;
+}
+
+
+/**
+ * Set the deleted state of an icon.
+ *
+ * \param w window handle
+ * \param i icon handle
+ * \param state shaded state
+ */
+void ro_gui_set_icon_deleted_state(wimp_w w, wimp_i i, bool state)
+{
+ wimp_caret caret;
+ os_error *error;
+
+ /* update the state */
+ if (ro_gui_get_icon_deleted_state(w, i) == state)
+ return;
+ error = xwimp_set_icon_state(w, i,
+ (state ? wimp_ICON_DELETED : 0), wimp_ICON_DELETED);
+ if (error) {
+ LOG("xwimp_get_icon_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+ if (!state)
+ return;
+
+ /* ensure the caret is not in a shaded icon */
+ error = xwimp_get_caret_position(&caret);
+ if (error) {
+ LOG("xwimp_get_caret_position: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+ if ((caret.w != w) || (caret.i != i))
+ return;
+ /* move the caret to the first avaiable writable */
+ if (ro_gui_set_caret_first(w))
+ return;
+ /* lose the caret */
+ error = xwimp_set_caret_position((wimp_w)-1, (wimp_i)-1, -1, -1, -1, -1);
+ if (error) {
+ LOG("xwimp_set_caret_position: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+}
+
+
+/**
+ * Gets the deleted state of an icon.
+ *
+ * \param w window handle
+ * \param i icon handle
+ */
+bool ro_gui_get_icon_deleted_state(wimp_w w, wimp_i i)
+{
+ wimp_icon_state ic;
+ ic.w = w;
+ ic.i = i;
+ xwimp_get_icon_state(&ic);
+ return (ic.icon.flags & wimp_ICON_DELETED) != 0;
+}
+
+
+/**
+ * Set the button type of an icon.
+ *
+ * \param w window handle
+ * \param i icon handle
+ * \param type button type
+ */
+void ro_gui_set_icon_button_type(wimp_w w, wimp_i i, int type)
+{
+ os_error *error;
+ error = xwimp_set_icon_state(w, i, wimp_ICON_BUTTON_TYPE,
+ (type << wimp_ICON_BUTTON_TYPE_SHIFT));
+ if (error) {
+ LOG("xwimp_set_icon_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+}
+
+
+/**
+ * Set an icon's sprite
+ *
+ * \param w window handle
+ * \param i icon handle
+ * \param area sprite area containing sprite
+ * \param name name of sprite in area (in local encoding)
+ */
+void ro_gui_set_icon_sprite(wimp_w w, wimp_i i, osspriteop_area *area,
+ const char *name)
+{
+ wimp_icon_state ic;
+ os_error *error;
+
+ /* get the icon data */
+ ic.w = w;
+ ic.i = i;
+ error = xwimp_get_icon_state(&ic);
+ if (error) {
+ LOG("xwimp_get_icon_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ /* copy the name across */
+ if (ic.icon.data.indirected_text.size) {
+ strncpy(ic.icon.data.indirected_text.text, name,
+ (unsigned int)ic.icon.data.indirected_text.size - 1);
+ ic.icon.data.indirected_text.text[
+ ic.icon.data.indirected_text.size - 1] = '\0';
+ }
+
+ ic.icon.data.indirected_sprite.area = area;
+
+ ro_gui_redraw_icon(w, i);
+}
+
+
+/**
+ * Set a window title
+ *
+ * \param w window handle
+ * \param text new title (copied)
+ */
+void ro_gui_set_window_title(wimp_w w, const char *text)
+{
+ wimp_window_info_base window;
+ os_error *error;
+ char *title_local_enc;
+ nserror err;
+
+ /* Get the window details
+ */
+ window.w = w;
+ error = xwimp_get_window_info_header_only((wimp_window_info *)&window);
+ if (error) {
+ LOG("xwimp_get_window_info: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ /* convert text to local encoding */
+ err = utf8_to_local_encoding(text, 0, &title_local_enc);
+ if (err != NSERROR_OK) {
+ /* A bad encoding should never happen,
+ * so assert this */
+ assert(err != NSERROR_BAD_ENCODING);
+ LOG("utf8_to_enc failed");
+ return;
+ }
+
+ /* Set the title string
+ */
+ strncpy(window.title_data.indirected_text.text, title_local_enc,
+ (unsigned int)window.title_data.indirected_text.size
+ - 1);
+ window.title_data.indirected_text.text[
+ window.title_data.indirected_text.size - 1] = '\0';
+
+ /* Redraw accordingly
+ */
+ error = xwimp_force_redraw_title(w);
+ if (error) {
+ LOG("xwimp_force_redraw_title: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ free(title_local_enc);
+}
+
+
+/**
+ * Places the caret in the first available icon
+ *
+ * \param w the window to place the caret in
+ * \return true if the caret was placed, false otherwise
+ */
+bool ro_gui_set_caret_first(wimp_w w)
+{
+ int icon, b;
+ wimp_window_state win_state;
+ wimp_window_info_base window;
+ wimp_icon_state state;
+ os_error *error;
+
+ /* check the window is open */
+ win_state.w = w;
+ error = xwimp_get_window_state(&win_state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return false;
+ }
+ if (!(win_state.flags & wimp_WINDOW_OPEN))
+ return false;
+
+ /* get the window details for the icon count */
+ window.w = w;
+ error = xwimp_get_window_info_header_only((wimp_window_info *)&window);
+ if (error) {
+ LOG("xwimp_get_window_info: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return false;
+ }
+
+ /* work through all the icons */
+ state.w = w;
+ for (icon = 0; icon < window.icon_count; icon++) {
+ state.i = icon;
+ error = xwimp_get_icon_state(&state);
+ if (error) {
+ LOG("xwimp_get_icon_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return false;
+ }
+
+ /* ignore if it's shaded or not writable */
+ if (state.icon.flags & wimp_ICON_SHADED)
+ continue;
+ b = (state.icon.flags >> wimp_ICON_BUTTON_TYPE_SHIFT) & 0xf;
+ if ((b != wimp_BUTTON_WRITE_CLICK_DRAG) &&
+ (b != wimp_BUTTON_WRITABLE))
+ continue;
+
+ /* move the caret */
+ error = xwimp_set_caret_position(w, icon, 0, 0, -1,
+ strlen(state.icon.data.indirected_text.text));
+ if (error) {
+ LOG("xwimp_set_caret_position: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+ return true;
+ }
+ return false;
+}
+
+
+/**
+ * Load a sprite file into memory.
+ *
+ * \param pathname file to load
+ * \return sprite area, or 0 on memory exhaustion or error and error reported
+ */
+
+osspriteop_area *ro_gui_load_sprite_file(const char *pathname)
+{
+ int len;
+ fileswitch_object_type obj_type;
+ osspriteop_area *area;
+ os_error *error;
+
+ error = xosfile_read_stamped_no_path(pathname,
+ &obj_type, 0, 0, &len, 0, 0);
+ if (error) {
+ LOG("xosfile_read_stamped_no_path: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("MiscError", error->errmess);
+ return 0;
+ }
+ if (obj_type != fileswitch_IS_FILE) {
+ ro_warn_user("FileError", pathname);
+ return 0;
+ }
+
+ area = malloc(len + 4);
+ if (!area) {
+ ro_warn_user("NoMemory", 0);
+ return 0;
+ }
+
+ area->size = len + 4;
+ area->sprite_count = 0;
+ area->first = 16;
+ area->used = 16;
+
+ error = xosspriteop_load_sprite_file(osspriteop_USER_AREA,
+ area, pathname);
+ if (error) {
+ LOG("xosspriteop_load_sprite_file: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("MiscError", error->errmess);
+ free(area);
+ return 0;
+ }
+
+ return area;
+}
+
+
+/**
+ * Check if a sprite is present in the Wimp sprite pool.
+ *
+ * \param sprite name of sprite
+ * \return true if the sprite is present
+ */
+
+bool ro_gui_wimp_sprite_exists(const char *sprite)
+{
+ static char last_sprite_found[16];
+ os_error *error;
+
+ /* make repeated calls fast */
+ if (!strncmp(sprite, last_sprite_found, sizeof(last_sprite_found)))
+ return true;
+
+ /* fallback if not known to exist */
+ error = xwimpspriteop_select_sprite(sprite, 0);
+ if (error) {
+ if (error->errnum != error_SPRITE_OP_DOESNT_EXIST) {
+ LOG("xwimpspriteop_select_sprite: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("MiscError", error->errmess);
+ }
+ return false;
+ }
+ snprintf(last_sprite_found, sizeof(last_sprite_found), sprite);
+ return true;
+}
+
+
+/**
+ * Locate a sprite in the Wimp sprite pool, returning a pointer to it.
+ *
+ * \param name sprite name
+ * \param sprite receives pointer to sprite if found
+ * \return error ptr iff not found
+ */
+
+os_error *ro_gui_wimp_get_sprite(const char *name, osspriteop_header **sprite)
+{
+ osspriteop_area *rom_base, *ram_base;
+ os_error *error;
+
+ error = xwimp_base_of_sprites(&rom_base, &ram_base);
+ if (error) return error;
+
+ error = xosspriteop_select_sprite(osspriteop_USER_AREA,
+ ram_base, (osspriteop_id)name, sprite);
+
+ if (error && error->errnum == error_SPRITE_OP_DOESNT_EXIST)
+ error = xosspriteop_select_sprite(osspriteop_USER_AREA,
+ rom_base, (osspriteop_id)name, sprite);
+
+ return error;
+}
+
+
+/**
+ * Get the dimensions of a sprite
+ *
+ * \param *area The sprite area to use.
+ * \param *sprite Pointer to the sprite name.
+ * \param *width Return the sprite width.
+ * \param *height Return the sprite height.
+ * \return true if successful; else false.
+ */
+
+bool ro_gui_wimp_get_sprite_dimensions(osspriteop_area *area, char *sprite,
+ int *width, int *height)
+{
+ os_error *error = NULL;
+ os_mode mode;
+ os_coord dimensions;
+
+ dimensions.x = 0;
+ dimensions.y = 0;
+
+ if (area != (osspriteop_area *) -1)
+ error = xosspriteop_read_sprite_info(osspriteop_USER_AREA,
+ area, (osspriteop_id) sprite,
+ &dimensions.x, &dimensions.y, 0, &mode);
+
+ if (error != NULL || area == (osspriteop_area *) -1)
+ error = xwimpspriteop_read_sprite_info(sprite,
+ &dimensions.x, &dimensions.y, 0, &mode);
+
+ if (error == NULL) {
+ ro_convert_pixels_to_os_units(&dimensions, mode);
+ if (width != NULL)
+ *width = dimensions.x;
+ if (height != NULL)
+ *height = dimensions.y;
+ } else if (error->errnum != error_SPRITE_OP_DOESNT_EXIST) {
+ LOG("xosspriteop_read_sprite_info: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("MiscError", error->errmess);
+ return false;
+ }
+
+ return true;
+}
+
+
+/**
+ * Performs simple user redraw for a window.
+ *
+ * \param redraw wimp draw
+ * \param user_fill whether to fill the redraw area
+ * \param user_colour the colour to use when filling
+ */
+
+void ro_gui_user_redraw(wimp_draw *redraw, bool user_fill,
+ os_colour user_colour)
+{
+ os_error *error;
+ osbool more;
+
+ error = xwimp_redraw_window(redraw, &more);
+ if (error) {
+ LOG("xwimp_redraw_window: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+ while (more) {
+ if (user_fill) {
+ error = xcolourtrans_set_gcol(user_colour,
+ colourtrans_SET_BG_GCOL,
+ os_ACTION_OVERWRITE, 0, 0);
+ if (error) {
+ LOG("xcolourtrans_set_gcol: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("MiscError", error->errmess);
+ }
+ os_clg();
+ }
+ error = xwimp_get_rectangle(redraw, &more);
+ if (error) {
+ LOG("xwimp_get_rectangle: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+ }
+}
+
+
+/**
+ * Sets whether a piece of window furniture is present for a window.
+ *
+ * \param w the window to modify
+ * \param bic_mask the furniture flags to clear
+ * \param xor_mask the furniture flags to toggle
+ */
+void ro_gui_wimp_update_window_furniture(wimp_w w, wimp_window_flags bic_mask,
+ wimp_window_flags xor_mask)
+{
+ wimp_window_state state;
+ wimp_w parent;
+ bits linkage;
+ os_error *error;
+ bool open;
+
+ state.w = w;
+ error = xwimp_get_window_state_and_nesting(&state, &parent, &linkage);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ open = state.flags & wimp_WINDOW_OPEN;
+ state.flags &= ~(63 << 16); /* clear bits 16-21 */
+ state.flags &= ~bic_mask;
+ state.flags ^= xor_mask;
+ if (!open)
+ state.next = wimp_HIDDEN;
+ error = xwimp_open_window_nested_with_flags(&state, parent, linkage);
+ if (error) {
+ LOG("xwimp_open_window: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ if (!open) {
+ error = xwimp_close_window(w);
+ if (error) {
+ LOG("xwimp_close_window: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+ }
+}
+
+
+/**
+ * Checks whether a piece of window furniture is present for a window.
+ *
+ * \param w the window to modify
+ * \param mask the furniture flags to check
+ */
+bool ro_gui_wimp_check_window_furniture(wimp_w w, wimp_window_flags mask)
+{
+ wimp_window_state state;
+ os_error *error;
+
+ state.w = w;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return false;
+ }
+ return state.flags & mask;
+}
+
+/**
+ * RO GUI-specific strlen, for control character terminated strings
+ *
+ * \param str The string to measure the length of
+ * \return The length of the string
+ */
+size_t ro_gui_strlen(const char *str)
+{
+ const char *str_begin;
+
+ if (str == NULL)
+ return 0;
+
+ for (str_begin = str; *str++ >= ' '; /* */)
+ /* */;
+
+ return str - str_begin - 1;
+}
+
+/**
+ * RO GUI-specific strncmp, for control character terminated strings
+ *
+ * \param s1 The first string for comparison
+ * \param s2 The second string for comparison
+ * \param len Maximum number of bytes to be checked
+ * \return 0 for equal strings up to len bytes; pos for s1 being bigger than
+ * s2; neg for s1 being smaller than s2.
+ */
+int ro_gui_strncmp(const char *s1, const char *s2, size_t len)
+{
+ while (len--) {
+ char c1 = *s1++;
+ char c2 = *s2++;
+ if (c1 < ' ' || c2 < ' ')
+ return (c1 < ' ' ? 0 : c1) - (c2 < ' ' ? 0 : c2);
+ int diff = c1 - c2;
+ if (diff)
+ return diff;
+ }
+ return 0;
+}
+
+
+/**
+ * Generic window scroll event handler.
+ *
+ * \param *scroll Pointer to Scroll Event block.
+ */
+
+void ro_gui_scroll(wimp_scroll *scroll)
+{
+ os_error *error;
+ int x = scroll->visible.x1 - scroll->visible.x0 - 32;
+ int y = scroll->visible.y1 - scroll->visible.y0 - 32;
+
+ switch (scroll->xmin) {
+ case wimp_SCROLL_PAGE_LEFT:
+ scroll->xscroll -= x;
+ break;
+ case wimp_SCROLL_COLUMN_LEFT:
+ scroll->xscroll -= 100;
+ break;
+ case wimp_SCROLL_COLUMN_RIGHT:
+ scroll->xscroll += 100;
+ break;
+ case wimp_SCROLL_PAGE_RIGHT:
+ scroll->xscroll += x;
+ break;
+ default:
+ scroll->xscroll += (x * (scroll->xmin>>2)) >> 2;
+ break;
+ }
+
+ switch (scroll->ymin) {
+ case wimp_SCROLL_PAGE_UP:
+ scroll->yscroll += y;
+ break;
+ case wimp_SCROLL_LINE_UP:
+ scroll->yscroll += 100;
+ break;
+ case wimp_SCROLL_LINE_DOWN:
+ scroll->yscroll -= 100;
+ break;
+ case wimp_SCROLL_PAGE_DOWN:
+ scroll->yscroll -= y;
+ break;
+ default:
+ scroll->yscroll += (y * (scroll->ymin>>2)) >> 2;
+ break;
+ }
+
+ error = xwimp_open_window((wimp_open *) scroll);
+ if (error) {
+ LOG("xwimp_open_window: 0x%x: %s", error->errnum, error->errmess);
+ }
+}
+
diff --git a/frontends/riscos/wimp.h b/frontends/riscos/wimp.h
new file mode 100644
index 000000000..fdcf67b95
--- /dev/null
+++ b/frontends/riscos/wimp.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2004 Richard Wilson <not_ginger_matt@users.sourceforge.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * General RISC OS WIMP/OS library functions (interface).
+ */
+
+
+#ifndef _NETSURF_RISCOS_WIMP_H_
+#define _NETSURF_RISCOS_WIMP_H_
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "oslib/os.h"
+#include "oslib/wimp.h"
+#include "rufl.h"
+
+
+int ro_get_hscroll_height(wimp_w w);
+int ro_get_vscroll_width(wimp_w w);
+int ro_get_title_height(wimp_w w);
+bool ro_gui_wimp_read_eig_factors(os_mode mode, int *xeig, int *yeig);
+void ro_convert_os_units_to_pixels(os_coord *os_units, os_mode mode);
+void ro_convert_pixels_to_os_units(os_coord *pixels, os_mode mode);
+
+#define ro_gui_redraw_icon(w, i) xwimp_set_icon_state(w, i, 0, 0)
+void ro_gui_force_redraw_icon(wimp_w w, wimp_i i);
+const char *ro_gui_get_icon_string(wimp_w w, wimp_i i);
+void ro_gui_set_icon_string(wimp_w w, wimp_i i, const char *text, bool is_utf8);
+
+void ro_gui_set_icon_integer(wimp_w w, wimp_i i, int value);
+void ro_gui_set_icon_decimal(wimp_w w, wimp_i i, int value, int decimal_places);
+int ro_gui_get_icon_decimal(wimp_w w, wimp_i i, int decimal_places);
+
+void ro_gui_set_icon_selected_state(wimp_w w, wimp_i i, bool state);
+bool ro_gui_get_icon_selected_state(wimp_w w, wimp_i i);
+void ro_gui_set_icon_shaded_state(wimp_w w, wimp_i i, bool state);
+bool ro_gui_get_icon_shaded_state(wimp_w w, wimp_i i);
+void ro_gui_set_icon_deleted_state(wimp_w w, wimp_i i, bool state);
+bool ro_gui_get_icon_deleted_state(wimp_w w, wimp_i i);
+void ro_gui_set_icon_button_type(wimp_w w, wimp_i i, int type);
+void ro_gui_set_icon_sprite(wimp_w w, wimp_i i, osspriteop_area *area,
+ const char *name);
+void ro_gui_set_window_title(wimp_w w, const char *title);
+bool ro_gui_set_caret_first(wimp_w w);
+void ro_gui_open_window_centre(wimp_w parent, wimp_w child);
+
+osspriteop_area *ro_gui_load_sprite_file(const char *pathname);
+bool ro_gui_wimp_sprite_exists(const char *sprite);
+os_error *ro_gui_wimp_get_sprite(const char *name, osspriteop_header **sprite);
+bool ro_gui_wimp_get_sprite_dimensions(osspriteop_area *area, char *sprite,
+ int *width, int *height);
+
+wimp_w ro_gui_set_window_background_colour(wimp_w window, wimp_colour background);
+void ro_gui_set_icon_colours(wimp_w window, wimp_i icon,
+ wimp_colour foreground, wimp_colour background);
+void ro_gui_user_redraw(wimp_draw *redraw, bool user_fill, os_colour user_colour);
+void ro_gui_wimp_update_window_furniture(wimp_w w, wimp_window_flags bic_mask,
+ wimp_window_flags xor_mask);
+bool ro_gui_wimp_check_window_furniture(wimp_w w, wimp_window_flags mask);
+
+void ro_gui_scroll(wimp_scroll *scroll);
+
+#endif
+
diff --git a/frontends/riscos/wimp_event.c b/frontends/riscos/wimp_event.c
new file mode 100644
index 000000000..015e87baf
--- /dev/null
+++ b/frontends/riscos/wimp_event.c
@@ -0,0 +1,1814 @@
+/*
+ * Copyright 2005 Richard Wilson <info@tinct.net>
+ * Copyright 2010, 2011 Stephen Fryatt <stevef@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Automated RISC OS WIMP event handling (implementation).
+ */
+
+#include <assert.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "oslib/os.h"
+#include "oslib/osbyte.h"
+#include "oslib/serviceinternational.h"
+#include "oslib/wimp.h"
+
+#include "utils/log.h"
+
+#include "riscos/gui.h"
+#include "riscos/dialog.h"
+#include "riscos/menus.h"
+#include "riscos/ucstables.h"
+#include "riscos/wimp.h"
+#include "riscos/wimp_event.h"
+#include "riscos/wimputils.h"
+
+#define WIN_HASH_SIZE 32
+#define WIN_HASH(w) (((unsigned)(w) >> 5) % WIN_HASH_SIZE)
+
+typedef enum {
+ EVENT_NUMERIC_FIELD,
+ EVENT_TEXT_FIELD,
+ EVENT_UP_ARROW,
+ EVENT_DOWN_ARROW,
+ EVENT_MENU_GRIGHT,
+ EVENT_CHECKBOX,
+ EVENT_RADIO,
+ EVENT_BUTTON,
+ EVENT_CANCEL,
+ EVENT_OK
+} event_type;
+
+struct event_data_numeric_field {
+ int stepping;
+ int min;
+ int max;
+ int decimal_places;
+};
+
+struct event_data_menu_gright {
+ wimp_i field;
+ wimp_menu *menu;
+};
+
+struct icon_event {
+ event_type type;
+ wimp_i i;
+ union {
+ struct event_data_numeric_field numeric_field;
+ struct event_data_menu_gright menu_gright;
+ wimp_i linked_icon;
+ int radio_group;
+ void (*callback)(wimp_pointer *pointer);
+ } data;
+ union {
+ char *textual;
+ bool boolean;
+ } previous_value;
+ bool previous_shaded;
+ struct icon_event *next;
+};
+
+struct event_window {
+ wimp_w w;
+ bool (*ok_click)(wimp_w w);
+ bool (*mouse_click)(wimp_pointer *pointer);
+ bool (*keypress)(wimp_key *key);
+ void (*open_window)(wimp_open *open);
+ void (*close_window)(wimp_w w);
+ void (*redraw_window)(wimp_draw *redraw);
+ void (*scroll_window)(wimp_scroll *scroll);
+ void (*entering_window)(wimp_entering *entering);
+ bool (*menu_prepare)(wimp_w w, wimp_i i, wimp_menu *m,
+ wimp_pointer *p);
+ bool (*menu_selection)(wimp_w w, wimp_i i, wimp_menu *m,
+ wimp_selection *s, menu_action a);
+ void (*menu_warning)(wimp_w w, wimp_i i, wimp_menu *m,
+ wimp_selection *s, menu_action a);
+ void (*menu_close)(wimp_w w, wimp_i i, wimp_menu *m);
+ wimp_menu *window_menu;
+ bool window_menu_auto;
+ bool window_menu_iconbar;
+ const char *help_prefix;
+ const char *(*get_help_suffix)(wimp_w w, wimp_i i, os_coord *pos,
+ wimp_mouse_state buttons);
+ void *user_data;
+ struct icon_event *first;
+ struct event_window *next;
+ int max_radio_group;
+};
+
+static void ro_gui_wimp_event_ok_click(struct event_window *window,
+ wimp_mouse_state state);
+static struct event_window *ro_gui_wimp_event_get_window(wimp_w w);
+static struct event_window *ro_gui_wimp_event_find_window(wimp_w w);
+static struct icon_event *ro_gui_wimp_event_get_event(wimp_w w, wimp_i i,
+ event_type type);
+static void ro_gui_wimp_event_prepare_gright_menu(wimp_w w, struct icon_event *event);
+static struct event_window *ro_gui_wimp_event_remove_window(wimp_w w);
+
+static struct event_window *ro_gui_wimp_event_windows[WIN_HASH_SIZE];
+
+static wimp_w ro_gui_wimp_event_submenu;
+
+/**
+ * Memorises the current state of any registered components in a window.
+ *
+ * \param w the window to memorise
+ * \return true on success, false on memory exhaustion or for an unknown window
+ */
+bool ro_gui_wimp_event_memorise(wimp_w w)
+{
+ struct event_window *window;
+ struct icon_event *event;
+ bool error = false;
+
+ window = ro_gui_wimp_event_find_window(w);
+ if (!window)
+ return false;
+
+ for (event = window->first; event; event = event->next) {
+ switch (event->type) {
+ case EVENT_NUMERIC_FIELD:
+ case EVENT_TEXT_FIELD:
+ if (event->previous_value.textual)
+ free(event->previous_value.textual);
+ event->previous_value.textual = strdup(
+ ro_gui_get_icon_string(window->w, event->i));
+ if (!event->previous_value.textual) {
+ error = true;
+ LOG("Unable to store state for icon %i", event->i);
+ }
+ break;
+ case EVENT_CHECKBOX:
+ case EVENT_RADIO:
+ event->previous_value.boolean =
+ ro_gui_get_icon_selected_state(window->w, event->i);
+ break;
+ default:
+ break;
+ }
+ if (event->type != EVENT_MENU_GRIGHT)
+ event->previous_shaded = ro_gui_get_icon_shaded_state(window->w,
+ event->i);
+ }
+ return !error;
+}
+
+
+/**
+ * Restore the state of any registered components in a window to their memorised state.
+ *
+ * \param w the window to restore
+ * \return true on success, false for an unknown window
+ */
+bool ro_gui_wimp_event_restore(wimp_w w)
+{
+ struct event_window *window;
+ struct icon_event *event;
+
+ window = ro_gui_wimp_event_find_window(w);
+ if (!window)
+ return false;
+
+ for (event = window->first; event; event = event->next) {
+ switch (event->type) {
+ case EVENT_NUMERIC_FIELD:
+ case EVENT_TEXT_FIELD:
+ if (event->previous_value.textual)
+ ro_gui_set_icon_string(window->w, event->i,
+ event->previous_value.textual, true);
+ break;
+ case EVENT_CHECKBOX:
+ case EVENT_RADIO:
+ ro_gui_set_icon_selected_state(window->w, event->i,
+ event->previous_value.boolean);
+ break;
+ default:
+ break;
+ }
+ if (event->type != EVENT_MENU_GRIGHT)
+ ro_gui_set_icon_shaded_state(window->w, event->i,
+ event->previous_shaded);
+ }
+ return true;
+}
+
+
+/**
+ * Ensures all values are within pre-determined boundaries.
+ *
+ * \param w the window to memorise
+ * \return true on success, false for an unknown window
+ */
+bool ro_gui_wimp_event_validate(wimp_w w)
+{
+ struct event_window *window;
+ struct icon_event *event;
+ int value;
+
+ window = ro_gui_wimp_event_find_window(w);
+ if (!window)
+ return false;
+
+ for (event = window->first; event; event = event->next) {
+ switch (event->type) {
+ case EVENT_NUMERIC_FIELD:
+ value = ro_gui_get_icon_decimal(window->w, event->i,
+ event->data.numeric_field.decimal_places);
+ if (value < event->data.numeric_field.min)
+ value = event->data.numeric_field.min;
+ else if (value > event->data.numeric_field.max)
+ value = event->data.numeric_field.max;
+ ro_gui_set_icon_decimal(window->w, event->i, value,
+ event->data.numeric_field.decimal_places);
+ break;
+ default:
+ break;
+ }
+ }
+ return true;
+}
+
+/**
+ * Transfer event data from one window to another. This can be used as an
+ * alternative to ro_gui_wimp_event_finalise() and re-registering, if
+ * events need to continue across a change of window handle.
+ *
+ * All aspects of the registered events MUST remain the same in the new
+ * window!
+ *
+ * \param from The current window, which is to be deleted.
+ * \param to The window to which the events should transfer.
+ * \return true on success; false for an unknown window.
+ */
+
+bool ro_gui_wimp_event_transfer(wimp_w from, wimp_w to)
+{
+ struct event_window *window;
+ int h;
+
+ LOG("Transferring all events from window 0x%x to window 0x%x", (unsigned int)from, (unsigned int)to);
+
+ window = ro_gui_wimp_event_remove_window(from);
+ if (window == NULL || window->w != from)
+ return false;
+
+ h = WIN_HASH(to);
+ window->w = to;
+ window->next = ro_gui_wimp_event_windows[h];
+ ro_gui_wimp_event_windows[h] = window;
+
+ ro_gui_menu_window_changed(from, to);
+
+ return true;
+}
+
+/**
+ * Free any resources associated with a window.
+ *
+ * \param w the window to free resources for
+ */
+void ro_gui_wimp_event_finalise(wimp_w w)
+{
+ struct event_window *window;
+ struct icon_event *event;
+
+ LOG("Removing all events for window 0x%x", (unsigned int)w);
+ window = ro_gui_wimp_event_remove_window(w);
+ if (!window)
+ return;
+
+ while (window->first) {
+ event = window->first;
+ window->first = event->next;
+ switch (event->type) {
+ case EVENT_NUMERIC_FIELD:
+ case EVENT_TEXT_FIELD:
+ if (event->previous_value.textual)
+ free(event->previous_value.textual);
+ event->previous_value.textual = NULL;
+ break;
+ default:
+ break;
+ }
+ free(event);
+ }
+ free(window);
+ return;
+}
+
+
+/**
+ * Free any resources associated with a specific icon in a window.
+ *
+ * \param w The window containing the icon.
+ * \param i The icon to free resources for.
+ */
+
+void ro_gui_wimp_event_deregister(wimp_w w, wimp_i i)
+{
+ struct event_window *window;
+ struct icon_event *event, *parent, *child;
+
+ LOG("Removing all events for window 0x%x, icon %d", (unsigned int)w, (int)i);
+ window = ro_gui_wimp_event_get_window(w);
+ if (!window)
+ return;
+
+ /* Remove any events that apply to the given icon. */
+
+ event = window->first;
+ parent = NULL;
+
+ while (event != NULL) {
+ child = event->next;
+
+ if (event->i == i) {
+ LOG("Removing event 0x%x", (unsigned int)event);
+
+ if (parent == NULL)
+ window->first = child;
+ else
+ parent->next = child;
+
+ switch (event->type) {
+ case EVENT_NUMERIC_FIELD:
+ case EVENT_TEXT_FIELD:
+ if (event->previous_value.textual)
+ free(event->previous_value.textual);
+ event->previous_value.textual = NULL;
+ break;
+ default:
+ break;
+ }
+
+ free(event);
+ } else {
+ parent = event;
+ }
+
+ event = child;
+ }
+}
+
+
+/**
+ * Set the associated help prefix for a given window.
+ *
+ * \param w the window to get the prefix for
+ * \param help_prefix the prefix to associate with the window (used directly)
+ * \return true on success, or NULL for memory exhaustion
+ */
+bool ro_gui_wimp_event_set_help_prefix(wimp_w w, const char *help_prefix)
+{
+ struct event_window *window;
+
+ window = ro_gui_wimp_event_get_window(w);
+ if (!window)
+ return false;
+ window->help_prefix = help_prefix;
+ return true;
+}
+
+
+/**
+ * Get the associated help prefix.
+ *
+ * \param w the window to get the prefix for
+ * \return the associated prefix, or NULL
+ */
+const char *ro_gui_wimp_event_get_help_prefix(wimp_w w)
+{
+ struct event_window *window;
+
+ window = ro_gui_wimp_event_find_window(w);
+ if (window)
+ return window->help_prefix;
+ return NULL;
+}
+
+
+/**
+ * Register a handler to decode help suffixes for a given window.
+ *
+ */
+
+bool ro_gui_wimp_event_register_help_suffix(wimp_w w,
+ const char *(*get_help_suffix)(wimp_w w, wimp_i i,
+ os_coord *pos, wimp_mouse_state buttons))
+{
+ struct event_window *window;
+
+ window = ro_gui_wimp_event_get_window(w);
+ if (!window)
+ return false;
+ window->get_help_suffix = get_help_suffix;
+ return true;
+}
+
+
+/**
+ * Get the associated help suffix.
+ *
+ * \param w The window to get the suffix for
+ * \param i The icon
+ * \param pos The os coordinates
+ * \param buttons The button state.
+ * \return The associated prefix, or NULL
+ */
+
+const char *ro_gui_wimp_event_get_help_suffix(wimp_w w, wimp_i i,
+ os_coord *pos, wimp_mouse_state buttons)
+{
+ struct event_window *window;
+
+ window = ro_gui_wimp_event_find_window(w);
+ if (window == NULL || window->get_help_suffix == NULL)
+ return NULL;
+
+ return window->get_help_suffix(w, i, pos, buttons);
+}
+
+
+/**
+ * Sets the user data associated with a window.
+ *
+ * \param w the window to associate the data with
+ * \param user the data to associate
+ */
+bool ro_gui_wimp_event_set_user_data(wimp_w w, void *user)
+{
+ struct event_window *window;
+
+ window = ro_gui_wimp_event_get_window(w);
+ if (!window)
+ return false;
+ window->user_data = user;
+ return true;
+
+}
+
+
+/**
+ * Gets the user data associated with a window.
+ *
+ * \param w the window to retrieve the data for
+ * \return the associated data, or NULL
+ */
+void *ro_gui_wimp_event_get_user_data(wimp_w w)
+{
+ struct event_window *window;
+
+ window = ro_gui_wimp_event_find_window(w);
+ if (window)
+ return window->user_data;
+ return NULL;
+}
+
+
+/**
+ * Handles a menu selection event.
+ *
+ * (At present, this is tied to being called from menus.c and relies on that
+ * module decoding the menu into an action code. If menus.c loses its
+ * menu handling in the future, such decoding might need to move here.)
+ *
+ * The order of execution is:
+ *
+ * 1. Try to match the menu to a pop-up menu. If successful, handle it as
+ * this.
+ * 2. Try to match the menu to a window menu. If successful, pass control to
+ * the menu's registered _select handler.
+ * 3. Return event as unhandled.
+ *
+ * \param w the window to owning the menu
+ * \param i the icon owning the menu
+ * \param menu the menu that has been selected
+ * \param selection the selection information
+ * \param action the menu action info from menus.c
+ * \return true if the menu is OK for an Adjust re-open;
+ * else false.
+ */
+bool ro_gui_wimp_event_menu_selection(wimp_w w, wimp_i i, wimp_menu *menu,
+ wimp_selection *selection, menu_action action)
+{
+ struct event_window *window;
+ struct icon_event *event;
+ wimp_menu_entry *menu_entry;
+ wimp_key key;
+ os_error *error;
+ wimp_caret caret;
+ wimp_icon_state ic;
+ unsigned int button_type;
+ bool prepared;
+
+ window = ro_gui_wimp_event_find_window(w);
+ if (window == NULL)
+ return false;
+
+ /* Start by looking for an icon event that matches. If there isn't one,
+ * then return details for an unconnected menu. It's up to the
+ * event recipient to sort out if this is a window menu or not, based
+ * on the menu handle passed back.
+ */
+
+ for (event = window->first; event; event = event->next)
+ if ((event->type == EVENT_MENU_GRIGHT) && (event->i == i))
+ break;
+ if (!event) {
+ if (window->menu_selection)
+ window->menu_selection(window->w, wimp_ICON_WINDOW,
+ menu, selection, action);
+
+ /* Prepare the menu pending a possible Adjust click. */
+ if (window->menu_prepare)
+ if (!window->menu_prepare(window->w, wimp_ICON_WINDOW,
+ menu, NULL))
+ return false;
+
+ return true;
+ }
+
+ menu_entry = &menu->entries[selection->items[0]];
+ for (i = 1; selection->items[i] != -1; i++)
+ menu_entry = &menu_entry->sub_menu->
+ entries[selection->items[i]];
+
+ /* if the entry is already ticked then we do nothing */
+ if (menu_entry->menu_flags & wimp_MENU_TICKED)
+ return true;
+
+ ro_gui_set_icon_string(window->w, event->data.menu_gright.field,
+ menu_entry->data.indirected_text.text, false);
+ if (window->menu_selection)
+ window->menu_selection(window->w, event->i, menu,
+ selection, action);
+ prepared = true;
+ if (window->menu_prepare)
+ prepared = window->menu_prepare(window->w, event->i,
+ menu, NULL);
+ if (prepared)
+ ro_gui_wimp_event_prepare_gright_menu(window->w, event);
+
+ /* set the caret for writable icons and send a CTRL+U keypress to
+ * stimulate activity if needed */
+ ic.w = window->w;
+ ic.i = event->data.menu_gright.field;
+ error = xwimp_get_icon_state(&ic);
+ if (error) {
+ LOG("xwimp_get_icon_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return false;
+ }
+ button_type = (ic.icon.flags & wimp_ICON_BUTTON_TYPE) >> wimp_ICON_BUTTON_TYPE_SHIFT;
+ if ((button_type != wimp_BUTTON_WRITABLE) &&
+ (button_type != wimp_BUTTON_WRITE_CLICK_DRAG))
+ return prepared;
+ error = xwimp_get_caret_position(&caret);
+ if (error) {
+ LOG("xwimp_get_caret_position: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return false;
+ }
+ if ((caret.w != window->w) || (caret.i != event->data.menu_gright.field)) {
+ error = xwimp_set_caret_position(window->w, event->data.menu_gright.field,
+ -1, -1, -1, strlen(menu_entry->data.indirected_text.text));
+ if (error) {
+ LOG("xwimp_set_caret_position: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+ }
+ if (window->keypress) {
+ key.w = window->w;
+ key.c = 21; // ctrl+u
+ window->keypress(&key);
+ }
+ return prepared;
+}
+
+
+/**
+ * Handles a mouse click event in a registered window.
+ *
+ * The order of execution is:
+ *
+ * 1. If a menu click, and the window has an automatic window menu, this is
+ * processed immediately.
+ * 2. Any registered mouse_click routine (see ro_gui_wimp_register_mouse_click())
+ * 3. If the current icon is not registered with a type then it is assumed that no
+ * action is necessary, and the click is deemed to have been handled.
+ * 4. If the registered mouse_click routine returned false, or there was no registered
+ * routine then the automated action for the registered icon type is performed
+ *
+ * \param pointer the current pointer state
+ * \return true if the event was handled, false otherwise
+ */
+bool ro_gui_wimp_event_mouse_click(wimp_pointer *pointer)
+{
+ struct event_window *window;
+ struct icon_event *event;
+ wimp_w w;
+ struct icon_event *search;
+ int current, step, stepping, min, max, decimal_places;
+ wimp_window_state open;
+ wimp_caret caret;
+ bool prepared;
+
+ w = pointer->w;
+ window = ro_gui_wimp_event_find_window(w);
+ if (!window)
+ return false;
+
+ /* Menu clicks take priority if there is an auto menu defined. */
+ if ((pointer->buttons == wimp_CLICK_MENU) &&
+ (window->window_menu != NULL) &&
+ (window->window_menu_auto)) {
+ ro_gui_wimp_event_process_window_menu_click(pointer);
+ return true;
+ }
+
+ /* registered routines take next priority */
+ if ((window->mouse_click) && (window->mouse_click(pointer)))
+ return true;
+
+ for (event = window->first; event; event = event->next)
+ if (event->i == pointer->i)
+ break;
+ if (!event)
+ return true;
+
+ switch (event->type) {
+ case EVENT_NUMERIC_FIELD:
+ case EVENT_TEXT_FIELD:
+ break;
+ case EVENT_UP_ARROW:
+ case EVENT_DOWN_ARROW:
+ for (search = window->first; search; search = search->next)
+ if (search->i == event->data.linked_icon) break;
+ if (!search) {
+ LOG("Incorrect reference.");
+ return false;
+ }
+ stepping = search->data.numeric_field.stepping;
+ min = search->data.numeric_field.min;
+ max = search->data.numeric_field.max;
+ decimal_places = search->data.numeric_field.decimal_places;
+
+ if (pointer->buttons & wimp_CLICK_ADJUST)
+ step = -stepping;
+ else if (pointer->buttons & wimp_CLICK_SELECT)
+ step = stepping;
+ else
+ return true;
+ if (event->type == EVENT_DOWN_ARROW)
+ step = -step;
+
+ current = ro_gui_get_icon_decimal(pointer->w, event->data.linked_icon,
+ decimal_places);
+ current += step;
+ if (current < min)
+ current = min;
+ if (current > max)
+ current = max;
+ ro_gui_set_icon_decimal(pointer->w, event->data.linked_icon, current,
+ decimal_places);
+ break;
+ case EVENT_MENU_GRIGHT:
+ /* if there's already a menu open then we assume that we are part of it.
+ * to follow the standard RISC OS behaviour we add a 'send to the back'
+ * button, then close the menu (which closes us) and then finally
+ * re-open ourselves. ugh! */
+ if (current_menu != NULL) {
+ os_error *error;
+ open.w = pointer->w;
+ error = xwimp_get_window_state(&open);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return false;
+ }
+ error = xwimp_get_caret_position(&caret);
+ if (error) {
+ LOG("xwimp_get_caret_position: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return false;
+ }
+ ro_gui_dialog_add_persistent(current_menu_window,
+ pointer->w);
+ ro_gui_menu_destroy();
+ error = xwimp_open_window(PTR_WIMP_OPEN(&open));
+ if (error) {
+ LOG("xwimp_open_window: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return false;
+ }
+ if (caret.w == pointer->w) {
+ error = xwimp_set_caret_position(caret.w,
+ caret.i,
+ caret.pos.x, caret.pos.y,
+ -1, caret.index);
+ if (error) {
+ LOG("xwimp_set_caret_position: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+ }
+ }
+ /* display the menu */
+
+ prepared = true;
+ if (window->menu_prepare != NULL)
+ prepared = window->menu_prepare(pointer->w, pointer->i,
+ event->data.menu_gright.menu, pointer);
+ if (prepared) {
+ ro_gui_wimp_event_prepare_gright_menu(pointer->w, event);
+ ro_gui_popup_menu(event->data.menu_gright.menu, pointer->w, pointer->i);
+ }
+ break;
+ case EVENT_CHECKBOX:
+ break;
+ case EVENT_RADIO:
+ for (search = window->first; search; search = search->next)
+ if ((search->type == EVENT_RADIO) &&
+ (search->data.radio_group ==
+ event->data.radio_group))
+ ro_gui_set_icon_selected_state(pointer->w,
+ search->i, (search == event));
+ break;
+ case EVENT_BUTTON:
+ if (event->data.callback)
+ event->data.callback(pointer);
+ break;
+ case EVENT_CANCEL:
+ if (pointer->buttons & wimp_CLICK_SELECT) {
+ ro_gui_dialog_close(pointer->w);
+ ro_gui_wimp_event_close_window(pointer->w);
+ ro_gui_menu_destroy();
+ } else {
+ ro_gui_wimp_event_restore(pointer->w);
+ }
+ break;
+ case EVENT_OK:
+ ro_gui_wimp_event_ok_click(window, pointer->buttons);
+ break;
+ }
+ return true;
+}
+
+
+/**
+ * Prepare a menu ready for use
+ *
+ * /param w the window owning the menu
+ * /param event the icon event owning the menu
+ */
+void ro_gui_wimp_event_prepare_gright_menu(wimp_w w, struct icon_event *event)
+{
+ int i;
+ const char *text;
+ unsigned int button_type;
+ wimp_icon_state ic;
+ wimp_menu *menu;
+ os_error *error;
+
+ /* if the linked icon is not writable then we set the ticked state
+ * of the menu item that matches the contents */
+ ic.w = w;
+ ic.i = event->data.menu_gright.field;
+ error = xwimp_get_icon_state(&ic);
+ if (error) {
+ LOG("xwimp_get_icon_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+ button_type = (ic.icon.flags & wimp_ICON_BUTTON_TYPE)
+ >> wimp_ICON_BUTTON_TYPE_SHIFT;
+ if ((button_type == wimp_BUTTON_WRITABLE) ||
+ (button_type == wimp_BUTTON_WRITE_CLICK_DRAG))
+ return;
+ text = ro_gui_get_icon_string(w, event->data.menu_gright.field);
+ menu = event->data.menu_gright.menu;
+ i = 0;
+ do {
+ if (!strcmp(menu->entries[i].data.indirected_text.text, text))
+ menu->entries[i].menu_flags |= wimp_MENU_TICKED;
+ else
+ menu->entries[i].menu_flags &= ~wimp_MENU_TICKED;
+ } while (!(menu->entries[i++].menu_flags & wimp_MENU_LAST));
+}
+
+
+/**
+ * Perform the necessary actions following a click on the OK button.
+ *
+ * /param window the window to perform the action on
+ * /param state the mouse button state
+ */
+void ro_gui_wimp_event_ok_click(struct event_window *window,
+ wimp_mouse_state state)
+{
+ struct icon_event *search;
+
+ for (search = window->first; search; search = search->next)
+ if (search->type == EVENT_OK) {
+ if (ro_gui_get_icon_shaded_state(window->w, search->i))
+ return;
+ break;
+ }
+ ro_gui_wimp_event_validate(window->w);
+
+ if (window->ok_click)
+ if (!window->ok_click(window->w))
+ return;
+
+ if (state & wimp_CLICK_SELECT) {
+ ro_gui_dialog_close(window->w);
+ ro_gui_wimp_event_close_window(window->w);
+ ro_gui_menu_destroy();
+ } else {
+ ro_gui_wimp_event_memorise(window->w);
+ }
+}
+
+
+/**
+ * Handle any registered keypresses, and the standard RISC OS ones
+ *
+ * \param key the key state
+ * \return true if keypress handled, false otherwise
+ */
+bool ro_gui_wimp_event_keypress(wimp_key *key)
+{
+ static const int *ucstable = NULL;
+ static int alphabet = 0;
+ static uint32_t wc = 0; /* buffer for UTF8 alphabet */
+ static int shift = 0;
+ struct event_window *window;
+ struct icon_event *event;
+ wimp_pointer pointer;
+ wimp_key k;
+ uint32_t c = (uint32_t) key->c;
+ int t_alphabet;
+ os_error *error;
+
+ window = ro_gui_wimp_event_find_window(key->w);
+ if (!window)
+ return false;
+
+ /* copy key state so we can corrupt it safely */
+ memcpy(&k, key, sizeof(wimp_key));
+
+ /* In order to make sensible use of the 0x80->0xFF ranges specified
+ * in the RISC OS 8bit alphabets, we must do the following:
+ *
+ * + Read the currently selected alphabet
+ * + Acquire a pointer to the UCS conversion table for this alphabet:
+ * + Try using ServiceInternational 8 to get the table
+ * + If that fails, use our internal table (see ucstables.c)
+ * + If the alphabet is not UTF8 and the conversion table exists:
+ * + Lookup UCS code in the conversion table
+ * + If code is -1 (i.e. undefined):
+ * + Use codepoint 0xFFFD instead
+ * + If the alphabet is UTF8, we must buffer input, thus:
+ * + If the keycode is < 0x80:
+ * + Handle it directly
+ * + If the keycode is a UTF8 sequence start:
+ * + Initialise the buffer appropriately
+ * + Otherwise:
+ * + OR in relevant bits from keycode to buffer
+ * + If we've received an entire UTF8 character:
+ * + Handle UCS code
+ * + Otherwise:
+ * + Simply handle the keycode directly, as there's no easy way
+ * of performing the mapping from keycode -> UCS4 codepoint.
+ */
+ error = xosbyte1(osbyte_ALPHABET_NUMBER, 127, 0, &t_alphabet);
+ if (error) {
+ LOG("failed reading alphabet: 0x%x: %s", error->errnum, error->errmess);
+ /* prevent any corruption of ucstable */
+ t_alphabet = alphabet;
+ }
+
+ if (t_alphabet != alphabet) {
+ void *ostable;
+ osbool unclaimed;
+ /* Alphabet has changed, so read UCS table location */
+ alphabet = t_alphabet;
+
+ error = xserviceinternational_get_ucs_conversion_table(
+ alphabet, &unclaimed, &ostable);
+ if (error != NULL) {
+ LOG("failed reading UCS conversion table: 0x%x: %s", error->errnum, error->errmess);
+ /* Try using our own table instead */
+ ucstable = ucstable_from_alphabet(alphabet);
+ } else if (unclaimed) {
+ /* Service wasn't claimed so use our own ucstable */
+ ucstable = ucstable_from_alphabet(alphabet);
+ } else {
+ /* Use the table provided by the OS */
+ ucstable = ostable;
+ }
+ }
+
+ if (c < 256) {
+ if (alphabet != 111 /* UTF8 */ && ucstable != NULL) {
+ /* defined in this alphabet? */
+ if (ucstable[c] == -1)
+ return true;
+
+ /* read UCS4 value out of table */
+ k.c = ucstable[c];
+ }
+ else if (alphabet == 111 /* UTF8 */) {
+ if ((c & 0x80) == 0x00 || (c & 0xC0) == 0xC0) {
+ /* UTF8 start sequence */
+ if ((c & 0xE0) == 0xC0) {
+ wc = ((c & 0x1F) << 6);
+ shift = 1;
+ return true;
+ }
+ else if ((c & 0xF0) == 0xE0) {
+ wc = ((c & 0x0F) << 12);
+ shift = 2;
+ return true;
+ }
+ else if ((c & 0xF8) == 0xF0) {
+ wc = ((c & 0x07) << 18);
+ shift = 3;
+ return true;
+ }
+ /* These next two have been removed
+ * from RFC3629, but there's no
+ * guarantee that RISC OS won't
+ * generate a UCS4 value outside the
+ * UTF16 plane, so we handle them
+ * anyway. */
+ else if ((c & 0xFC) == 0xF8) {
+ wc = ((c & 0x03) << 24);
+ shift = 4;
+ }
+ else if ((c & 0xFE) == 0xFC) {
+ wc = ((c & 0x01) << 30);
+ shift = 5;
+ }
+ else if (c >= 0x80) {
+ /* If this ever happens,
+ * RISC OS' UTF8 keyboard
+ * drivers are broken */
+ LOG("unexpected UTF8 start"" byte %x (ignoring)", c);
+ return true;
+ }
+ /* Anything else is ASCII, so just
+ * handle it directly. */
+ }
+ else {
+ if ((c & 0xC0) != 0x80) {
+ /* If this ever happens,
+ * RISC OS' UTF8 keyboard
+ * drivers are broken */
+ LOG("unexpected keycode: ""%x (ignoring)", c);
+ return true;
+ }
+
+ /* Continuation of UTF8 character */
+ wc |= ((c & 0x3F) << (6 * --shift));
+ if (shift > 0)
+ /* partial character */
+ return true;
+ else
+ /* got entire character, so
+ * fetch from buffer and
+ * handle it */
+ k.c = wc;
+ }
+ }
+ } else {
+ k.c |= IS_WIMP_KEY;
+ }
+
+ /* registered routines take priority */
+ if (window->keypress)
+ if (window->keypress(&k))
+ return true;
+
+ switch (key->c) {
+ /* Escape performs the CANCEL action (simulated click) */
+ case wimp_KEY_ESCAPE:
+ for (event = window->first; event; event = event->next) {
+ switch (event->type) {
+ case EVENT_CANCEL:
+ pointer.w = key->w;
+ pointer.i = event->i;
+ pointer.buttons = wimp_CLICK_SELECT;
+ ro_gui_wimp_event_mouse_click(&pointer);
+ return true;
+ default:
+ break;
+ }
+ }
+ return false;
+ /* CTRL+F2 closes a window with a close icon */
+ case wimp_KEY_CONTROL + wimp_KEY_F2:
+ if (!ro_gui_wimp_check_window_furniture(key->w,
+ wimp_WINDOW_CLOSE_ICON))
+ return false;
+ ro_gui_dialog_close(key->w);
+ ro_gui_wimp_event_close_window(key->w);
+ ro_gui_menu_destroy();
+ return true;
+ /* Return performs the OK action */
+ case wimp_KEY_RETURN:
+ if (!window->ok_click)
+ return false;
+ /* todo: check we aren't greyed out */
+ ro_gui_wimp_event_ok_click(window, wimp_CLICK_SELECT);
+ return true;
+ }
+ return false;
+}
+
+
+/**
+ * Handle any open window requests
+ *
+ * \param open the window open request
+ */
+bool ro_gui_wimp_event_open_window(wimp_open *open)
+{
+ struct event_window *window;
+
+ window = ro_gui_wimp_event_find_window(open->w);
+ if ((window) && (window->open_window)) {
+ window->open_window(open);
+ return true;
+ }
+ return false;
+}
+
+
+/**
+ * Service any close window handlers
+ *
+ * \param w the window being closed
+ */
+bool ro_gui_wimp_event_close_window(wimp_w w)
+{
+ struct event_window *window;
+
+ LOG("Close event received for window 0x%x", (unsigned int)w);
+ if (w == ro_gui_wimp_event_submenu)
+ ro_gui_wimp_event_submenu = 0;
+ window = ro_gui_wimp_event_find_window(w);
+ if ((window) && (window->close_window)) {
+ window->close_window(w);
+ return true;
+ }
+ return false;
+}
+
+
+/**
+ * Handle any redraw window requests
+ *
+ * \param redraw the window redraw request
+ */
+bool ro_gui_wimp_event_redraw_window(wimp_draw *redraw)
+{
+ struct event_window *window;
+
+ window = ro_gui_wimp_event_find_window(redraw->w);
+ if ((window) && (window->redraw_window)) {
+ window->redraw_window(redraw);
+ return true;
+ }
+ return false;
+}
+
+
+/**
+ * Handle any scroll window requests
+ *
+ * \param scroll the window scroll request
+ */
+bool ro_gui_wimp_event_scroll_window(wimp_scroll *scroll)
+{
+ struct event_window *window;
+
+ window = ro_gui_wimp_event_find_window(scroll->w);
+ if ((window) && (window->scroll_window)) {
+ window->scroll_window(scroll);
+ return true;
+ }
+ return false;
+}
+
+
+/**
+ * Handle any pointer entering window requests
+ *
+ * \param entering the pointer entering window request
+ */
+bool ro_gui_wimp_event_pointer_entering_window(wimp_entering *entering)
+{
+ struct event_window *window;
+
+ window = ro_gui_wimp_event_find_window(entering->w);
+ if ((window) && (window->entering_window)) {
+ window->entering_window(entering);
+ return true;
+ }
+ return false;
+}
+
+
+/**
+ * Process a Menu click in a window, by checking for a registered window
+ * menu and opening it if one is found.
+ *
+ * \param pointer The pointer block from the mouse click event.
+ * \return true if the click was actioned; else false.
+ */
+
+bool ro_gui_wimp_event_process_window_menu_click(wimp_pointer *pointer)
+{
+ struct event_window *window;
+
+ window = ro_gui_wimp_event_find_window(pointer->w);
+ if ((window) && (window->window_menu)
+ && (pointer->buttons == wimp_CLICK_MENU)) {
+ int xpos, ypos;
+
+ if (window->menu_prepare)
+ if (!window->menu_prepare(window->w, wimp_ICON_WINDOW,
+ window->window_menu, pointer))
+ return false;
+
+ if (window->window_menu_iconbar) {
+ int entry = 0;
+ int line_height = window->window_menu->height +
+ window->window_menu->gap;
+ int gap_height = 24; /* The fixed dotted line height */
+
+ xpos = pointer->pos.x;
+ ypos = 96;
+ do {
+ ypos += line_height;
+ if ((window->window_menu->
+ entries[entry].menu_flags &
+ wimp_MENU_SEPARATE) != 0)
+ ypos += gap_height;
+ } while ((window->window_menu->
+ entries[entry++].menu_flags &
+ wimp_MENU_LAST) == 0);
+ } else {
+ xpos = pointer->pos.x;
+ ypos = pointer->pos.y;
+ }
+
+ ro_gui_menu_create(window->window_menu, xpos, ypos, window->w);
+ return true;
+ }
+ return false;
+}
+
+
+/**
+ * Trigger a window's Prepare Menu event.
+ *
+ * \param w The window to use.
+ * \param i The icon to use.
+ * \param *menu The menu handle to use.
+ * \return true if the affected menu was prepared OK; else
+ * false.
+ */
+
+bool ro_gui_wimp_event_prepare_menu(wimp_w w, wimp_i i, wimp_menu *menu)
+{
+ struct event_window *window;
+
+ window = ro_gui_wimp_event_find_window(w);
+ if (window == NULL)
+ return false;
+
+ if (window->menu_prepare)
+ return window->menu_prepare(w, i, menu, NULL);
+
+ /* The menu is always OK if there's no event handler. */
+
+ return true;
+}
+
+/**
+ * Register a window menu to be (semi-)automatically handled.
+ *
+ * \param w The window to attach the menu to.
+ * \param m The menu to be attached.
+ * \param menu_auto true if the menu should be opened autimatically on
+ * Menu clicks with no task intervention; false to pass
+ * clicks to the window's Mouse Event handler and leave
+ * that to pass the menu click back to us for handling
+ * and menu opening.
+ * \param position_ibar true if the menu should open in an iconbar
+ * position; false to open at the pointer.
+ * \return true if the menu was registed ok; else false.
+ */
+
+bool ro_gui_wimp_event_register_menu(wimp_w w, wimp_menu *m,
+ bool menu_auto, bool position_ibar)
+{
+ struct event_window *window;
+
+ window = ro_gui_wimp_event_get_window(w);
+ if (!window)
+ return false;
+ window->window_menu = m;
+ window->window_menu_auto = menu_auto;
+ window->window_menu_iconbar = position_ibar;
+ return true;
+}
+
+/**
+ * Register a numeric field to be automatically handled
+ */
+bool ro_gui_wimp_event_register_numeric_field(wimp_w w, wimp_i i,
+ wimp_i up, wimp_i down,
+ int min, int max, int stepping, int decimal_places)
+{
+ struct icon_event *event;
+
+ event = ro_gui_wimp_event_get_event(w, i, EVENT_NUMERIC_FIELD);
+ if (!event)
+ return false;
+ event->data.numeric_field.min = min;
+ event->data.numeric_field.max = max;
+ event->data.numeric_field.stepping = stepping;
+ event->data.numeric_field.decimal_places = decimal_places;
+
+ event = ro_gui_wimp_event_get_event(w, up, EVENT_UP_ARROW);
+ if (!event)
+ return false;
+ event->data.linked_icon = i;
+
+ event = ro_gui_wimp_event_get_event(w, down, EVENT_DOWN_ARROW);
+ if (!event)
+ return false;
+ event->data.linked_icon = i;
+
+ return true;
+}
+
+
+/**
+ * Register a text field to be automatically handled
+ */
+bool ro_gui_wimp_event_register_text_field(wimp_w w, wimp_i i) {
+ struct icon_event *event;
+
+ event = ro_gui_wimp_event_get_event(w, i, EVENT_TEXT_FIELD);
+ if (!event)
+ return false;
+ return true;
+}
+
+
+/**
+ * Register an icon menu to be automatically handled
+ */
+bool ro_gui_wimp_event_register_menu_gright(wimp_w w, wimp_i i,
+ wimp_i gright, wimp_menu *menu)
+{
+ struct icon_event *event;
+
+ event = ro_gui_wimp_event_get_event(w, gright, EVENT_MENU_GRIGHT);
+ if (!event)
+ return false;
+ event->data.menu_gright.field = i;
+ event->data.menu_gright.menu = menu;
+
+ return ro_gui_wimp_event_register_text_field(w, i);
+}
+
+
+/**
+ * Register a checkbox to be automatically handled
+ */
+bool ro_gui_wimp_event_register_checkbox(wimp_w w, wimp_i i)
+{
+ struct icon_event *event;
+
+ event = ro_gui_wimp_event_get_event(w, i, EVENT_CHECKBOX);
+ if (!event)
+ return false;
+ return true;
+}
+
+
+/**
+ * Register a group of radio icons to be automatically handled
+ */
+bool ro_gui_wimp_event_register_radio(wimp_w w, wimp_i *i)
+{
+ struct event_window *window;
+
+ window = ro_gui_wimp_event_get_window(w);
+ if (!window)
+ return false;
+ window->max_radio_group++;
+
+ while (*i != -1) {
+ struct icon_event *event = ro_gui_wimp_event_get_event(w, *i,
+ EVENT_RADIO);
+ if (!event)
+ return false;
+ event->data.radio_group = window->max_radio_group;
+ i++;
+ }
+ return true;
+}
+
+
+/**
+ * Register a function to be called when a particular button is pressed.
+ */
+bool ro_gui_wimp_event_register_button(wimp_w w, wimp_i i,
+ void (*callback)(wimp_pointer *pointer))
+{
+ struct icon_event *event;
+
+ event = ro_gui_wimp_event_get_event(w, i, EVENT_BUTTON);
+ if (!event)
+ return false;
+ event->data.callback = callback;
+ return true;
+}
+
+
+/**
+ * Register a function to be called for the Cancel action on a window.
+ */
+bool ro_gui_wimp_event_register_cancel(wimp_w w, wimp_i i)
+{
+ struct icon_event *event;
+
+ event = ro_gui_wimp_event_get_event(w, i, EVENT_CANCEL);
+ if (!event)
+ return false;
+ return true;
+}
+
+
+/**
+ * Register a function to be called for the OK action on a window.
+ */
+bool ro_gui_wimp_event_register_ok(wimp_w w, wimp_i i,
+ bool (*callback)(wimp_w w))
+{
+ struct event_window *window;
+ struct icon_event *event;
+
+ window = ro_gui_wimp_event_get_window(w);
+ if (!window)
+ return false;
+ window->ok_click = callback;
+
+ event = ro_gui_wimp_event_get_event(w, i, EVENT_OK);
+ if (!event)
+ return false;
+ return true;
+}
+
+
+/**
+ * Register a function to be called for all mouse-clicks to icons
+ * in a window that don't have registered actions.
+ */
+bool ro_gui_wimp_event_register_mouse_click(wimp_w w,
+ bool (*callback)(wimp_pointer *pointer))
+{
+ struct event_window *window;
+
+ window = ro_gui_wimp_event_get_window(w);
+ if (!window)
+ return false;
+ window->mouse_click = callback;
+ return true;
+}
+
+
+/**
+ * Register a function to be called for all keypresses within a
+ * particular window.
+ *
+ * Important: the character code passed to the callback in key->c
+ * is UTF-32 (i.e. in the range [0, &10ffff]). WIMP keys (e.g. F1)
+ * will have bit 31 set.
+ *
+ */
+bool ro_gui_wimp_event_register_keypress(wimp_w w,
+ bool (*callback)(wimp_key *key))
+{
+ struct event_window *window;
+
+ window = ro_gui_wimp_event_get_window(w);
+ if (!window)
+ return false;
+ window->keypress = callback;
+ return true;
+}
+
+
+/**
+ * Register a function to be called for all window opening requests.
+ */
+bool ro_gui_wimp_event_register_open_window(wimp_w w,
+ void (*callback)(wimp_open *open))
+{
+ struct event_window *window;
+
+ window = ro_gui_wimp_event_get_window(w);
+ if (!window)
+ return false;
+ window->open_window = callback;
+ return true;
+}
+
+/**
+ * Register a function to be called after the window has been closed.
+ */
+bool ro_gui_wimp_event_register_close_window(wimp_w w,
+ void (*callback)(wimp_w w))
+{
+ struct event_window *window;
+
+ window = ro_gui_wimp_event_get_window(w);
+ if (!window)
+ return false;
+ window->close_window = callback;
+ return true;
+}
+
+/**
+ * Register a function to be called for all window redraw operations.
+ */
+bool ro_gui_wimp_event_register_redraw_window(wimp_w w,
+ void (*callback)(wimp_draw *redraw))
+{
+ struct event_window *window;
+
+ window = ro_gui_wimp_event_get_window(w);
+ if (!window)
+ return false;
+ window->redraw_window = callback;
+ return true;
+}
+
+/**
+ * Register a function to be called for all window scroll requests.
+ */
+
+bool ro_gui_wimp_event_register_scroll_window(wimp_w w,
+ void (*callback)(wimp_scroll *scroll))
+{
+ struct event_window *window;
+
+ window = ro_gui_wimp_event_get_window(w);
+ if (!window)
+ return false;
+ window->scroll_window = callback;
+ return true;
+}
+
+/**
+ * Register a function to be called for all pointer entering window requests.
+ */
+
+bool ro_gui_wimp_event_register_pointer_entering_window(wimp_w w,
+ void (*callback)(wimp_entering *entering))
+{
+ struct event_window *window;
+
+ window = ro_gui_wimp_event_get_window(w);
+ if (!window)
+ return false;
+ window->entering_window = callback;
+ return true;
+}
+
+/**
+ * Register a function to be called before a menu is (re-)opened.
+ *
+ * \param *w The window for which events should be returned.
+ * \param *callback A function to be called beofre the menu is
+ * (re-)opened.
+ * \return true if the menu was registed ok; else false.
+ */
+bool ro_gui_wimp_event_register_menu_prepare(wimp_w w,
+ bool (*callback)(wimp_w w, wimp_i i, wimp_menu *m,
+ wimp_pointer *p))
+{
+ struct event_window *window;
+
+ window = ro_gui_wimp_event_get_window(w);
+ if (!window)
+ return false;
+ window->menu_prepare = callback;
+ return true;
+}
+
+
+/**
+ * Register a function to be called following a menu selection.
+ *
+ * \param *w The window for which events should be returned.
+ * \param *callback A function to be called when a selection is
+ * made.
+ * \return true if the menu was registed ok; else false.
+ */
+bool ro_gui_wimp_event_register_menu_selection(wimp_w w,
+ bool (*callback)(wimp_w w, wimp_i i, wimp_menu *m,
+ wimp_selection *s, menu_action a))
+{
+ struct event_window *window;
+
+ window = ro_gui_wimp_event_get_window(w);
+ if (!window)
+ return false;
+ window->menu_selection = callback;
+ return true;
+}
+
+
+/**
+ * Register a function to be called when a sub-menu warning is received.
+ *
+ * \param *w The window for which events should be returned.
+ * \param *callback A function to be called whenever a submenu
+ * warning is received for the menu.
+ * \return true if the menu was registed ok; else false.
+ */
+bool ro_gui_wimp_event_register_menu_warning(wimp_w w,
+ void (*callback)(wimp_w w, wimp_i i, wimp_menu *m,
+ wimp_selection *s, menu_action a))
+{
+ struct event_window *window;
+
+ window = ro_gui_wimp_event_get_window(w);
+ if (!window)
+ return false;
+ window->menu_warning = callback;
+ return true;
+}
+
+
+/**
+ * Register a function to be called before a menu is finally closed.
+ *
+ * \param *w The window for which events should be returned.
+ * \param *callback A function to be called when the menu is closed.
+ * \return true if the menu was registed ok; else false.
+ */
+bool ro_gui_wimp_event_register_menu_close(wimp_w w,
+ void (*callback)(wimp_w w, wimp_i i, wimp_menu *m))
+{
+ struct event_window *window;
+
+ window = ro_gui_wimp_event_get_window(w);
+ if (!window)
+ return false;
+ window->menu_close = callback;
+ return true;
+}
+
+
+/**
+ * Finds the event data associated with a given window handle, or creates a
+ * new one.
+ *
+ * \param w the window to find data for
+ */
+struct event_window *ro_gui_wimp_event_get_window(wimp_w w)
+{
+ struct event_window *window;
+ int h;
+
+ assert((int)w != 0);
+ window = ro_gui_wimp_event_find_window(w);
+ if (window)
+ return window;
+
+ LOG("Creating structure for window 0x%x", (unsigned int)w);
+ window = calloc(1, sizeof(struct event_window));
+ if (!window)
+ return NULL;
+
+ h = WIN_HASH(w);
+ window->w = w;
+ window->next = ro_gui_wimp_event_windows[h];
+ ro_gui_wimp_event_windows[h] = window;
+ return window;
+}
+
+
+/**
+ * Removes the event data associated with a given handle from the hash tables,
+ * but does not delete it.
+ *
+ * \param w the window to be removed
+ * \return pointer to the event data or NULL if not found
+ */
+
+struct event_window *ro_gui_wimp_event_remove_window(wimp_w w)
+{
+ struct event_window **prev;
+ int h = WIN_HASH(w);
+
+ /* search hash chain for the window */
+ prev = &ro_gui_wimp_event_windows[h];
+ while (*prev) {
+ struct event_window *window = *prev;
+
+ if (window->w == w) {
+ /* remove from chain */
+ *prev = window->next;
+ return window;
+ }
+ prev = &window->next;
+ }
+
+ /* not found */
+ return NULL;
+}
+
+/**
+ * Find the event data associated with a given window handle
+ *
+ * \param w the window to find data for
+ */
+struct event_window *ro_gui_wimp_event_find_window(wimp_w w)
+{
+ struct event_window *window;
+ int h = WIN_HASH(w);
+
+ /* search hash chain for window */
+ for (window = ro_gui_wimp_event_windows[h]; window; window = window->next) {
+ if (window->w == w)
+ return window;
+ }
+ return NULL;
+}
+
+struct icon_event *ro_gui_wimp_event_get_event(wimp_w w, wimp_i i,
+ event_type type)
+{
+ struct event_window *window;
+ struct icon_event *event;
+
+ window = ro_gui_wimp_event_get_window(w);
+ if (!window)
+ return NULL;
+
+ for (event = window->first; event; event = event->next) {
+ if (event->i == i) {
+ event->type = type;
+ return event;
+ }
+ }
+
+ event = calloc(1, sizeof(struct icon_event));
+ if (!event)
+ return NULL;
+ event->i = i;
+ event->type = type;
+ event->next = window->first;
+ window->first = event;
+
+ return event;
+}
+
+/* Handle sumbenu warnings. This is called from ro_gui_menu_warning(), and
+ * returns to that function to have the submenu opened correctly.
+ *
+ * \param w the window to owning the menu
+ * \param i the icon owning the menu
+ * \param menu the menu that has been selected
+ * \param selection the selection information
+ * \param action the menu action info from menus.c
+ * \return true if the event was handled, false otherwise
+ */
+
+bool ro_gui_wimp_event_submenu_warning(wimp_w w, wimp_i i, wimp_menu *menu,
+ wimp_selection *selection, menu_action action)
+{
+ struct event_window *window;
+ struct icon_event *event;
+
+ ro_gui_wimp_event_register_submenu(0);
+
+ /* Process the event for any window menus. Find the window data, then
+ * try and match to an icon event. If we can, then there isn't anything
+ * to do.
+ */
+
+ window = ro_gui_wimp_event_find_window(w);
+ if (!window)
+ return false;
+
+ for (event = window->first; event; event = event->next)
+ if ((event->type == EVENT_MENU_GRIGHT) && (event->i == i))
+ break;
+ if (event) {
+ if (window->menu_close != NULL &&
+ event->type == EVENT_MENU_GRIGHT &&
+ event->data.menu_gright.menu == menu) {
+ window->menu_close(w, i, menu);
+ return true;
+ }
+
+ return false;
+ }
+
+ /* If the warning is for a window menu, then pass the event on to it. */
+
+ if ((window->window_menu) && (window->window_menu == menu)) {
+ if (window->menu_warning) {
+ window->menu_warning(w, wimp_ICON_WINDOW, menu,
+ selection, action);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/**
+ * Handle menus being closed. This is called from the menus modules, in
+ * every scenario when one of our own menus is open.
+ *
+ * \param w the window to owning the menu
+ * \param i the icon owning the menu
+ * \param menu the menu that has been selected
+ */
+
+void ro_gui_wimp_event_menus_closed(wimp_w w, wimp_i i, wimp_menu *menu)
+{
+ struct event_window *window;
+ struct icon_event *event;
+
+ ro_gui_wimp_event_register_submenu(0);
+
+ /* Process the event for any window menus. Find the window data, then
+ * try and match to an icon event. If we can, then GRight menus are
+ * sent the event; otherwise, we do nothing.
+ */
+
+ window = ro_gui_wimp_event_find_window(w);
+ if (!window)
+ return;
+
+ for (event = window->first; event; event = event->next)
+ if ((event->type == EVENT_MENU_GRIGHT) && (event->i == i))
+ break;
+ if (event) {
+ if (window->menu_close != NULL &&
+ event->type == EVENT_MENU_GRIGHT &&
+ event->data.menu_gright.menu == menu)
+ window->menu_close(w, i, menu);
+ return;
+ }
+
+ /* If the close is for a window menu, then pass the event on to it. */
+
+ if ((window->window_menu) && (window->window_menu == menu) &&
+ (window->menu_close))
+ window->menu_close(w, wimp_ICON_WINDOW, menu);
+}
+
+/**
+ * Register a submenu as being opened
+ */
+void ro_gui_wimp_event_register_submenu(wimp_w w)
+{
+ if (ro_gui_wimp_event_submenu)
+ ro_gui_wimp_event_close_window(ro_gui_wimp_event_submenu);
+ ro_gui_wimp_event_submenu = w;
+}
+
diff --git a/frontends/riscos/wimp_event.h b/frontends/riscos/wimp_event.h
new file mode 100644
index 000000000..0a54ab04d
--- /dev/null
+++ b/frontends/riscos/wimp_event.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2005 Richard Wilson <info@tinct.net>
+ * Copyright 2010, 2011 Stephen Fryatt <stevef@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Automated RISC OS WIMP event handling (interface).
+ */
+
+
+#ifndef _NETSURF_RISCOS_WIMP_EVENT_H_
+#define _NETSURF_RISCOS_WIMP_EVENT_H_
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "oslib/os.h"
+#include "oslib/wimp.h"
+#include "riscos/menus.h"
+
+#define IS_WIMP_KEY (1u<<31)
+
+bool ro_gui_wimp_event_memorise(wimp_w w);
+bool ro_gui_wimp_event_restore(wimp_w w);
+bool ro_gui_wimp_event_validate(wimp_w w);
+bool ro_gui_wimp_event_transfer(wimp_w from, wimp_w to);
+void ro_gui_wimp_event_finalise(wimp_w w);
+void ro_gui_wimp_event_deregister(wimp_w w, wimp_i i);
+
+bool ro_gui_wimp_event_set_help_prefix(wimp_w w, const char *help_prefix);
+const char *ro_gui_wimp_event_get_help_prefix(wimp_w w);
+bool ro_gui_wimp_event_register_help_suffix(wimp_w w,
+ const char *(*get_help_suffix)(wimp_w w, wimp_i i,
+ os_coord *pos, wimp_mouse_state buttons));
+const char *ro_gui_wimp_event_get_help_suffix(wimp_w w, wimp_i i,
+ os_coord *pos, wimp_mouse_state buttons);
+bool ro_gui_wimp_event_set_user_data(wimp_w w, void *user);
+void *ro_gui_wimp_event_get_user_data(wimp_w w);
+
+bool ro_gui_wimp_event_menu_selection(wimp_w w, wimp_i i, wimp_menu *menu,
+ wimp_selection *selection, menu_action action);
+bool ro_gui_wimp_event_mouse_click(wimp_pointer *pointer);
+bool ro_gui_wimp_event_keypress(wimp_key *key);
+bool ro_gui_wimp_event_open_window(wimp_open *open);
+bool ro_gui_wimp_event_close_window(wimp_w w);
+bool ro_gui_wimp_event_redraw_window(wimp_draw *redraw);
+bool ro_gui_wimp_event_scroll_window(wimp_scroll *scroll);
+bool ro_gui_wimp_event_pointer_entering_window(wimp_entering *entering);
+
+bool ro_gui_wimp_event_process_window_menu_click(wimp_pointer *pointer);
+bool ro_gui_wimp_event_prepare_menu(wimp_w w, wimp_i i, wimp_menu *menu);
+
+bool ro_gui_wimp_event_register_menu(wimp_w w, wimp_menu *m,
+ bool menu_auto, bool position_ibar);
+bool ro_gui_wimp_event_register_numeric_field(wimp_w w, wimp_i i, wimp_i up,
+ wimp_i down, int min, int max, int stepping,
+ int decimal_places);
+bool ro_gui_wimp_event_register_text_field(wimp_w w, wimp_i i);
+bool ro_gui_wimp_event_register_menu_gright(wimp_w w, wimp_i i,
+ wimp_i gright, wimp_menu *menu);
+bool ro_gui_wimp_event_register_checkbox(wimp_w w, wimp_i i);
+bool ro_gui_wimp_event_register_radio(wimp_w w, wimp_i *i);
+bool ro_gui_wimp_event_register_button(wimp_w w, wimp_i i,
+ void (*callback)(wimp_pointer *pointer));
+bool ro_gui_wimp_event_register_cancel(wimp_w w, wimp_i i);
+bool ro_gui_wimp_event_register_ok(wimp_w w, wimp_i i,
+ bool (*callback)(wimp_w w));
+
+bool ro_gui_wimp_event_register_mouse_click(wimp_w w,
+ bool (*callback)(wimp_pointer *pointer));
+bool ro_gui_wimp_event_register_keypress(wimp_w w,
+ bool (*callback)(wimp_key *key));
+bool ro_gui_wimp_event_register_open_window(wimp_w w,
+ void (*callback)(wimp_open *open));
+bool ro_gui_wimp_event_register_close_window(wimp_w w,
+ void (*callback)(wimp_w w));
+bool ro_gui_wimp_event_register_redraw_window(wimp_w w,
+ void (*callback)(wimp_draw *redraw));
+bool ro_gui_wimp_event_register_scroll_window(wimp_w w,
+ void (*callback)(wimp_scroll *scroll));
+bool ro_gui_wimp_event_register_pointer_entering_window(wimp_w w,
+ void (*callback)(wimp_entering *entering));
+bool ro_gui_wimp_event_register_menu_prepare(wimp_w w,
+ bool (*callback)(wimp_w w, wimp_i i, wimp_menu *m,
+ wimp_pointer *p));
+bool ro_gui_wimp_event_register_menu_selection(wimp_w w,
+ bool (*callback)(wimp_w w, wimp_i i, wimp_menu *m,
+ wimp_selection *s, menu_action a));
+bool ro_gui_wimp_event_register_menu_warning(wimp_w w,
+ void (*callback)(wimp_w w, wimp_i i, wimp_menu *m,
+ wimp_selection *s, menu_action a));
+bool ro_gui_wimp_event_register_menu_close(wimp_w w,
+ void (*callback)(wimp_w w, wimp_i i, wimp_menu *m));
+
+bool ro_gui_wimp_event_submenu_warning(wimp_w w, wimp_i i, wimp_menu *menu,
+ wimp_selection *selection, menu_action action);
+void ro_gui_wimp_event_menus_closed(wimp_w w, wimp_i i, wimp_menu *menu);
+void ro_gui_wimp_event_register_submenu(wimp_w w);
+
+#endif
diff --git a/frontends/riscos/wimputils.h b/frontends/riscos/wimputils.h
new file mode 100644
index 000000000..5225a720e
--- /dev/null
+++ b/frontends/riscos/wimputils.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2009 John-Mark Bell <jmb@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * A collection of grubby utilities for working with OSLib's wimp API.
+ */
+
+#ifndef riscos_wimputils_h_
+#define riscos_wimputils_h_
+
+#include <oslib/wimp.h>
+
+/* Magical union to permit aliasing of wimp_window_state and wimp_open
+ * Do not use this directly. Use the macros, instead. */
+typedef union window_open_state {
+ wimp_window_state state;
+ wimp_open open;
+} window_open_state;
+
+/* Convert a pointer to a wimp_window_state into a pointer to a wimp_open */
+#define PTR_WIMP_OPEN(pstate) ((wimp_open *) (window_open_state *) (pstate))
+
+/* Similarly for wimp_message_list */
+typedef struct ns_wimp_message_list {
+ /* Nasty hack to ensure that we have at least one field in the struct */
+ int first;
+ int rest[];
+} ns_wimp_message_list;
+
+typedef union message_list {
+ wimp_message_list wimp;
+ ns_wimp_message_list ns;
+} message_list;
+
+#define PTR_WIMP_MESSAGE_LIST(l) ((wimp_message_list *) (message_list *) (l))
+
+/* Also for VDU variable lists */
+typedef struct ns_os_vdu_var_list {
+ os_vdu_var first;
+ os_vdu_var rest[];
+} ns_os_vdu_var_list;
+
+typedef union vdu_var_list {
+ os_vdu_var_list os;
+ ns_os_vdu_var_list ns;
+} vdu_var_list;
+
+#define PTR_OS_VDU_VAR_LIST(l) ((os_vdu_var_list *) (vdu_var_list *) (l))
+
+#endif
diff --git a/frontends/riscos/window.c b/frontends/riscos/window.c
new file mode 100644
index 000000000..ab1501cd6
--- /dev/null
+++ b/frontends/riscos/window.c
@@ -0,0 +1,5025 @@
+/*
+ * Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
+ * Copyright 2004 James Bursa <bursa@users.sourceforge.net>
+ * Copyright 2003 John M Bell <jmb202@ecs.soton.ac.uk>
+ * Copyright 2004 Andrew Timmins <atimmins@blueyonder.co.uk>
+ * Copyright 2005 Richard Wilson <info@tinct.net>
+ * Copyright 2005 Adrian Lees <adrianl@users.sourceforge.net>
+ * Copyright 2010-2014 Stephen Fryatt <stevef@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Implementation of RISC OS browser window handling.
+ */
+
+#include <assert.h>
+#include <ctype.h>
+#include <inttypes.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <time.h>
+#include <string.h>
+#include <oslib/colourtrans.h>
+#include <oslib/osbyte.h>
+#include <oslib/osfile.h>
+#include <oslib/osspriteop.h>
+#include <oslib/wimp.h>
+#include <oslib/wimpspriteop.h>
+#include <nsutils/time.h>
+
+#include "utils/config.h"
+#include "utils/nsoption.h"
+#include "utils/log.h"
+#include "utils/talloc.h"
+#include "utils/file.h"
+#include "utils/utf8.h"
+#include "utils/utils.h"
+#include "utils/messages.h"
+#include "utils/string.h"
+#include "content/content.h"
+#include "content/hlcache.h"
+#include "content/urldb.h"
+#include "desktop/browser_history.h"
+#include "desktop/browser.h"
+#include "desktop/cookie_manager.h"
+#include "desktop/scrollbar.h"
+#include "desktop/frames.h"
+#include "desktop/mouse.h"
+#include "desktop/plotters.h"
+#include "desktop/textinput.h"
+#include "desktop/tree.h"
+#include "desktop/gui_window.h"
+#include "image/bitmap.h"
+#include "render/form.h"
+
+#include "riscos/bitmap.h"
+#include "riscos/buffer.h"
+#include "riscos/cookies.h"
+#include "riscos/dialog.h"
+#include "riscos/global_history.h"
+#include "riscos/gui.h"
+#include "riscos/gui/status_bar.h"
+#include "riscos/help.h"
+#include "riscos/hotlist.h"
+#include "riscos/menus.h"
+#include "riscos/mouse.h"
+#include "riscos/oslib_pre7.h"
+#include "riscos/save.h"
+#include "riscos/content-handlers/sprite.h"
+#include "riscos/textselection.h"
+#include "riscos/toolbar.h"
+#include "riscos/url_complete.h"
+#include "riscos/url_suggest.h"
+#include "riscos/wimp.h"
+#include "riscos/wimp_event.h"
+#include "riscos/wimputils.h"
+#include "riscos/window.h"
+#include "riscos/ucstables.h"
+#include "riscos/filetype.h"
+
+void gui_window_redraw_window(struct gui_window *g);
+
+static void gui_window_set_extent(struct gui_window *g, int width, int height);
+
+static void ro_gui_window_redraw(wimp_draw *redraw);
+static void ro_gui_window_scroll(wimp_scroll *scroll);
+static void ro_gui_window_pointer_entering(wimp_entering *entering);
+static void ro_gui_window_track_end(wimp_leaving *leaving, void *data);
+static void ro_gui_window_open(wimp_open *open);
+static void ro_gui_window_close(wimp_w w);
+static bool ro_gui_window_click(wimp_pointer *mouse);
+static bool ro_gui_window_keypress(wimp_key *key);
+static bool ro_gui_window_toolbar_keypress(void *data, wimp_key *key);
+static bool ro_gui_window_handle_local_keypress(struct gui_window *g,
+ wimp_key *key, bool is_toolbar);
+static bool ro_gui_window_menu_prepare(wimp_w w, wimp_i i, wimp_menu *menu,
+ wimp_pointer *pointer);
+static void ro_gui_window_menu_warning(wimp_w w, wimp_i i, wimp_menu *menu,
+ wimp_selection *selection, menu_action action);
+static bool ro_gui_window_menu_select(wimp_w w, wimp_i i, wimp_menu *menu,
+ wimp_selection *selection, menu_action action);
+static void ro_gui_window_menu_close(wimp_w w, wimp_i i, wimp_menu *menu);
+
+static void ro_gui_window_scroll_end(wimp_dragged *drag, void *data);
+
+static void ro_gui_window_scroll_action(struct gui_window *g,
+ int scroll_x, int scroll_y);
+
+static void ro_gui_window_toolbar_click(void *data,
+ toolbar_action_type action_type, union toolbar_action action);
+
+static bool ro_gui_window_content_export_types(hlcache_handle *h,
+ bool *export_draw, bool *export_sprite);
+static void ro_gui_window_prepare_pageinfo(struct gui_window *g);
+static void ro_gui_window_prepare_objectinfo(hlcache_handle *object,
+ nsurl *target_url);
+
+static void ro_gui_window_launch_url(struct gui_window *g, const char *url);
+static void ro_gui_window_action_home(struct gui_window *g);
+static void ro_gui_window_action_new_window(struct gui_window *g);
+static void ro_gui_window_action_local_history(struct gui_window *g);
+static void ro_gui_window_action_save(struct gui_window *g,
+ gui_save_type save_type);
+static void ro_gui_window_action_search(struct gui_window *g);
+static void ro_gui_window_action_zoom(struct gui_window *g);
+static void ro_gui_window_action_add_bookmark(struct gui_window *g);
+static void ro_gui_window_action_remove_bookmark(struct gui_window *g);
+static void ro_gui_window_action_print(struct gui_window *g);
+static void ro_gui_window_action_page_info(struct gui_window *g);
+
+static void ro_gui_window_remove_update_boxes(struct gui_window *g);
+static void ro_gui_window_update_toolbar_buttons(struct gui_window *g);
+static void ro_gui_window_update_toolbar(void *data);
+static void ro_gui_window_save_toolbar_buttons(void *data, char *config);
+static void ro_gui_window_update_theme(void *data, bool ok);
+
+static bool ro_gui_window_import_text(struct gui_window *g,
+ const char *filename);
+static void ro_gui_window_clone_options(
+ struct gui_window *new_gui,
+ struct gui_window *old_gui);
+
+static bool ro_gui_window_prepare_form_select_menu(struct gui_window *bw,
+ struct form_control *control);
+static void ro_gui_window_process_form_select_menu(struct gui_window *g,
+ wimp_selection *selection);
+
+#ifndef wimp_KEY_END
+#define wimp_KEY_END wimp_KEY_COPY
+#endif
+
+#ifndef wimp_WINDOW_GIVE_SHADED_ICON_INFO
+ /* RISC OS 5+. Requires OSLib trunk. */
+#define wimp_WINDOW_GIVE_SHADED_ICON_INFO ((wimp_extra_window_flags) 0x10u)
+#endif
+
+#define SCROLL_VISIBLE_PADDING 32
+
+/** Remembers which iconised sprite numbers are in use */
+static bool iconise_used[64];
+static int iconise_next = 0;
+
+/** Whether a pressed mouse button has become a drag */
+static bool mouse_drag_select;
+static bool mouse_drag_adjust;
+
+/** List of all browser windows. */
+static struct gui_window *window_list = 0;
+/** GUI window which is being redrawn. Valid only during redraw. */
+struct gui_window *ro_gui_current_redraw_gui;
+/** Form control which gui_form_select_menu is for. */
+static struct form_control *gui_form_select_control;
+/** The browser window menu handle. */
+static wimp_menu *ro_gui_browser_window_menu = NULL;
+/** Menu of options for form select controls. */
+static wimp_menu *gui_form_select_menu = NULL;
+/** Main content object under menu, or 0 if none. */
+static hlcache_handle *current_menu_main = 0;
+/** Object under menu, or 0 if no object. */
+static hlcache_handle *current_menu_object = 0;
+/** URL of link under menu, or 0 if no link. */
+static nsurl *current_menu_url = 0;
+
+static float scale_snap_to[] = {0.10, 0.125, 0.25, 0.333, 0.5, 0.75,
+ 1.0,
+ 1.5, 2.0, 3.0, 4.0, 6.0, 8.0, 12.0, 16.0};
+#define SCALE_SNAP_TO_SIZE (sizeof scale_snap_to) / (sizeof(float))
+
+/** An entry in ro_gui_pointer_table. */
+struct ro_gui_pointer_entry {
+ bool wimp_area; /** The pointer is in the Wimp's sprite area. */
+ char sprite_name[16];
+ int xactive;
+ int yactive;
+};
+
+/** Map from gui_pointer_shape to pointer sprite data. Must be ordered as
+ * enum gui_pointer_shape. */
+struct ro_gui_pointer_entry ro_gui_pointer_table[] = {
+ { true, "ptr_default", 0, 0 },
+ { false, "ptr_point", 6, 0 },
+ { false, "ptr_caret", 4, 9 },
+ { false, "ptr_menu", 6, 4 },
+ { false, "ptr_ud", 6, 7 },
+ { false, "ptr_ud", 6, 7 },
+ { false, "ptr_lr", 7, 6 },
+ { false, "ptr_lr", 7, 6 },
+ { false, "ptr_ld", 7, 7 },
+ { false, "ptr_ld", 7, 7 },
+ { false, "ptr_rd", 7, 7 },
+ { false, "ptr_rd", 6, 7 },
+ { false, "ptr_cross", 7, 7 },
+ { false, "ptr_move", 8, 0 },
+ { false, "ptr_wait", 7, 10 },
+ { false, "ptr_help", 0, 0 },
+ { false, "ptr_nodrop", 0, 0 },
+ { false, "ptr_nt_allwd", 10, 10 },
+ { false, "ptr_progress", 0, 0 },
+};
+
+struct update_box {
+ int x0;
+ int y0;
+ int x1;
+ int y1;
+ bool use_buffer;
+ struct gui_window *g;
+ struct update_box *next;
+};
+
+struct update_box *pending_updates;
+#define MARGIN 4
+
+static const struct toolbar_callbacks ro_gui_window_toolbar_callbacks = {
+ ro_gui_window_update_theme,
+ ro_gui_window_update_toolbar,
+ (void (*)(void *)) ro_gui_window_update_toolbar_buttons,
+ ro_gui_window_toolbar_click,
+ ro_gui_window_toolbar_keypress,
+ ro_gui_window_save_toolbar_buttons
+};
+
+
+/**
+ * Initialise the browser window module and its menus.
+ */
+
+void ro_gui_window_initialise(void)
+{
+ /* Build the browser window menu. */
+
+ static const struct ns_menu browser_definition = {
+ "NetSurf", {
+ { "Page", BROWSER_PAGE, 0 },
+ { "Page.PageInfo",BROWSER_PAGE_INFO, &dialog_pageinfo },
+ { "Page.Save", BROWSER_SAVE, &dialog_saveas },
+ { "Page.SaveComp", BROWSER_SAVE_COMPLETE, &dialog_saveas },
+ { "Page.Export", NO_ACTION, 0 },
+#ifdef WITH_DRAW_EXPORT
+ { "Page.Export.Draw", BROWSER_EXPORT_DRAW, &dialog_saveas },
+#endif
+#ifdef WITH_PDF_EXPORT
+ { "Page.Export.PDF", BROWSER_EXPORT_PDF, &dialog_saveas },
+#endif
+ { "Page.Export.Text", BROWSER_EXPORT_TEXT, &dialog_saveas },
+ { "Page.SaveURL", NO_ACTION, 0 },
+ { "Page.SaveURL.URI", BROWSER_SAVE_URL_URI, &dialog_saveas },
+ { "Page.SaveURL.URL", BROWSER_SAVE_URL_URL, &dialog_saveas },
+ { "Page.SaveURL.LinkText", BROWSER_SAVE_URL_TEXT, &dialog_saveas },
+ { "_Page.Print", BROWSER_PRINT, &dialog_print },
+ { "Page.NewWindow", BROWSER_NEW_WINDOW, 0 },
+ { "Page.FindText", BROWSER_FIND_TEXT, &dialog_search },
+ { "Page.ViewSrc", BROWSER_VIEW_SOURCE, 0 },
+ { "Object", BROWSER_OBJECT, 0 },
+ { "Object.Object", BROWSER_OBJECT_OBJECT, 0 },
+ { "Object.Object.ObjInfo", BROWSER_OBJECT_INFO, &dialog_objinfo },
+ { "Object.Object.ObjSave", BROWSER_OBJECT_SAVE, &dialog_saveas },
+ { "Object.Object.Export", BROWSER_OBJECT_EXPORT, 0 },
+ { "Object.Object.Export.Sprite", BROWSER_OBJECT_EXPORT_SPRITE, &dialog_saveas },
+#ifdef WITH_DRAW_EXPORT
+ { "Object.Object.Export.ObjDraw", BROWSER_OBJECT_EXPORT_DRAW, &dialog_saveas },
+#endif
+ { "Object.Object.SaveURL", NO_ACTION, 0 },
+ { "Object.Object.SaveURL.URI", BROWSER_OBJECT_SAVE_URL_URI, &dialog_saveas },
+ { "Object.Object.SaveURL.URL", BROWSER_OBJECT_SAVE_URL_URL, &dialog_saveas },
+ { "Object.Object.SaveURL.LinkText", BROWSER_OBJECT_SAVE_URL_TEXT, &dialog_saveas },
+ { "Object.Object.ObjPrint", BROWSER_OBJECT_PRINT, 0 },
+ { "Object.Object.ObjReload", BROWSER_OBJECT_RELOAD, 0 },
+ { "Object.Link", BROWSER_OBJECT_LINK, 0 },
+ { "Object.Link.LinkSave", BROWSER_LINK_SAVE, 0 },
+ { "Object.Link.LinkSave.URI", BROWSER_LINK_SAVE_URI, &dialog_saveas },
+ { "Object.Link.LinkSave.URL", BROWSER_LINK_SAVE_URL, &dialog_saveas },
+ { "Object.Link.LinkSave.LinkText", BROWSER_LINK_SAVE_TEXT, &dialog_saveas },
+ { "_Object.Link.LinkDload", BROWSER_LINK_DOWNLOAD, 0 },
+ { "Object.Link.LinkNew", BROWSER_LINK_NEW_WINDOW, 0 },
+ { "Selection", BROWSER_SELECTION, 0 },
+ { "_Selection.SelSave", BROWSER_SELECTION_SAVE, &dialog_saveas },
+ { "Selection.Copy", BROWSER_SELECTION_COPY, 0 },
+ { "Selection.Cut", BROWSER_SELECTION_CUT, 0 },
+ { "_Selection.Paste", BROWSER_SELECTION_PASTE, 0 },
+ { "Selection.Clear", BROWSER_SELECTION_CLEAR, 0 },
+ { "Selection.SelectAll", BROWSER_SELECTION_ALL, 0 },
+ { "Navigate", NO_ACTION, 0 },
+ { "Navigate.Home", BROWSER_NAVIGATE_HOME, 0 },
+ { "Navigate.Back", BROWSER_NAVIGATE_BACK, 0 },
+ { "Navigate.Forward", BROWSER_NAVIGATE_FORWARD, 0 },
+ { "_Navigate.UpLevel", BROWSER_NAVIGATE_UP, 0 },
+ { "Navigate.Reload", BROWSER_NAVIGATE_RELOAD_ALL, 0 },
+ { "Navigate.Stop", BROWSER_NAVIGATE_STOP, 0 },
+ { "View", NO_ACTION, 0 },
+ { "View.ScaleView", BROWSER_SCALE_VIEW, &dialog_zoom },
+ { "View.Images", NO_ACTION, 0 },
+ { "View.Images.ForeImg", BROWSER_IMAGES_FOREGROUND, 0 },
+ { "View.Images.BackImg", BROWSER_IMAGES_BACKGROUND, 0 },
+ { "View.Toolbars", NO_ACTION, 0 },
+ { "View.Toolbars.ToolButtons", TOOLBAR_BUTTONS, 0 },
+ { "View.Toolbars.ToolAddress", TOOLBAR_ADDRESS_BAR, 0 },
+ { "_View.Toolbars.ToolThrob", TOOLBAR_THROBBER, 0 },
+ { "View.Toolbars.EditToolbar", TOOLBAR_EDIT, 0 },
+ { "_View.Render", NO_ACTION, 0 },
+ { "View.Render.RenderAnims", BROWSER_BUFFER_ANIMS, 0 },
+ { "View.Render.RenderAll", BROWSER_BUFFER_ALL, 0 },
+ { "_View.OptDefault", BROWSER_SAVE_VIEW, 0 },
+ { "View.Window", NO_ACTION, 0 },
+ { "View.Window.WindowSave", BROWSER_WINDOW_DEFAULT, 0 },
+ { "View.Window.WindowStagr", BROWSER_WINDOW_STAGGER, 0 },
+ { "_View.Window.WindowSize", BROWSER_WINDOW_COPY, 0 },
+ { "View.Window.WindowReset", BROWSER_WINDOW_RESET, 0 },
+ { "Utilities", NO_ACTION, 0 },
+ { "Utilities.Hotlist", HOTLIST_SHOW, 0 },
+ { "Utilities.Hotlist.HotlistAdd", HOTLIST_ADD_URL, 0 },
+ { "Utilities.Hotlist.HotlistShow", HOTLIST_SHOW, 0 },
+ { "Utilities.History", HISTORY_SHOW_GLOBAL, 0 },
+ { "Utilities.History.HistLocal", HISTORY_SHOW_LOCAL, 0 },
+ { "Utilities.History.HistGlobal", HISTORY_SHOW_GLOBAL, 0 },
+ { "Utilities.Cookies", COOKIES_SHOW, 0 },
+ { "Utilities.Cookies.ShowCookies", COOKIES_SHOW, 0 },
+ { "Utilities.Cookies.DeleteCookies", COOKIES_DELETE, 0 },
+ { "Help", HELP_OPEN_CONTENTS, 0 },
+ { "Help.HelpContent", HELP_OPEN_CONTENTS, 0 },
+ { "Help.HelpGuide", HELP_OPEN_GUIDE, 0 },
+ { "_Help.HelpInfo", HELP_OPEN_INFORMATION, 0 },
+ { "Help.HelpCredits", HELP_OPEN_CREDITS, 0 },
+ { "_Help.HelpLicence", HELP_OPEN_LICENCE, 0 },
+ { "Help.HelpInter", HELP_LAUNCH_INTERACTIVE, 0 },
+ {NULL, 0, 0}
+ }
+ };
+ ro_gui_browser_window_menu =
+ ro_gui_menu_define_menu(&browser_definition);
+
+}
+
+
+/*
+ * Interface With Core
+ */
+
+/**
+ * Place the caret in a browser window.
+ *
+ * \param g window with caret
+ * \param x coordinates of caret
+ * \param y coordinates of caret
+ * \param height height of caret
+ * \param clip clip rectangle, or NULL if none
+ */
+
+static void gui_window_place_caret(struct gui_window *g, int x, int y, int height,
+ const struct rect *clip)
+{
+ os_error *error;
+
+ error = xwimp_set_caret_position(g->window, -1,
+ x * 2, -(y + height) * 2, height * 2, -1);
+ if (error) {
+ LOG("xwimp_set_caret_position: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+}
+
+/**
+ * Create and open a new browser window.
+ *
+ * \param bw bw to create gui_window for
+ * \param existing an existing gui_window, may be NULL
+ * \param flags flags for gui window creation
+ * \return gui window, or NULL on error
+ */
+
+static struct gui_window *gui_window_create(struct browser_window *bw,
+ struct gui_window *existing,
+ gui_window_create_flags flags)
+{
+ int screen_width, screen_height;
+ static int window_count = 2;
+ wimp_window window;
+ wimp_window_state state;
+ os_error *error;
+ bool open_centred = true;
+ struct gui_window *g;
+
+ g = malloc(sizeof *g);
+ if (!g) {
+ ro_warn_user("NoMemory", 0);
+ return 0;
+ }
+ g->bw = bw;
+ g->toolbar = 0;
+ g->status_bar = 0;
+ g->old_width = 0;
+ g->old_height = 0;
+ g->update_extent = true;
+ g->active = false;
+ strcpy(g->title, "NetSurf");
+ g->iconise_icon = -1;
+ g->scale = browser_window_get_scale(bw);
+
+ /* Set the window position */
+ if (existing != NULL &&
+ flags & GW_CREATE_CLONE &&
+ nsoption_bool(window_size_clone)) {
+ state.w = existing->window;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+ window.visible.x0 = state.visible.x0;
+ window.visible.x1 = state.visible.x1;
+ window.visible.y0 = state.visible.y0 - 48;
+ window.visible.y1 = state.visible.y1 - 48;
+ open_centred = false;
+ } else {
+ int win_width, win_height;
+ ro_gui_screen_size(&screen_width, &screen_height);
+
+ /* Check if we have a preferred position */
+ if ((nsoption_int(window_screen_width) != 0) &&
+ (nsoption_int(window_screen_height) != 0)) {
+ win_width = (nsoption_int(window_width) *
+ screen_width) /
+ nsoption_int(window_screen_width);
+ win_height = (nsoption_int(window_height) *
+ screen_height) /
+ nsoption_int(window_screen_height);
+ window.visible.x0 = (nsoption_int(window_x) *
+ screen_width) /
+ nsoption_int(window_screen_width);
+ window.visible.y0 = (nsoption_int(window_y) *
+ screen_height) /
+ nsoption_int(window_screen_height);
+ if (nsoption_bool(window_stagger)) {
+ window.visible.y0 += 96 -
+ (48 * (window_count % 5));
+ }
+ open_centred = false;
+ if (win_width < 100)
+ win_width = 100;
+ if (win_height < 100)
+ win_height = 100;
+ } else {
+
+ /* Base how we define the window height/width
+ on the compile time options set */
+ win_width = screen_width * 3 / 4;
+ if (1600 < win_width)
+ win_width = 1600;
+ win_height = win_width * 3 / 4;
+
+ window.visible.x0 = (screen_width - win_width) / 2;
+ window.visible.y0 = ((screen_height - win_height) / 2) +
+ 96 - (48 * (window_count % 5));
+ }
+ window.visible.x1 = window.visible.x0 + win_width;
+ window.visible.y1 = window.visible.y0 + win_height;
+ }
+
+ /* General flags for a non-movable, non-resizable, no-title bar window */
+ window.xscroll = 0;
+ window.yscroll = 0;
+ window.next = wimp_TOP;
+ window.flags = wimp_WINDOW_MOVEABLE |
+ wimp_WINDOW_NEW_FORMAT |
+ wimp_WINDOW_VSCROLL |
+ wimp_WINDOW_HSCROLL |
+ wimp_WINDOW_IGNORE_XEXTENT |
+ wimp_WINDOW_IGNORE_YEXTENT |
+ wimp_WINDOW_SCROLL_REPEAT;
+ window.title_fg = wimp_COLOUR_BLACK;
+ window.title_bg = wimp_COLOUR_LIGHT_GREY;
+ window.work_fg = wimp_COLOUR_LIGHT_GREY;
+ window.work_bg = wimp_COLOUR_TRANSPARENT;
+ window.scroll_outer = wimp_COLOUR_DARK_GREY;
+ window.scroll_inner = wimp_COLOUR_MID_LIGHT_GREY;
+ window.highlight_bg = wimp_COLOUR_CREAM;
+ window.extra_flags = wimp_WINDOW_USE_EXTENDED_SCROLL_REQUEST |
+ wimp_WINDOW_GIVE_SHADED_ICON_INFO;
+ window.extent.x0 = 0;
+ window.extent.y0 = -(window.visible.y1 - window.visible.y0);
+ window.extent.x1 = window.visible.x1 - window.visible.x0;
+ window.extent.y1 = 0;
+ window.title_flags = wimp_ICON_TEXT |
+ wimp_ICON_INDIRECTED |
+ wimp_ICON_HCENTRED;
+ window.work_flags = wimp_BUTTON_DOUBLE_CLICK_DRAG <<
+ wimp_ICON_BUTTON_TYPE_SHIFT;
+ window.sprite_area = wimpspriteop_AREA;
+ window.xmin = 1;
+ window.ymin = 1;
+ window.title_data.indirected_text.text = g->title;
+ window.title_data.indirected_text.validation = (char *) -1;
+ window.title_data.indirected_text.size = 255;
+ window.icon_count = 0;
+
+ /* Add in flags */
+ window.flags |= wimp_WINDOW_SIZE_ICON |
+ wimp_WINDOW_BACK_ICON |
+ wimp_WINDOW_CLOSE_ICON |
+ wimp_WINDOW_TITLE_ICON |
+ wimp_WINDOW_TOGGLE_ICON;
+
+ if (open_centred) {
+ int scroll_width = ro_get_vscroll_width(NULL);
+ window.visible.x0 -= scroll_width;
+ }
+
+ error = xwimp_create_window(&window, &g->window);
+ if (error) {
+ LOG("xwimp_create_window: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ free(g);
+ return 0;
+ }
+
+ /* Link into window list */
+ g->prev = 0;
+ g->next = window_list;
+ if (window_list)
+ window_list->prev = g;
+ window_list = g;
+ window_count++;
+
+ /* Add in a toolbar and status bar */
+ g->status_bar = ro_gui_status_bar_create(g->window,
+ nsoption_int(toolbar_status_size));
+ g->toolbar = ro_toolbar_create(NULL, g->window,
+ THEME_STYLE_BROWSER_TOOLBAR, TOOLBAR_FLAGS_NONE,
+ &ro_gui_window_toolbar_callbacks, g,
+ "HelpToolbar");
+ if (g->toolbar != NULL) {
+ ro_toolbar_add_buttons(g->toolbar,
+ brower_toolbar_buttons,
+ nsoption_charp(toolbar_browser));
+ ro_toolbar_add_url(g->toolbar);
+ ro_toolbar_add_throbber(g->toolbar);
+ ro_toolbar_rebuild(g->toolbar);
+ }
+
+ /* Register event handlers. Do this quickly, as some of the things
+ * that follow will indirectly look up our user data: this MUST
+ * be set first!
+ */
+ ro_gui_wimp_event_set_user_data(g->window, g);
+ ro_gui_wimp_event_register_open_window(g->window, ro_gui_window_open);
+ ro_gui_wimp_event_register_close_window(g->window, ro_gui_window_close);
+ ro_gui_wimp_event_register_redraw_window(g->window, ro_gui_window_redraw);
+ ro_gui_wimp_event_register_scroll_window(g->window, ro_gui_window_scroll);
+ ro_gui_wimp_event_register_pointer_entering_window(g->window, ro_gui_window_pointer_entering);
+ ro_gui_wimp_event_register_keypress(g->window, ro_gui_window_keypress);
+ ro_gui_wimp_event_register_mouse_click(g->window, ro_gui_window_click);
+ ro_gui_wimp_event_register_menu(g->window, ro_gui_browser_window_menu,
+ true, false);
+ ro_gui_wimp_event_register_menu_prepare(g->window,
+ ro_gui_window_menu_prepare);
+ ro_gui_wimp_event_register_menu_selection(g->window,
+ ro_gui_window_menu_select);
+ ro_gui_wimp_event_register_menu_warning(g->window,
+ ro_gui_window_menu_warning);
+ ro_gui_wimp_event_register_menu_close(g->window,
+ ro_gui_window_menu_close);
+
+ /* Set the window options */
+ ro_gui_window_clone_options(g, existing);
+ ro_gui_window_update_toolbar_buttons(g);
+
+ /* Open the window at the top of the stack */
+ state.w = g->window;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return g;
+ }
+
+ state.next = wimp_TOP;
+
+ ro_gui_window_open(PTR_WIMP_OPEN(&state));
+
+ /* Claim the caret */
+ if (ro_toolbar_take_caret(g->toolbar))
+ ro_gui_url_complete_start(g->toolbar);
+ else
+ gui_window_place_caret(g, -100, -100, 0, NULL);
+
+ return g;
+}
+
+
+/**
+ * Close a browser window and free any related resources.
+ *
+ * \param g gui_window to destroy
+ */
+
+static void gui_window_destroy(struct gui_window *g)
+{
+ os_error *error;
+ wimp_w w;
+
+ assert(g);
+
+ /* stop any tracking */
+ ro_mouse_kill(g);
+
+ /* remove from list */
+ if (g->prev)
+ g->prev->next = g->next;
+ else
+ window_list = g->next;
+ if (g->next)
+ g->next->prev = g->prev;
+
+ /* destroy toolbar */
+ if (g->toolbar)
+ ro_toolbar_destroy(g->toolbar);
+ if (g->status_bar)
+ ro_gui_status_bar_destroy(g->status_bar);
+
+ w = g->window;
+ ro_gui_url_complete_close();
+ ro_gui_dialog_close_persistent(w);
+ if (current_menu_window == w)
+ ro_gui_menu_destroy();
+ ro_gui_window_remove_update_boxes(g);
+
+ /* delete window */
+ error = xwimp_delete_window(w);
+ if (error) {
+ LOG("xwimp_delete_window: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+ ro_gui_wimp_event_finalise(w);
+
+ free(g);
+}
+
+
+/**
+ * Set the title of a browser window.
+ *
+ * \param g gui_window to update
+ * \param title new window title, copied
+ */
+
+static void gui_window_set_title(struct gui_window *g, const char *title)
+{
+ assert(g);
+ assert(title);
+
+ if (g->scale != 1.0) {
+ int scale_disp = g->scale * 100;
+
+ if (ABS((float)scale_disp - g->scale * 100) >= 0.05)
+ snprintf(g->title, sizeof g->title, "%s (%.1f%%)",
+ title, g->scale * 100);
+ else
+ snprintf(g->title, sizeof g->title, "%s (%i%%)",
+ title, scale_disp);
+ } else {
+ strncpy(g->title, title, sizeof g->title);
+ }
+
+ ro_gui_set_window_title(g->window, g->title);
+}
+
+
+/**
+ * Force a redraw of the entire contents of a browser window.
+ *
+ * \param g gui_window to redraw
+ */
+void gui_window_redraw_window(struct gui_window *g)
+{
+ wimp_window_info info;
+ os_error *error;
+
+ assert(g);
+ info.w = g->window;
+ error = xwimp_get_window_info_header_only(&info);
+ if (error) {
+ LOG("xwimp_get_window_info_header_only: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+ error = xwimp_force_redraw(g->window, info.extent.x0, info.extent.y0,
+ info.extent.x1, info.extent.y1);
+ if (error) {
+ LOG("xwimp_force_redraw: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+}
+
+
+/**
+ * Redraw an area of a window.
+ *
+ * \param g The window to update
+ * \param rect The area of the window to update.
+ */
+
+static void gui_window_update_box(struct gui_window *g, const struct rect *rect)
+{
+ bool use_buffer;
+ int x0, y0, x1, y1;
+ struct update_box *cur;
+
+ x0 = floorf(rect->x0 * 2 * g->scale);
+ y0 = -ceilf(rect->y1 * 2 * g->scale);
+ x1 = ceilf(rect->x1 * 2 * g->scale) + 1;
+ y1 = -floorf(rect->y0 * 2 * g->scale) + 1;
+ use_buffer =
+ (g->option.buffer_everything || g->option.buffer_animations);
+
+ /* try to optimise buffered redraws */
+ if (use_buffer) {
+ for (cur = pending_updates; cur != NULL; cur = cur->next) {
+ if ((cur->g != g) || (!cur->use_buffer))
+ continue;
+ if ((((cur->x0 - x1) < MARGIN) || ((cur->x1 - x0) < MARGIN)) &&
+ (((cur->y0 - y1) < MARGIN) || ((cur->y1 - y0) < MARGIN))) {
+ cur->x0 = min(cur->x0, x0);
+ cur->y0 = min(cur->y0, y0);
+ cur->x1 = max(cur->x1, x1);
+ cur->y1 = max(cur->y1, y1);
+ return;
+ }
+
+ }
+ }
+ cur = malloc(sizeof(struct update_box));
+ if (!cur) {
+ LOG("No memory for malloc.");
+ ro_warn_user("NoMemory", 0);
+ return;
+ }
+ cur->x0 = x0;
+ cur->y0 = y0;
+ cur->x1 = x1;
+ cur->y1 = y1;
+ cur->next = pending_updates;
+ pending_updates = cur;
+ cur->g = g;
+ cur->use_buffer = use_buffer;
+}
+
+
+/**
+ * Get the scroll position of a browser window.
+ *
+ * \param g gui_window
+ * \param sx receives x ordinate of point at top-left of window
+ * \param sy receives y ordinate of point at top-left of window
+ * \return true iff successful
+ */
+
+static bool gui_window_get_scroll(struct gui_window *g, int *sx, int *sy)
+{
+ wimp_window_state state;
+ os_error *error;
+ int toolbar_height = 0;
+
+ assert(g);
+
+ state.w = g->window;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return false;
+ }
+
+ if (g->toolbar)
+ toolbar_height = ro_toolbar_full_height(g->toolbar);
+ *sx = state.xscroll / (2 * g->scale);
+ *sy = -(state.yscroll - toolbar_height) / (2 * g->scale);
+ return true;
+}
+
+
+/**
+ * Set the scroll position of a browser window.
+ *
+ * \param g gui_window to scroll
+ * \param sx point to place at top-left of window
+ * \param sy point to place at top-left of window
+ */
+
+static void gui_window_set_scroll(struct gui_window *g, int sx, int sy)
+{
+ wimp_window_state state;
+ os_error *error;
+
+ assert(g);
+
+ state.w = g->window;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ state.xscroll = sx * 2 * g->scale;
+ state.yscroll = -sy * 2 * g->scale;
+ if (g->toolbar)
+ state.yscroll += ro_toolbar_full_height(g->toolbar);
+ ro_gui_window_open(PTR_WIMP_OPEN(&state));
+}
+
+
+/**
+ * Scrolls the specified area of a browser window into view.
+ *
+ * \param g gui_window to scroll
+ * \param x0 left point to ensure visible
+ * \param y0 bottom point to ensure visible
+ * \param x1 right point to ensure visible
+ * \param y1 top point to ensure visible
+ */
+static void gui_window_scroll_visible(struct gui_window *g, int x0, int y0, int x1, int y1)
+{
+ wimp_window_state state;
+ os_error *error;
+ int cx0, cy0, width, height;
+ int padding_available;
+ int toolbar_height = 0;
+ int correction;
+
+ assert(g);
+
+ state.w = g->window;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ if (g->toolbar)
+ toolbar_height = ro_toolbar_full_height(g->toolbar);
+
+ x0 = x0 * 2 * g->scale;
+ y0 = y0 * 2 * g->scale;
+ x1 = x1 * 2 * g->scale;
+ y1 = y1 * 2 * g->scale;
+
+ cx0 = state.xscroll;
+ cy0 = -state.yscroll + toolbar_height;
+ width = state.visible.x1 - state.visible.x0;
+ height = state.visible.y1 - state.visible.y0 - toolbar_height;
+
+ /* make sure we're visible */
+ correction = (x1 - cx0 - width);
+ if (correction > 0)
+ cx0 += correction;
+ correction = (y1 - cy0 - height);
+ if (correction > 0)
+ cy0 += correction;
+ if (x0 < cx0)
+ cx0 = x0;
+ if (y0 < cy0)
+ cy0 = y0;
+
+ /* try to give a SCROLL_VISIBLE_PADDING border of space around us */
+ padding_available = (width - x1 + x0) / 2;
+ if (padding_available > 0) {
+ if (padding_available > SCROLL_VISIBLE_PADDING)
+ padding_available = SCROLL_VISIBLE_PADDING;
+ correction = (cx0 + width - x1);
+ if (correction < padding_available)
+ cx0 += padding_available;
+ correction = (x0 - cx0);
+ if (correction < padding_available)
+ cx0 -= padding_available;
+ }
+ padding_available = (height - y1 + y0) / 2;
+ if (padding_available > 0) {
+ if (padding_available > SCROLL_VISIBLE_PADDING)
+ padding_available = SCROLL_VISIBLE_PADDING;
+ correction = (cy0 + height - y1);
+ if (correction < padding_available)
+ cy0 += padding_available;
+ correction = (y0 - cy0);
+ if (correction < padding_available)
+ cy0 -= padding_available;
+ }
+
+ state.xscroll = cx0;
+ state.yscroll = -cy0 + toolbar_height;
+ ro_gui_window_open(PTR_WIMP_OPEN(&state));
+}
+
+
+/**
+ * Find the current dimensions of a browser window's content area.
+ *
+ * \param g gui_window to measure
+ * \param width receives width of window
+ * \param height receives height of window
+ * \param scaled whether to return scaled values
+ */
+
+static void gui_window_get_dimensions(struct gui_window *g, int *width, int *height, bool scaled)
+{
+ /* use the cached window sizes */
+ *width = g->old_width / 2;
+ *height = g->old_height / 2;
+ if (scaled) {
+ *width /= g->scale;
+ *height /= g->scale;
+ }
+}
+
+
+/**
+ * Update the extent of the inside of a browser window to that of the
+ * current content.
+ *
+ * \param g gui_window to update the extent of
+ */
+
+static void gui_window_update_extent(struct gui_window *g)
+{
+ os_error *error;
+ wimp_window_info info;
+
+ assert(g);
+
+ info.w = g->window;
+ error = xwimp_get_window_info_header_only(&info);
+ if (error) {
+ LOG("xwimp_get_window_info_header_only: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ /* scroll on toolbar height change */
+ if (g->toolbar) {
+ int scroll = ro_toolbar_height(g->toolbar) - info.extent.y1;
+ info.yscroll += scroll;
+ }
+
+ /* Handle change of extents */
+ g->update_extent = true;
+ ro_gui_window_open(PTR_WIMP_OPEN(&info));
+}
+
+
+/**
+ * Set the status bar of a browser window.
+ *
+ * \param g gui_window to update
+ * \param text new status text
+ */
+
+static void riscos_window_set_status(struct gui_window *g, const char *text)
+{
+ if (g->status_bar)
+ ro_gui_status_bar_set_text(g->status_bar, text);
+}
+
+
+/**
+ * Change mouse pointer shape
+ */
+
+void gui_window_set_pointer(struct gui_window *g, gui_pointer_shape shape)
+{
+ static gui_pointer_shape curr_pointer = GUI_POINTER_DEFAULT;
+ struct ro_gui_pointer_entry *entry;
+ os_error *error;
+
+ if (shape == curr_pointer)
+ return;
+
+ assert(shape < sizeof ro_gui_pointer_table /
+ sizeof ro_gui_pointer_table[0]);
+
+ entry = &ro_gui_pointer_table[shape];
+
+ if (entry->wimp_area) {
+ /* pointer in the Wimp's sprite area */
+ error = xwimpspriteop_set_pointer_shape(entry->sprite_name,
+ 1, entry->xactive, entry->yactive, 0, 0);
+ if (error) {
+ LOG("xwimpspriteop_set_pointer_shape: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+ } else {
+ /* pointer in our own sprite area */
+ error = xosspriteop_set_pointer_shape(osspriteop_USER_AREA,
+ gui_sprites,
+ (osspriteop_id) entry->sprite_name,
+ 1, entry->xactive, entry->yactive, 0, 0);
+ if (error) {
+ LOG("xosspriteop_set_pointer_shape: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+ }
+
+ curr_pointer = shape;
+}
+
+
+/* exported function documented in riscos/window.h */
+nserror ro_gui_window_set_url(struct gui_window *g, nsurl *url)
+{
+ size_t idn_url_l;
+ char *idn_url_s = NULL;
+
+ if (g->toolbar) {
+ if (nsoption_bool(display_decoded_idn) == true) {
+ if (nsurl_get_utf8(url, &idn_url_s, &idn_url_l) != NSERROR_OK)
+ idn_url_s = NULL;
+ }
+
+ ro_toolbar_set_url(g->toolbar, idn_url_s ? idn_url_s : nsurl_access(url), true, false);
+
+ if (idn_url_s)
+ free(idn_url_s);
+
+ ro_gui_url_complete_start(g->toolbar);
+ }
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * Update the interface to reflect start of page loading.
+ *
+ * \param g window with start of load
+ */
+
+static void gui_window_start_throbber(struct gui_window *g)
+{
+ ro_gui_window_update_toolbar_buttons(g);
+ ro_gui_menu_refresh(ro_gui_browser_window_menu);
+ if (g->toolbar != NULL)
+ ro_toolbar_start_throbbing(g->toolbar);
+ g->active = true;
+}
+
+
+
+/**
+ * Update the interface to reflect page loading stopped.
+ *
+ * \param g window with start of load
+ */
+
+static void gui_window_stop_throbber(struct gui_window *g)
+{
+ ro_gui_window_update_toolbar_buttons(g);
+ ro_gui_menu_refresh(ro_gui_browser_window_menu);
+ if (g->toolbar != NULL)
+ ro_toolbar_stop_throbbing(g->toolbar);
+ g->active = false;
+}
+
+/**
+ * set favicon
+ */
+
+static void gui_window_set_icon(struct gui_window *g, hlcache_handle *icon)
+{
+ if (g == NULL || g->toolbar == NULL)
+ return;
+
+ ro_toolbar_set_site_favicon(g->toolbar, icon);
+}
+
+
+
+/**
+ * Remove the caret, if present.
+ *
+ * \param g window with caret
+ */
+
+static void gui_window_remove_caret(struct gui_window *g)
+{
+ wimp_caret caret;
+ os_error *error;
+
+ error = xwimp_get_caret_position(&caret);
+ if (error) {
+ LOG("xwimp_get_caret_position: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ if (caret.w != g->window)
+ /* we don't have the caret: do nothing */
+ return;
+
+ /* hide caret, but keep input focus */
+ gui_window_place_caret(g, -100, -100, 0, NULL);
+}
+
+
+/**
+ * Called when the gui_window has new content.
+ *
+ * \param g the gui_window that has new content
+ */
+
+static void gui_window_new_content(struct gui_window *g)
+{
+ ro_gui_menu_refresh(ro_gui_browser_window_menu);
+ ro_gui_window_update_toolbar_buttons(g);
+ ro_gui_dialog_close_persistent(g->window);
+ ro_toolbar_set_content_favicon(g->toolbar, g);
+}
+
+
+/**
+ * Starts drag scrolling of a browser window
+ *
+ * \param g the window to scroll
+ */
+
+static bool gui_window_scroll_start(struct gui_window *g)
+{
+ wimp_window_info_base info;
+ wimp_pointer pointer;
+ os_error *error;
+ wimp_drag drag;
+ int height;
+ int width;
+
+ error = xwimp_get_pointer_info(&pointer);
+ if (error) {
+ LOG("xwimp_get_pointer_info 0x%x : %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return false;
+ }
+
+ info.w = g->window;
+ error = xwimp_get_window_info_header_only((wimp_window_info*)&info);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x : %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return false;
+ }
+
+ width = info.extent.x1 - info.extent.x0;
+ height = info.extent.y1 - info.extent.y0;
+
+ drag.type = wimp_DRAG_USER_POINT;
+ drag.bbox.x1 = pointer.pos.x + info.xscroll;
+ drag.bbox.y0 = pointer.pos.y + info.yscroll;
+ drag.bbox.x0 = drag.bbox.x1 - (width - (info.visible.x1 - info.visible.x0));
+ drag.bbox.y1 = drag.bbox.y0 + (height - (info.visible.y1 - info.visible.y0));
+
+ if (g->toolbar) {
+ int tbar_height = ro_toolbar_full_height(g->toolbar);
+ drag.bbox.y0 -= tbar_height;
+ drag.bbox.y1 -= tbar_height;
+ }
+
+ error = xwimp_drag_box(&drag);
+ if (error) {
+ LOG("xwimp_drag_box: 0x%x : %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return false;
+ }
+
+ ro_mouse_drag_start(ro_gui_window_scroll_end, ro_gui_window_mouse_at,
+ NULL, g);
+ return true;
+}
+
+
+/**
+ * Platform-dependent part of starting drag operation.
+ *
+ * \param g gui window containing the drag
+ * \param type type of drag the core is performing
+ * \param rect rectangle to constrain pointer to (relative to drag start coord)
+ * \return true iff succesful
+ */
+
+static bool gui_window_drag_start(struct gui_window *g, gui_drag_type type,
+ const struct rect *rect)
+{
+ wimp_pointer pointer;
+ wimp_drag drag;
+
+ if (rect != NULL) {
+ /* We have a box to constrain the pointer to, for the drag
+ * duration */
+ os_error *error = xwimp_get_pointer_info(&pointer);
+ if (error) {
+ LOG("xwimp_get_pointer_info 0x%x : %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return false;
+ }
+
+ drag.type = wimp_DRAG_USER_POINT;
+ drag.bbox.x0 = pointer.pos.x +
+ (int)(rect->x0 * 2 * g->scale);
+ drag.bbox.y0 = pointer.pos.y +
+ (int)(rect->y0 * 2 * g->scale);
+ drag.bbox.x1 = pointer.pos.x +
+ (int)(rect->x1 * 2 * g->scale);
+ drag.bbox.y1 = pointer.pos.y +
+ (int)(rect->y1 * 2 * g->scale);
+
+ error = xwimp_drag_box(&drag);
+ if (error) {
+ LOG("xwimp_drag_box: 0x%x : %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return false;
+ }
+ }
+
+ switch (type) {
+ case GDRAGGING_SCROLLBAR:
+ /* Dragging a core scrollbar */
+ ro_mouse_drag_start(ro_gui_window_scroll_end, ro_gui_window_mouse_at,
+ NULL, g);
+ break;
+
+ default:
+ /* Not handled here yet */
+ break;
+ }
+
+ return true;
+}
+
+
+/**
+ * Save the specified content as a link.
+ *
+ * \param g The window containing the content
+ * \param url The url of the link
+ * \param title The title of the link
+ */
+static nserror
+gui_window_save_link(struct gui_window *g, nsurl *url, const char *title)
+{
+ ro_gui_save_prepare(GUI_SAVE_LINK_URL, NULL, NULL, url, title);
+ ro_gui_dialog_open_persistent(g->window, dialog_saveas, true);
+ return NSERROR_OK;
+}
+
+
+/**
+ * Updates a windows extent.
+ *
+ * \param g the gui_window to update
+ * \param width the minimum width, or -1 to use window width
+ * \param height the minimum height, or -1 to use window height
+ */
+
+void gui_window_set_extent(struct gui_window *g, int width, int height)
+{
+ int screen_width;
+ int toolbar_height = 0;
+ wimp_window_state state;
+ os_error *error;
+
+ if (g->toolbar)
+ toolbar_height = ro_toolbar_full_height(g->toolbar);
+
+ /* get the current state */
+ if ((height == -1) || (width == -1)) {
+ state.w = g->window;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+ if (width == -1)
+ width = state.visible.x1 - state.visible.x0;
+ if (height == -1) {
+ height = state.visible.y1 - state.visible.y0;
+ height -= toolbar_height;
+ }
+ }
+
+ /* the top-level framed window is a total pain. to get it to maximise
+ * to the top of the screen we need to fake it having a suitably large
+ * extent */
+ if (browser_window_is_frameset(g->bw)) {
+ ro_gui_screen_size(&screen_width, &height);
+ if (g->toolbar)
+ height -= ro_toolbar_full_height(g->toolbar);
+ height -= ro_get_hscroll_height(g->window);
+ height -= ro_get_title_height(g->window);
+ }
+ if (browser_window_has_content(g->bw)) {
+ int w, h;
+ browser_window_get_extents(g->bw, true, &w, &h);
+ width = max(width, w * 2);
+ height = max(height, h * 2);
+ }
+ os_box extent = { 0, -height, width, toolbar_height };
+ error = xwimp_set_extent(g->window, &extent);
+ if (error) {
+ LOG("xwimp_set_extent: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+}
+
+
+/**
+ * Display a menu of options for a form select control.
+ *
+ * \param g gui window containing form control
+ * \param control form control of type GADGET_SELECT
+ */
+
+static void gui_window_create_form_select_menu(struct gui_window *g,
+ struct form_control *control)
+{
+ os_error *error;
+ wimp_pointer pointer;
+
+ /* The first time the menu is opened, control bypasses the normal
+ * Menu Prepare event and so we prepare here. On any re-opens,
+ * ro_gui_window_prepare_form_select_menu() is called from the
+ * normal wimp event.
+ */
+
+ if (!ro_gui_window_prepare_form_select_menu(g, control))
+ return;
+
+ error = xwimp_get_pointer_info(&pointer);
+ if (error) {
+ LOG("xwimp_get_pointer_info: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ ro_gui_menu_destroy();
+ return;
+ }
+
+ gui_form_select_control = control;
+ ro_gui_menu_create(gui_form_select_menu,
+ pointer.pos.x, pointer.pos.y, g->window);
+}
+
+
+/*
+ * RISC OS Wimp Event Handlers
+ */
+
+
+/**
+ * Handle a Redraw_Window_Request for a browser window.
+ */
+
+void ro_gui_window_redraw(wimp_draw *redraw)
+{
+ osbool more;
+ struct gui_window *g = (struct gui_window *)ro_gui_wimp_event_get_user_data(redraw->w);
+ os_error *error;
+ struct redraw_context ctx = {
+ .interactive = true,
+ .background_images = true,
+ .plot = &ro_plotters
+ };
+
+ /* We can't render locked contents. If the browser window is not
+ * ready for redraw, do nothing. Else, in the case of buffered
+ * rendering we'll show random data. */
+ if (!browser_window_redraw_ready(g->bw))
+ return;
+
+ ro_gui_current_redraw_gui = g;
+
+ error = xwimp_redraw_window(redraw, &more);
+ if (error) {
+ LOG("xwimp_redraw_window: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+ while (more) {
+ struct rect clip;
+
+ /* OS's redraw request coordinates are in screen coordinates,
+ * with an origin at the bottom left of the screen.
+ * Find the coordinate of the top left of the document in terms
+ * of OS screen coordinates.
+ * NOTE: OS units are 2 per px. */
+ ro_plot_origin_x = redraw->box.x0 - redraw->xscroll;
+ ro_plot_origin_y = redraw->box.y1 - redraw->yscroll;
+
+ /* Convert OS redraw rectangle request coordinates into NetSurf
+ * coordinates. NetSurf coordinates have origin at top left of
+ * document and units are in px. */
+ clip.x0 = (redraw->clip.x0 - ro_plot_origin_x) / 2; /* left */
+ clip.y0 = (ro_plot_origin_y - redraw->clip.y1) / 2; /* top */
+ clip.x1 = (redraw->clip.x1 - ro_plot_origin_x) / 2; /* right */
+ clip.y1 = (ro_plot_origin_y - redraw->clip.y0) / 2; /* bottom */
+
+ if (ro_gui_current_redraw_gui->option.buffer_everything)
+ ro_gui_buffer_open(redraw);
+
+ browser_window_redraw(g->bw, 0, 0, &clip, &ctx);
+
+ if (ro_gui_current_redraw_gui->option.buffer_everything)
+ ro_gui_buffer_close();
+
+ /* Check to see if there are more rectangles to draw and
+ * get next one */
+ error = xwimp_get_rectangle(redraw, &more);
+ /* RISC OS 3.7 returns an error here if enough buffer was
+ claimed to cause a new dynamic area to be created. It
+ doesn't actually stop anything working, so we mask it out
+ for now until a better fix is found. This appears to be a
+ bug in RISC OS. */
+ if (error && !(ro_gui_current_redraw_gui->
+ option.buffer_everything &&
+ error->errnum == error_WIMP_GET_RECT)) {
+ LOG("xwimp_get_rectangle: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ ro_gui_current_redraw_gui = NULL;
+ return;
+ }
+ }
+ ro_gui_current_redraw_gui = NULL;
+}
+
+
+/**
+ * Set a gui_window's scale
+ */
+void ro_gui_window_set_scale(struct gui_window *g, float scale)
+{
+ g->scale = scale;
+ browser_window_set_scale(g->bw, scale, true);
+}
+
+
+/**
+ * Open a window using the given wimp_open, handling toolbars and resizing.
+ */
+
+void ro_gui_window_open(wimp_open *open)
+{
+ struct gui_window *g = (struct gui_window *)ro_gui_wimp_event_get_user_data(open->w);
+ int width = open->visible.x1 - open->visible.x0;
+ int height = open->visible.y1 - open->visible.y0;
+ browser_scrolling h_scroll;
+ browser_scrolling v_scroll;
+ int toolbar_height = 0;
+ float new_scale = 0;
+ wimp_window_state state;
+ os_error *error;
+ wimp_w parent;
+ bits linkage;
+ bool have_content;
+
+ if (open->next == wimp_TOP && g->iconise_icon >= 0) {
+ /* window is no longer iconised, release its sprite number */
+ iconise_used[g->iconise_icon] = false;
+ g->iconise_icon = -1;
+ }
+
+ have_content = browser_window_has_content(g->bw);
+
+ /* get the current flags/nesting state */
+ state.w = g->window;
+ error = xwimp_get_window_state_and_nesting(&state, &parent, &linkage);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ /* account for toolbar height, if present */
+ if (g->toolbar)
+ toolbar_height = ro_toolbar_full_height(g->toolbar);
+ height -= toolbar_height;
+
+ /* work with the state from now on so we can modify flags */
+ state.visible = open->visible;
+ state.xscroll = open->xscroll;
+ state.yscroll = open->yscroll;
+ state.next = open->next;
+
+ browser_window_get_scrollbar_type(g->bw, &h_scroll, &v_scroll);
+
+ /* handle 'auto' scroll bars' and non-fitting scrollbar removal */
+ if ((h_scroll != BW_SCROLLING_NO) && (v_scroll != BW_SCROLLING_NO)) {
+ int size;
+
+ /* windows lose scrollbars when containing a frameset */
+ bool no_hscroll = false;
+ bool no_vscroll = browser_window_is_frameset(g->bw);
+
+ /* hscroll */
+ size = ro_get_hscroll_height(NULL);
+ size -= 2; /* 1px border on both sides */
+ if (!no_hscroll) {
+ if (!(state.flags & wimp_WINDOW_HSCROLL)) {
+ height -= size;
+ state.visible.y0 += size;
+ if (have_content) {
+ browser_window_schedule_reformat(g->bw);
+ }
+ }
+ state.flags |= wimp_WINDOW_HSCROLL;
+ } else {
+ if (state.flags & wimp_WINDOW_HSCROLL) {
+ height += size;
+ state.visible.y0 -= size;
+ if (have_content) {
+ browser_window_schedule_reformat(g->bw);
+ }
+ }
+ state.flags &= ~wimp_WINDOW_HSCROLL;
+ }
+
+ /* vscroll */
+ size = ro_get_vscroll_width(NULL);
+ size -= 2; /* 1px border on both sides */
+ if (!no_vscroll) {
+ if (!(state.flags & wimp_WINDOW_VSCROLL)) {
+ width -= size;
+ state.visible.x1 -= size;
+ if (have_content) {
+ browser_window_schedule_reformat(g->bw);
+ }
+ }
+ state.flags |= wimp_WINDOW_VSCROLL;
+ } else {
+ if (state.flags & wimp_WINDOW_VSCROLL) {
+ width += size;
+ state.visible.x1 += size;
+ if (have_content) {
+ browser_window_schedule_reformat(g->bw);
+ }
+ }
+ state.flags &= ~wimp_WINDOW_VSCROLL;
+ }
+ }
+
+ /* reformat or change extent if necessary */
+ if (have_content &&
+ (g->old_width != width || g->old_height != height)) {
+ /* Ctrl-resize of a top-level window scales the content size */
+ if ((g->old_width > 0) && (g->old_width != width) &&
+ (ro_gui_ctrl_pressed()))
+ new_scale = (g->scale * width) / g->old_width;
+ browser_window_schedule_reformat(g->bw);
+ }
+ if (g->update_extent || g->old_width != width ||
+ g->old_height != height) {
+ g->old_width = width;
+ g->old_height = height;
+ g->update_extent = false;
+ gui_window_set_extent(g, width, height);
+ }
+
+ /* first resize stops any flickering by making the URL window on top */
+ ro_gui_url_complete_resize(g->toolbar, PTR_WIMP_OPEN(&state));
+
+ /* Windows containing framesets can only be scrolled via the core, which
+ * is implementing frame scrollbars itself. The x and y offsets are
+ * therefore fixed.
+ */
+
+ if (browser_window_is_frameset(g->bw)) {
+ state.xscroll = 0;
+ state.yscroll = toolbar_height;
+ }
+
+ error = xwimp_open_window_nested_with_flags(&state, parent, linkage);
+ if (error) {
+ LOG("xwimp_open_window: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ /* update the toolbar */
+ if (g->status_bar)
+ ro_gui_status_bar_resize(g->status_bar);
+ if (g->toolbar) {
+ ro_toolbar_process(g->toolbar, -1, false);
+ /* second resize updates to the new URL bar width */
+ ro_gui_url_complete_resize(g->toolbar, open);
+ }
+
+ /* set the new scale from a ctrl-resize. this must be done at the end as
+ * it may cause a frameset recalculation based on the new window size.
+ */
+ if (new_scale > 0) {
+ ro_gui_window_set_scale(g, new_scale);
+ }
+}
+
+
+/**
+ * Handle wimp closing event
+ */
+
+void ro_gui_window_close(wimp_w w)
+{
+ struct gui_window *g = (struct gui_window *)ro_gui_wimp_event_get_user_data(w);
+ wimp_pointer pointer;
+ os_error *error;
+ char *temp_name;
+ char *filename = NULL;
+ struct nsurl *url;
+ bool destroy;
+
+ error = xwimp_get_pointer_info(&pointer);
+ if (error) {
+ LOG("xwimp_get_pointer_info: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ if (pointer.buttons & wimp_CLICK_ADJUST) {
+ destroy = !ro_gui_shift_pressed();
+
+ url = browser_window_get_url(g->bw);
+ if (url != NULL) {
+ netsurf_nsurl_to_path(url, &filename);
+ }
+ if (filename != NULL) {
+ temp_name = malloc(strlen(filename) + 32);
+ if (temp_name) {
+ char *r;
+ sprintf(temp_name, "Filer_OpenDir %s",
+ filename);
+ r = temp_name + strlen(temp_name);
+ while (r > temp_name) {
+ if (*r == '.') {
+ *r = '\0';
+ break;
+ }
+ r--;
+ }
+ error = xos_cli(temp_name);
+ if (error) {
+ LOG("xos_cli: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("MiscError", error->errmess);
+ return;
+ }
+ free(temp_name);
+ }
+ free(filename);
+ } else {
+ /* this is pointless if we are about to close the
+ * window */
+ if (!destroy && url != NULL)
+ browser_window_navigate_up(g->bw, false);
+ }
+ }
+ else
+ destroy = true;
+
+ if (destroy)
+ browser_window_destroy(g->bw);
+}
+
+
+/**
+ * Handle Mouse_Click events in a browser window. This should never see
+ * Menu clicks, as these will be routed to the menu handlers.
+ *
+ * \param *pointer details of mouse click
+ * \return true if click handled, false otherwise
+ */
+
+bool ro_gui_window_click(wimp_pointer *pointer)
+{
+ struct gui_window *g;
+ os_coord pos;
+
+ /* We should never see Menu clicks. */
+
+ if (pointer->buttons == wimp_CLICK_MENU)
+ return false;
+
+ g = (struct gui_window *) ro_gui_wimp_event_get_user_data(pointer->w);
+
+ /* try to close url-completion */
+ ro_gui_url_complete_close();
+
+ /* set input focus */
+ if (pointer->buttons & (wimp_SINGLE_SELECT | wimp_SINGLE_ADJUST))
+ gui_window_place_caret(g, -100, -100, 0, NULL);
+
+ if (ro_gui_window_to_window_pos(g, pointer->pos.x, pointer->pos.y, &pos))
+ browser_window_mouse_click(g->bw,
+ ro_gui_mouse_click_state(pointer->buttons,
+ wimp_BUTTON_DOUBLE_CLICK_DRAG),
+ pos.x, pos.y);
+
+ return true;
+}
+
+
+/**
+ * Process Key_Pressed events in a browser window.
+ *
+ * \param *key The wimp keypress block for the event.
+ * \return true if the event was handled, else false.
+ */
+
+bool ro_gui_window_keypress(wimp_key *key)
+{
+ struct gui_window *g;
+ uint32_t c = (uint32_t) key->c;
+
+ g = (struct gui_window *) ro_gui_wimp_event_get_user_data(key->w);
+ if (g == NULL)
+ return false;
+
+ /* First send the key to the browser window, eg. form fields. */
+
+ if ((unsigned)c < 0x20 || (0x7f <= c && c <= 0x9f) ||
+ (c & IS_WIMP_KEY)) {
+ /* Munge control keys into unused control chars */
+ /* We can't map onto 1->26 (reserved for ctrl+<qwerty>
+ That leaves 27->31 and 128->159 */
+ switch (c & ~IS_WIMP_KEY) {
+ case wimp_KEY_TAB: c = 9; break;
+ case wimp_KEY_SHIFT | wimp_KEY_TAB: c = 11; break;
+
+ /* cursor movement keys */
+ case wimp_KEY_HOME:
+ case wimp_KEY_CONTROL | wimp_KEY_LEFT:
+ c = NS_KEY_LINE_START;
+ break;
+ case wimp_KEY_END:
+ if (os_version >= RISCOS5)
+ c = NS_KEY_LINE_END;
+ else
+ c = NS_KEY_DELETE_RIGHT;
+ break;
+ case wimp_KEY_CONTROL | wimp_KEY_RIGHT: c = NS_KEY_LINE_END; break;
+ case wimp_KEY_CONTROL | wimp_KEY_UP: c = NS_KEY_TEXT_START; break;
+ case wimp_KEY_CONTROL | wimp_KEY_DOWN: c = NS_KEY_TEXT_END; break;
+ case wimp_KEY_SHIFT | wimp_KEY_LEFT: c = NS_KEY_WORD_LEFT ; break;
+ case wimp_KEY_SHIFT | wimp_KEY_RIGHT: c = NS_KEY_WORD_RIGHT; break;
+ case wimp_KEY_SHIFT | wimp_KEY_UP: c = NS_KEY_PAGE_UP; break;
+ case wimp_KEY_SHIFT | wimp_KEY_DOWN: c = NS_KEY_PAGE_DOWN; break;
+ case wimp_KEY_LEFT: c = NS_KEY_LEFT; break;
+ case wimp_KEY_RIGHT: c = NS_KEY_RIGHT; break;
+ case wimp_KEY_UP: c = NS_KEY_UP; break;
+ case wimp_KEY_DOWN: c = NS_KEY_DOWN; break;
+
+ /* editing */
+ case wimp_KEY_CONTROL | wimp_KEY_END:
+ c = NS_KEY_DELETE_LINE_END;
+ break;
+ case wimp_KEY_DELETE:
+ if (ro_gui_ctrl_pressed())
+ c = NS_KEY_DELETE_LINE_START;
+ else if (os_version < RISCOS5)
+ c = NS_KEY_DELETE_LEFT;
+ break;
+
+ case wimp_KEY_F8:
+ c = NS_KEY_UNDO;
+ break;
+ case wimp_KEY_F9:
+ c = NS_KEY_REDO;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (!(c & IS_WIMP_KEY)) {
+ if (browser_window_key_press(g->bw, c))
+ return true;
+ }
+
+ return ro_gui_window_handle_local_keypress(g, key, false);
+}
+
+
+/**
+ * Callback handler for keypresses within browser window toolbars.
+ *
+ * \param *data Client data, pointing to the GUI Window.
+ * \param *key The keypress data.
+ * \return true if the keypress was handled; else false.
+ */
+
+bool ro_gui_window_toolbar_keypress(void *data, wimp_key *key)
+{
+ struct gui_window *g = (struct gui_window *) data;
+
+ if (g != NULL)
+ return ro_gui_window_handle_local_keypress(g, key, true);
+
+ return false;
+}
+
+
+/**
+ * Handle keypresses within the RISC OS GUI: this is to be called after the
+ * core has been given a chance to act, or on keypresses in the toolbar where
+ * the core doesn't get involved.
+ *
+ * \param *g The gui window to which the keypress applies.
+ * \param *key The keypress data.
+ * \param is_toolbar true if the keypress is from a toolbar;
+ * else false.
+ * \return true if the keypress was claimed; else false.
+ */
+
+bool ro_gui_window_handle_local_keypress(struct gui_window *g, wimp_key *key,
+ bool is_toolbar)
+{
+ struct browser_window_features cont;
+ os_error *ro_error;
+ wimp_pointer pointer;
+ os_coord pos;
+ float scale;
+ uint32_t c = (uint32_t) key->c;
+ wimp_scroll_direction xscroll = wimp_SCROLL_NONE;
+ wimp_scroll_direction yscroll = wimp_SCROLL_NONE;
+ nsurl *url;
+
+ if (g == NULL)
+ return false;
+
+ ro_error = xwimp_get_pointer_info(&pointer);
+ if (ro_error) {
+ LOG("xwimp_get_pointer_info: 0x%x: %s\n", ro_error->errnum, ro_error->errmess);
+ ro_warn_user("WimpError", ro_error->errmess);
+ return false;
+ }
+
+ if (!ro_gui_window_to_window_pos(g, pointer.pos.x, pointer.pos.y, &pos))
+ return false;
+
+ browser_window_get_features(g->bw, pos.x, pos.y, &cont);
+
+ switch (c) {
+ case IS_WIMP_KEY + wimp_KEY_F1: /* Help. */
+ {
+ nserror error = nsurl_create(
+ "http://www.netsurf-browser.org/documentation/",
+ &url);
+ if (error == NSERROR_OK) {
+ error = browser_window_create(BW_CREATE_HISTORY,
+ url,
+ NULL,
+ NULL,
+ NULL);
+ nsurl_unref(url);
+ }
+ if (error != NSERROR_OK) {
+ ro_warn_user(messages_get_errorcode(error), 0);
+ }
+ return true;
+ }
+ case IS_WIMP_KEY + wimp_KEY_CONTROL + wimp_KEY_F1:
+ ro_gui_window_action_page_info(g);
+ return true;
+
+ case IS_WIMP_KEY + wimp_KEY_F2:
+ if (g->toolbar == NULL)
+ return false;
+ ro_gui_url_complete_close();
+ ro_toolbar_set_url(g->toolbar, "www.", true, true);
+ ro_gui_url_complete_start(g->toolbar);
+ ro_gui_url_complete_keypress(g->toolbar, wimp_KEY_DOWN);
+ return true;
+
+ case IS_WIMP_KEY + wimp_KEY_CONTROL + wimp_KEY_F2:
+ /* Close window. */
+ ro_gui_url_complete_close();
+ gui_window_set_pointer(g, GUI_POINTER_DEFAULT);
+ browser_window_destroy(g->bw);
+ return true;
+
+ case 19: /* Ctrl + S */
+ case IS_WIMP_KEY + wimp_KEY_F3:
+ ro_gui_window_action_save(g, GUI_SAVE_SOURCE);
+ return true;
+
+ case IS_WIMP_KEY + wimp_KEY_CONTROL + wimp_KEY_F3:
+ ro_gui_window_action_save(g, GUI_SAVE_TEXT);
+ return true;
+
+ case IS_WIMP_KEY + wimp_KEY_SHIFT + wimp_KEY_F3:
+ ro_gui_window_action_save(g, GUI_SAVE_COMPLETE);
+ return true;
+
+ case IS_WIMP_KEY + wimp_KEY_CONTROL + wimp_KEY_SHIFT + wimp_KEY_F3:
+ ro_gui_window_action_save(g, GUI_SAVE_DRAW);
+ return true;
+
+ case 6: /* Ctrl + F */
+ case IS_WIMP_KEY + wimp_KEY_F4: /* Search */
+ ro_gui_window_action_search(g);
+ return true;
+
+ case IS_WIMP_KEY + wimp_KEY_F5: /* Reload */
+ if (g->bw != NULL)
+ browser_window_reload(g->bw, false);
+ return true;
+
+ case 18: /* Ctrl+R (Full reload) */
+ case IS_WIMP_KEY + wimp_KEY_CONTROL + wimp_KEY_F5:
+ if (g->bw != NULL)
+ browser_window_reload(g->bw, true);
+ return true;
+
+ case IS_WIMP_KEY + wimp_KEY_F6: /* Hotlist */
+ ro_gui_hotlist_open();
+ return true;
+
+ case IS_WIMP_KEY + wimp_KEY_F7: /* Show local history */
+ ro_gui_window_action_local_history(g);
+ return true;
+
+ case IS_WIMP_KEY + wimp_KEY_CONTROL + wimp_KEY_F7:
+ /* Show global history */
+ ro_gui_global_history_open();
+ return true;
+
+ case IS_WIMP_KEY + wimp_KEY_F8: /* View source */
+ ro_gui_view_source((cont.main != NULL) ? cont.main :
+ browser_window_get_content(g->bw));
+ return true;
+
+ case IS_WIMP_KEY + wimp_KEY_F9:
+ /* Dump content for debugging. */
+ ro_gui_dump_browser_window(g->bw);
+ return true;
+
+ case IS_WIMP_KEY + wimp_KEY_CONTROL + wimp_KEY_F9:
+ urldb_dump();
+ return true;
+
+ case IS_WIMP_KEY + wimp_KEY_CONTROL + wimp_KEY_SHIFT + wimp_KEY_F9:
+ talloc_report_full(0, stderr);
+ return true;
+
+ case IS_WIMP_KEY + wimp_KEY_F11: /* Zoom */
+ ro_gui_window_action_zoom(g);
+ return true;
+
+ case IS_WIMP_KEY + wimp_KEY_SHIFT + wimp_KEY_F11:
+ /* Toggle display of box outlines. */
+ browser_window_debug(g->bw, CONTENT_DEBUG_REDRAW);
+
+ gui_window_redraw_window(g);
+ return true;
+
+ case wimp_KEY_RETURN:
+ if (is_toolbar) {
+ const char *toolbar_url;
+ toolbar_url = ro_toolbar_get_url(g->toolbar);
+ if (toolbar_url != NULL)
+ ro_gui_window_launch_url(g, toolbar_url);
+ }
+ return true;
+
+ case wimp_KEY_ESCAPE:
+ if (ro_gui_url_complete_close()) {
+ ro_gui_url_complete_start(g->toolbar);
+ return true;
+ }
+
+ if (g->bw != NULL)
+ browser_window_stop(g->bw);
+ return true;
+
+ case 14: /* CTRL+N */
+ ro_gui_window_action_new_window(g);
+ return true;
+
+ case 17: /* CTRL+Q (Zoom out) */
+ case 23: /* CTRL+W (Zoom in) */
+ if (browser_window_has_content(g->bw) == false)
+ break;
+ scale = g->scale;
+ if (ro_gui_shift_pressed() && c == 17)
+ scale = g->scale - 0.1;
+ else if (ro_gui_shift_pressed() && c == 23)
+ scale = g->scale + 0.1;
+ else if (c == 17) {
+ for (int i = SCALE_SNAP_TO_SIZE - 1; i >= 0; i--)
+ if (scale_snap_to[i] < g->scale) {
+ scale = scale_snap_to[i];
+ break;
+ }
+ } else {
+ for (unsigned int i = 0; i < SCALE_SNAP_TO_SIZE; i++)
+ if (scale_snap_to[i] > g->scale) {
+ scale = scale_snap_to[i];
+ break;
+ }
+ }
+ if (scale < scale_snap_to[0])
+ scale = scale_snap_to[0];
+ if (scale > scale_snap_to[SCALE_SNAP_TO_SIZE - 1])
+ scale = scale_snap_to[SCALE_SNAP_TO_SIZE - 1];
+ if (g->scale != scale) {
+ ro_gui_window_set_scale(g, scale);
+ }
+ return true;
+
+ case IS_WIMP_KEY + wimp_KEY_PRINT:
+ ro_gui_window_action_print(g);
+ return true;
+
+ case IS_WIMP_KEY | wimp_KEY_LEFT:
+ case IS_WIMP_KEY | wimp_KEY_RIGHT:
+ case IS_WIMP_KEY | wimp_KEY_CONTROL | wimp_KEY_LEFT:
+ case IS_WIMP_KEY | wimp_KEY_CONTROL | wimp_KEY_RIGHT:
+ case IS_WIMP_KEY | wimp_KEY_UP:
+ case IS_WIMP_KEY | wimp_KEY_DOWN:
+ case IS_WIMP_KEY | wimp_KEY_PAGE_UP:
+ case IS_WIMP_KEY | wimp_KEY_PAGE_DOWN:
+ case wimp_KEY_HOME:
+ case IS_WIMP_KEY | wimp_KEY_CONTROL | wimp_KEY_UP:
+ case IS_WIMP_KEY | wimp_KEY_END:
+ case IS_WIMP_KEY | wimp_KEY_CONTROL | wimp_KEY_DOWN:
+ if (is_toolbar)
+ return false;
+ break;
+ default:
+ return false; /* This catches any keys we don't want to claim */
+ }
+
+ /* Any keys that exit from the above switch() via break should be
+ * processed as scroll actions in the browser window. */
+
+ switch (c) {
+ case IS_WIMP_KEY | wimp_KEY_LEFT:
+ xscroll = wimp_SCROLL_COLUMN_LEFT;
+ break;
+ case IS_WIMP_KEY | wimp_KEY_RIGHT:
+ xscroll = wimp_SCROLL_COLUMN_RIGHT;
+ break;
+ case IS_WIMP_KEY | wimp_KEY_CONTROL | wimp_KEY_LEFT:
+ xscroll = 0x7fffffff;
+ break;
+ case IS_WIMP_KEY | wimp_KEY_CONTROL | wimp_KEY_RIGHT:
+ xscroll = 0x80000000;
+ break;
+ case IS_WIMP_KEY | wimp_KEY_UP:
+ yscroll = wimp_SCROLL_LINE_UP;
+ break;
+ case IS_WIMP_KEY | wimp_KEY_DOWN:
+ yscroll = wimp_SCROLL_LINE_DOWN;
+ break;
+ case IS_WIMP_KEY | wimp_KEY_PAGE_UP:
+ yscroll = wimp_SCROLL_PAGE_UP;
+ break;
+ case IS_WIMP_KEY | wimp_KEY_PAGE_DOWN:
+ yscroll = wimp_SCROLL_PAGE_DOWN;
+ break;
+ case wimp_KEY_HOME:
+ case IS_WIMP_KEY | wimp_KEY_CONTROL | wimp_KEY_UP:
+ yscroll = 0x7fffffff;
+ break;
+ case IS_WIMP_KEY | wimp_KEY_END:
+ case IS_WIMP_KEY | wimp_KEY_CONTROL | wimp_KEY_DOWN:
+ yscroll = 0x80000000;
+ break;
+ }
+
+ ro_gui_window_scroll_action(g, xscroll, yscroll);
+
+ return true;
+}
+
+
+/**
+ * Prepare the browser window menu for (re-)opening
+ *
+ * \param w The window owning the menu.
+ * \param i The icon owning the menu.
+ * \param *menu The menu about to be opened.
+ * \param *pointer Pointer to the relevant wimp event block, or
+ * NULL for an Adjust click.
+ * \return true if the event was handled; else false.
+ */
+
+bool ro_gui_window_menu_prepare(wimp_w w, wimp_i i, wimp_menu *menu,
+ wimp_pointer *pointer)
+{
+ struct gui_window *g;
+ struct browser_window *bw;
+ struct toolbar *toolbar;
+ struct browser_window_features cont;
+ bool export_sprite, export_draw, have_content;
+ os_coord pos;
+ browser_editor_flags editor_flags;
+
+ g = (struct gui_window *) ro_gui_wimp_event_get_user_data(w);
+ toolbar = g->toolbar;
+ bw = g->bw;
+ have_content = browser_window_has_content(g->bw);
+ editor_flags = browser_window_get_editor_flags(bw);
+
+ /* If this is the form select menu, handle it now and then exit.
+ * Otherwise, carry on to the main browser window menu.
+ */
+
+ if (menu == gui_form_select_menu) {
+ return ro_gui_window_prepare_form_select_menu(g,
+ gui_form_select_control);
+ }
+
+ if (menu != ro_gui_browser_window_menu)
+ return false;
+
+ /* If this is a new opening for the browser window menu (ie. not for a
+ * toolbar menu), get details of the object under the pointer.
+ */
+
+ if (pointer != NULL && g->window == w) {
+ ro_gui_url_complete_close();
+
+ current_menu_main = NULL;
+ current_menu_object = NULL;
+ current_menu_url = NULL;
+
+ if (ro_gui_window_to_window_pos(g, pointer->pos.x,
+ pointer->pos.y, &pos)) {
+ browser_window_get_features(bw, pos.x, pos.y, &cont);
+
+ current_menu_main = cont.main;
+ current_menu_object = cont.object;
+ current_menu_url = cont.link;
+ }
+ }
+
+ /* Shade menu entries according to the state of the window and object
+ * under the pointer.
+ */
+
+ /* Toolbar (Sub)Menu */
+
+ ro_gui_menu_set_entry_shaded(menu, TOOLBAR_BUTTONS,
+ ro_toolbar_menu_option_shade(toolbar));
+ ro_gui_menu_set_entry_ticked(menu, TOOLBAR_BUTTONS,
+ ro_toolbar_menu_buttons_tick(toolbar));
+
+ ro_gui_menu_set_entry_shaded(menu, TOOLBAR_ADDRESS_BAR,
+ ro_toolbar_menu_edit_shade(toolbar));
+ ro_gui_menu_set_entry_ticked(menu, TOOLBAR_ADDRESS_BAR,
+ ro_toolbar_menu_url_tick(toolbar));
+
+ ro_gui_menu_set_entry_shaded(menu, TOOLBAR_THROBBER,
+ ro_toolbar_menu_edit_shade(toolbar));
+ ro_gui_menu_set_entry_ticked(menu, TOOLBAR_THROBBER,
+ ro_toolbar_menu_throbber_tick(toolbar));
+
+ ro_gui_menu_set_entry_shaded(menu, TOOLBAR_EDIT,
+ ro_toolbar_menu_edit_shade(toolbar));
+ ro_gui_menu_set_entry_ticked(menu, TOOLBAR_EDIT,
+ ro_toolbar_menu_edit_tick(toolbar));
+
+ /* Page Submenu */
+
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_PAGE,
+ !browser_window_can_search(bw));
+
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_PAGE_INFO, !have_content);
+
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_PRINT, !have_content);
+
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_NEW_WINDOW, !have_content);
+
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_FIND_TEXT,
+ !browser_window_can_search(bw));
+
+
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_VIEW_SOURCE, !have_content);
+
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_SAVE_URL_URI, !have_content);
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_SAVE_URL_URL, !have_content);
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_SAVE_URL_TEXT,
+ !have_content);
+
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_SAVE, !have_content);
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_SAVE_COMPLETE,
+ !have_content);
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_EXPORT_DRAW, !have_content);
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_EXPORT_PDF, !have_content);
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_EXPORT_TEXT, !have_content);
+
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_LINK_SAVE_URI,
+ !current_menu_url);
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_LINK_SAVE_URL,
+ !current_menu_url);
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_LINK_SAVE_TEXT,
+ !current_menu_url);
+
+
+
+ /* Object Submenu */
+
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_OBJECT,
+ current_menu_object == NULL &&
+ current_menu_url == NULL);
+
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_OBJECT_LINK,
+ current_menu_url == NULL);
+
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_OBJECT_INFO,
+ current_menu_object == NULL);
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_OBJECT_RELOAD,
+ current_menu_object == NULL);
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_OBJECT_OBJECT,
+ current_menu_object == NULL);
+
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_OBJECT_PRINT, true);
+ /* Not yet implemented */
+
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_OBJECT_SAVE,
+ current_menu_object == NULL);
+
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_OBJECT_SAVE_URL_URI,
+ current_menu_object == NULL);
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_OBJECT_SAVE_URL_URL,
+ current_menu_object == NULL);
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_OBJECT_SAVE_URL_TEXT,
+ current_menu_object == NULL);
+
+ if (current_menu_object != NULL)
+ ro_gui_window_content_export_types(current_menu_object,
+ &export_draw, &export_sprite);
+ else
+ ro_gui_window_content_export_types(
+ browser_window_get_content(bw),
+ &export_draw, &export_sprite);
+
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_OBJECT_EXPORT,
+ (!have_content && current_menu_object == NULL)
+ || !(export_sprite || export_draw));
+
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_OBJECT_EXPORT_SPRITE,
+ (!have_content && current_menu_object == NULL)
+ || !export_sprite);
+
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_OBJECT_EXPORT_DRAW,
+ (!have_content && current_menu_object == NULL)
+ || !export_draw);
+
+
+ /* Selection Submenu */
+
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_SELECTION,
+ !browser_window_can_select(bw));
+
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_SELECTION_SAVE,
+ ~editor_flags & BW_EDITOR_CAN_COPY);
+
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_SELECTION_COPY,
+ ~editor_flags & BW_EDITOR_CAN_COPY);
+
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_SELECTION_CUT,
+ ~editor_flags & BW_EDITOR_CAN_CUT);
+
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_SELECTION_PASTE,
+ ~editor_flags & BW_EDITOR_CAN_PASTE);
+
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_SELECTION_CLEAR,
+ ~editor_flags & BW_EDITOR_CAN_COPY);
+
+
+ /* Navigate Submenu */
+
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_NAVIGATE_BACK,
+ !browser_window_back_available(bw));
+
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_NAVIGATE_FORWARD,
+ !browser_window_forward_available(bw));
+
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_NAVIGATE_RELOAD_ALL,
+ !browser_window_reload_available(bw));
+
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_NAVIGATE_STOP,
+ !browser_window_stop_available(bw));
+
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_NAVIGATE_UP,
+ !browser_window_up_available(bw));
+
+
+
+ /* View Submenu */
+
+ ro_gui_menu_set_entry_ticked(menu, BROWSER_IMAGES_FOREGROUND,
+ g != NULL && nsoption_bool(foreground_images));
+
+ ro_gui_menu_set_entry_ticked(menu, BROWSER_IMAGES_BACKGROUND,
+ g != NULL && nsoption_bool(background_images));
+
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_BUFFER_ANIMS,
+ g == NULL || g->option.buffer_everything);
+ ro_gui_menu_set_entry_ticked(menu, BROWSER_BUFFER_ANIMS, g != NULL &&
+ (g->option.buffer_animations ||
+ g->option.buffer_everything));
+
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_BUFFER_ALL, g == NULL);
+ ro_gui_menu_set_entry_ticked(menu, BROWSER_BUFFER_ALL,
+ g != NULL && g->option.buffer_everything);
+
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_SCALE_VIEW, !have_content);
+
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_WINDOW_STAGGER,
+ nsoption_int(window_screen_width) == 0);
+ ro_gui_menu_set_entry_ticked(menu, BROWSER_WINDOW_STAGGER,
+ ((nsoption_int(window_screen_width) == 0) ||
+ nsoption_bool(window_stagger)));
+
+ ro_gui_menu_set_entry_ticked(menu, BROWSER_WINDOW_COPY,
+ nsoption_bool(window_size_clone));
+
+ ro_gui_menu_set_entry_shaded(menu, BROWSER_WINDOW_RESET,
+ nsoption_int(window_screen_width) == 0);
+
+
+ /* Utilities Submenu */
+
+ ro_gui_menu_set_entry_shaded(menu, HOTLIST_ADD_URL, !have_content);
+
+ ro_gui_menu_set_entry_shaded(menu, HISTORY_SHOW_LOCAL,
+ (bw == NULL ||
+ !(have_content || browser_window_back_available(bw) ||
+ browser_window_forward_available(bw))));
+
+
+ /* Help Submenu */
+
+ ro_gui_menu_set_entry_ticked(menu, HELP_LAUNCH_INTERACTIVE,
+ ro_gui_interactive_help_available() &&
+ nsoption_bool(interactive_help));
+
+ return true;
+}
+
+
+/**
+ * Handle submenu warnings for a browser window menu
+ *
+ * \param w The window owning the menu.
+ * \param i The icon owning the menu.
+ * \param *menu The menu to which the warning applies.
+ * \param *selection The wimp menu selection data.
+ * \param action The selected menu action.
+ */
+
+void ro_gui_window_menu_warning(wimp_w w, wimp_i i, wimp_menu *menu,
+ wimp_selection *selection, menu_action action)
+{
+ struct gui_window *g;
+ hlcache_handle *h;
+ struct toolbar *toolbar;
+ bool export;
+
+ if (menu != ro_gui_browser_window_menu)
+ return;
+
+ g = (struct gui_window *) ro_gui_wimp_event_get_user_data(w);
+ toolbar = g->toolbar;
+ h = browser_window_get_content(g->bw);
+
+ switch (action) {
+ case BROWSER_PAGE_INFO:
+ if (h != NULL)
+ ro_gui_window_prepare_pageinfo(g);
+ break;
+
+ case BROWSER_FIND_TEXT:
+ if (h != NULL && (content_get_type(h) == CONTENT_HTML ||
+ content_get_type(h) == CONTENT_TEXTPLAIN))
+ ro_gui_search_prepare(g->bw);
+ break;
+
+ case BROWSER_SCALE_VIEW:
+ if (h != NULL)
+ ro_gui_dialog_prepare_zoom(g);
+ break;
+
+ case BROWSER_PRINT:
+ if (h != NULL)
+ ro_gui_print_prepare(g);
+ break;
+
+ case BROWSER_OBJECT_INFO:
+ if (current_menu_object != NULL)
+ ro_gui_window_prepare_objectinfo(current_menu_object,
+ current_menu_url);
+ break;
+
+ case BROWSER_OBJECT_SAVE:
+ if (current_menu_object != NULL)
+ ro_gui_save_prepare(GUI_SAVE_OBJECT_ORIG,
+ current_menu_object, NULL, NULL, NULL);
+ break;
+
+ case BROWSER_SELECTION_SAVE:
+ if (browser_window_get_editor_flags(g->bw) & BW_EDITOR_CAN_COPY)
+ ro_gui_save_prepare(GUI_SAVE_TEXT_SELECTION, NULL,
+ browser_window_get_selection(g->bw),
+ NULL, NULL);
+ break;
+
+ case BROWSER_SAVE_URL_URI:
+ if (h != NULL)
+ ro_gui_save_prepare(GUI_SAVE_LINK_URI, NULL, NULL,
+ hlcache_handle_get_url(h),
+ content_get_title(h));
+ break;
+
+ case BROWSER_SAVE_URL_URL:
+ if (h != NULL)
+ ro_gui_save_prepare(GUI_SAVE_LINK_URL, NULL, NULL,
+ hlcache_handle_get_url(h),
+ content_get_title(h));
+ break;
+
+ case BROWSER_SAVE_URL_TEXT:
+ if (h != NULL)
+ ro_gui_save_prepare(GUI_SAVE_LINK_TEXT, NULL, NULL,
+ hlcache_handle_get_url(h),
+ content_get_title(h));
+ break;
+
+ case BROWSER_OBJECT_SAVE_URL_URI:
+ if (current_menu_object != NULL)
+ ro_gui_save_prepare(GUI_SAVE_LINK_URI, NULL, NULL,
+ hlcache_handle_get_url(
+ current_menu_object),
+ content_get_title(current_menu_object));
+ break;
+
+ case BROWSER_OBJECT_SAVE_URL_URL:
+ if (current_menu_object != NULL)
+ ro_gui_save_prepare(GUI_SAVE_LINK_URL, NULL, NULL,
+ hlcache_handle_get_url(
+ current_menu_object),
+ content_get_title(current_menu_object));
+ break;
+
+ case BROWSER_OBJECT_SAVE_URL_TEXT:
+ if (current_menu_object != NULL)
+ ro_gui_save_prepare(GUI_SAVE_LINK_TEXT, NULL, NULL,
+ hlcache_handle_get_url(
+ current_menu_object),
+ content_get_title(current_menu_object));
+ break;
+
+ case BROWSER_SAVE:
+ if (h != NULL)
+ ro_gui_save_prepare(GUI_SAVE_SOURCE, h, NULL, NULL, NULL);
+ break;
+
+ case BROWSER_SAVE_COMPLETE:
+ if (h != NULL)
+ ro_gui_save_prepare(GUI_SAVE_COMPLETE, h, NULL, NULL, NULL);
+ break;
+
+ case BROWSER_EXPORT_DRAW:
+ if (h != NULL)
+ ro_gui_save_prepare(GUI_SAVE_DRAW, h, NULL, NULL, NULL);
+ break;
+
+ case BROWSER_EXPORT_PDF:
+ if (h != NULL)
+ ro_gui_save_prepare(GUI_SAVE_PDF, h, NULL, NULL, NULL);
+ break;
+
+ case BROWSER_EXPORT_TEXT:
+ if (h != NULL)
+ ro_gui_save_prepare(GUI_SAVE_TEXT, h, NULL, NULL, NULL);
+ break;
+
+ case BROWSER_LINK_SAVE_URI:
+ if (current_menu_url != NULL)
+ ro_gui_save_prepare(GUI_SAVE_LINK_URI, NULL, NULL,
+ current_menu_url, NULL);
+ break;
+
+ case BROWSER_LINK_SAVE_URL:
+ if (current_menu_url != NULL)
+ ro_gui_save_prepare(GUI_SAVE_LINK_URL, NULL, NULL,
+ current_menu_url, NULL);
+ break;
+
+ case BROWSER_LINK_SAVE_TEXT:
+ if (current_menu_url != NULL)
+ ro_gui_save_prepare(GUI_SAVE_LINK_TEXT, NULL, NULL,
+ current_menu_url, NULL);
+ break;
+
+ case BROWSER_OBJECT_EXPORT_SPRITE:
+ if (current_menu_object != NULL) {
+ ro_gui_window_content_export_types(current_menu_object,
+ NULL, &export);
+
+ if (export)
+ ro_gui_save_prepare(GUI_SAVE_OBJECT_NATIVE,
+ current_menu_object,
+ NULL, NULL, NULL);
+ } else if (h != NULL) {
+ ro_gui_window_content_export_types(h, NULL, &export);
+
+ if (export)
+ ro_gui_save_prepare(GUI_SAVE_OBJECT_NATIVE,
+ h, NULL, NULL, NULL);
+ }
+ break;
+
+ case BROWSER_OBJECT_EXPORT_DRAW:
+ if (current_menu_object != NULL) {
+ ro_gui_window_content_export_types(current_menu_object,
+ &export, NULL);
+
+ if (export)
+ ro_gui_save_prepare(GUI_SAVE_OBJECT_NATIVE,
+ current_menu_object,
+ NULL, NULL, NULL);
+ } else if (h != NULL) {
+ ro_gui_window_content_export_types(h, &export, NULL);
+
+ if (export)
+ ro_gui_save_prepare(GUI_SAVE_OBJECT_NATIVE,
+ h, NULL, NULL, NULL);
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+static void ro_gui_window_paste_cb(void *pw)
+{
+ struct browser_window *bw = pw;
+
+ browser_window_key_press(bw, NS_KEY_PASTE);
+}
+
+
+/**
+ * Handle selections from a browser window menu
+ *
+ * \param w The window owning the menu.
+ * \param i The icon owning the menu.
+ * \param *menu The menu from which the selection was made.
+ * \param *selection The wimp menu selection data.
+ * \param action The selected menu action.
+ * \return true if action accepted; else false.
+ */
+
+bool ro_gui_window_menu_select(wimp_w w, wimp_i i, wimp_menu *menu,
+ wimp_selection *selection, menu_action action)
+{
+ struct gui_window *g;
+ struct browser_window *bw;
+ hlcache_handle *h;
+ struct toolbar *toolbar;
+ wimp_window_state state;
+ nsurl *url;
+ nserror error = NSERROR_OK;
+
+ g = (struct gui_window *) ro_gui_wimp_event_get_user_data(w);
+ toolbar = g->toolbar;
+ bw = g->bw;
+ h = browser_window_get_content(bw);
+
+ /* If this is a form menu from the core, handle it now and then exit.
+ * Otherwise, carry on to the main browser window menu.
+ */
+
+ if (menu == gui_form_select_menu && w == g->window) {
+ ro_gui_window_process_form_select_menu(g, selection);
+
+ return true;
+ }
+
+ /* We're now safe to assume that this is either the browser or
+ * toolbar window menu.
+ */
+
+ switch (action) {
+
+ /* help actions */
+ case HELP_OPEN_CONTENTS:
+ error = nsurl_create("http://www.netsurf-browser.org/documentation/", &url);
+ if (error == NSERROR_OK) {
+ error = browser_window_create(BW_CREATE_HISTORY,
+ url,
+ NULL,
+ NULL,
+ NULL);
+ nsurl_unref(url);
+ }
+ break;
+
+ case HELP_OPEN_GUIDE:
+ error = nsurl_create("http://www.netsurf-browser.org/documentation/guide", &url);
+ if (error == NSERROR_OK) {
+ error = browser_window_create(BW_CREATE_HISTORY,
+ url,
+ NULL,
+ NULL,
+ NULL);
+ nsurl_unref(url);
+ }
+ break;
+
+ case HELP_OPEN_INFORMATION:
+ error = nsurl_create("http://www.netsurf-browser.org/documentation/info", &url);
+ if (error == NSERROR_OK) {
+ error = browser_window_create(BW_CREATE_HISTORY,
+ url,
+ NULL,
+ NULL,
+ NULL);
+ nsurl_unref(url);
+ }
+ break;
+
+ case HELP_OPEN_CREDITS:
+ error = nsurl_create("about:credits", &url);
+ if (error == NSERROR_OK) {
+ error = browser_window_create(BW_CREATE_HISTORY,
+ url,
+ NULL,
+ NULL,
+ NULL);
+ nsurl_unref(url);
+ }
+ break;
+
+ case HELP_OPEN_LICENCE:
+ error = nsurl_create("about:licence", &url);
+ if (error == NSERROR_OK) {
+ error = browser_window_create(BW_CREATE_HISTORY,
+ url,
+ NULL,
+ NULL,
+ NULL);
+ nsurl_unref(url);
+ }
+ break;
+
+ case HELP_LAUNCH_INTERACTIVE:
+ if (!ro_gui_interactive_help_available()) {
+ ro_gui_interactive_help_start();
+ nsoption_set_bool(interactive_help, true);
+ } else {
+ nsoption_set_bool(interactive_help, !nsoption_bool(interactive_help));
+ }
+ break;
+
+ /* history actions */
+ case HISTORY_SHOW_LOCAL:
+ ro_gui_window_action_local_history(g);
+ break;
+ case HISTORY_SHOW_GLOBAL:
+ ro_gui_global_history_open();
+ break;
+
+ /* hotlist actions */
+ case HOTLIST_ADD_URL:
+ ro_gui_window_action_add_bookmark(g);
+ break;
+ case HOTLIST_SHOW:
+ ro_gui_hotlist_open();
+ break;
+
+ /* cookies actions */
+ case COOKIES_SHOW:
+ ro_gui_cookies_open();
+ break;
+
+ case COOKIES_DELETE:
+ cookie_manager_keypress(NS_KEY_SELECT_ALL);
+ cookie_manager_keypress(NS_KEY_DELETE_LEFT);
+ break;
+
+ /* page actions */
+ case BROWSER_PAGE_INFO:
+ ro_gui_window_action_page_info(g);
+ break;
+ case BROWSER_PRINT:
+ ro_gui_window_action_print(g);
+ break;
+ case BROWSER_NEW_WINDOW:
+ ro_gui_window_action_new_window(g);
+ break;
+ case BROWSER_VIEW_SOURCE:
+ if (current_menu_main != NULL) {
+ ro_gui_view_source(current_menu_main);
+ } else if (h != NULL) {
+ ro_gui_view_source(h);
+ }
+ break;
+
+ /* object actions */
+ case BROWSER_OBJECT_INFO:
+ if (current_menu_object != NULL) {
+ ro_gui_window_prepare_objectinfo(current_menu_object,
+ current_menu_url);
+ ro_gui_dialog_open_persistent(g->window,
+ dialog_objinfo, false);
+ }
+ break;
+ case BROWSER_OBJECT_RELOAD:
+ if (current_menu_object != NULL) {
+ content_invalidate_reuse_data(current_menu_object);
+ browser_window_reload(bw, false);
+ }
+ break;
+
+ /* link actions */
+ case BROWSER_LINK_SAVE_URI:
+ if (current_menu_url != NULL) {
+ ro_gui_save_prepare(GUI_SAVE_LINK_URI, NULL, NULL,
+ current_menu_url, NULL);
+ ro_gui_dialog_open_persistent(g->window, dialog_saveas,
+ false);
+ }
+ break;
+ case BROWSER_LINK_SAVE_URL:
+ if (current_menu_url != NULL) {
+ ro_gui_save_prepare(GUI_SAVE_LINK_URL, NULL, NULL,
+ current_menu_url, NULL);
+ ro_gui_dialog_open_persistent(g->window, dialog_saveas,
+ false);
+ }
+ break;
+ case BROWSER_LINK_SAVE_TEXT:
+ if (current_menu_url != NULL) {
+ ro_gui_save_prepare(GUI_SAVE_LINK_TEXT, NULL, NULL,
+ current_menu_url, NULL);
+ ro_gui_dialog_open_persistent(g->window, dialog_saveas,
+ false);
+ }
+ break;
+
+ case BROWSER_LINK_DOWNLOAD:
+ if (current_menu_url != NULL) {
+ error = browser_window_navigate(bw,
+ current_menu_url,
+ browser_window_get_url(bw),
+ BW_NAVIGATE_DOWNLOAD,
+ NULL,
+ NULL,
+ NULL);
+ }
+ break;
+
+ case BROWSER_LINK_NEW_WINDOW:
+ if (current_menu_url != NULL) {
+ error = browser_window_create(
+ BW_CREATE_HISTORY |
+ BW_CREATE_CLONE,
+ current_menu_url,
+ browser_window_get_url(bw),
+ bw,
+ NULL);
+ }
+ break;
+
+
+ /* save actions */
+ case BROWSER_OBJECT_SAVE:
+ if (current_menu_object != NULL) {
+ ro_gui_save_prepare(GUI_SAVE_OBJECT_ORIG,
+ current_menu_object, NULL, NULL, NULL);
+ ro_gui_dialog_open_persistent(g->window, dialog_saveas,
+ false);
+ }
+ break;
+ case BROWSER_OBJECT_EXPORT_SPRITE:
+ if (current_menu_object != NULL) {
+ ro_gui_save_prepare(GUI_SAVE_OBJECT_NATIVE,
+ current_menu_object, NULL, NULL, NULL);
+ ro_gui_dialog_open_persistent(g->window, dialog_saveas,
+ false);
+ }
+ break;
+ case BROWSER_OBJECT_EXPORT_DRAW:
+ if (current_menu_object != NULL) {
+ ro_gui_save_prepare(GUI_SAVE_OBJECT_NATIVE,
+ current_menu_object, NULL, NULL, NULL);
+ ro_gui_dialog_open_persistent(g->window, dialog_saveas,
+ false);
+ }
+ break;
+ case BROWSER_SAVE:
+ ro_gui_window_action_save(g, GUI_SAVE_SOURCE);
+ break;
+ case BROWSER_SAVE_COMPLETE:
+ ro_gui_window_action_save(g, GUI_SAVE_COMPLETE);
+ break;
+ case BROWSER_EXPORT_DRAW:
+ ro_gui_window_action_save(g, GUI_SAVE_DRAW);
+ break;
+ case BROWSER_EXPORT_PDF:
+ ro_gui_window_action_save(g, GUI_SAVE_PDF);
+ break;
+ case BROWSER_EXPORT_TEXT:
+ ro_gui_window_action_save(g, GUI_SAVE_TEXT);
+ break;
+ case BROWSER_SAVE_URL_URI:
+ ro_gui_window_action_save(g, GUI_SAVE_LINK_URI);
+ break;
+ case BROWSER_SAVE_URL_URL:
+ ro_gui_window_action_save(g, GUI_SAVE_LINK_URL);
+ break;
+ case BROWSER_SAVE_URL_TEXT:
+ ro_gui_window_action_save(g, GUI_SAVE_LINK_TEXT);
+ break;
+
+ /* selection actions */
+ case BROWSER_SELECTION_SAVE:
+ if (h != NULL) {
+ ro_gui_save_prepare(GUI_SAVE_TEXT_SELECTION, NULL,
+ browser_window_get_selection(bw),
+ NULL, NULL);
+ ro_gui_dialog_open_persistent(g->window, dialog_saveas,
+ false);
+ }
+ break;
+ case BROWSER_SELECTION_COPY:
+ browser_window_key_press(bw, NS_KEY_COPY_SELECTION);
+ break;
+ case BROWSER_SELECTION_CUT:
+ browser_window_key_press(bw, NS_KEY_CUT_SELECTION);
+ break;
+ case BROWSER_SELECTION_PASTE:
+ ro_gui_selection_prepare_paste(w, ro_gui_window_paste_cb, bw);
+ break;
+ case BROWSER_SELECTION_ALL:
+ browser_window_key_press(bw, NS_KEY_SELECT_ALL);
+ break;
+ case BROWSER_SELECTION_CLEAR:
+ browser_window_key_press(bw, NS_KEY_CLEAR_SELECTION);
+ break;
+
+ /* navigation actions */
+ case BROWSER_NAVIGATE_HOME:
+ ro_gui_window_action_home(g);
+ break;
+ case BROWSER_NAVIGATE_BACK:
+ if (bw != NULL)
+ browser_window_history_back(bw, false);
+ break;
+ case BROWSER_NAVIGATE_FORWARD:
+ if (bw != NULL)
+ browser_window_history_forward(bw, false);
+ break;
+ case BROWSER_NAVIGATE_UP:
+ if (bw != NULL && h != NULL)
+ browser_window_navigate_up(g->bw, false);
+ break;
+ case BROWSER_NAVIGATE_RELOAD_ALL:
+ if (bw != NULL)
+ browser_window_reload(bw, true);
+ break;
+ case BROWSER_NAVIGATE_STOP:
+ if (bw != NULL)
+ browser_window_stop(bw);
+ break;
+
+ /* browser window/display actions */
+ case BROWSER_SCALE_VIEW:
+ ro_gui_window_action_zoom(g);
+ break;
+ case BROWSER_FIND_TEXT:
+ ro_gui_window_action_search(g);
+ break;
+ case BROWSER_IMAGES_FOREGROUND:
+ if (g != NULL)
+ nsoption_set_bool(foreground_images,
+ !nsoption_bool(foreground_images));
+ break;
+ case BROWSER_IMAGES_BACKGROUND:
+ if (g != NULL)
+ nsoption_set_bool(background_images,
+ !nsoption_bool(background_images));
+ break;
+ case BROWSER_BUFFER_ANIMS:
+ if (g != NULL)
+ g->option.buffer_animations =
+ !g->option.buffer_animations;
+ break;
+ case BROWSER_BUFFER_ALL:
+ if (g != NULL)
+ g->option.buffer_everything =
+ !g->option.buffer_everything;
+ break;
+ case BROWSER_SAVE_VIEW:
+ if (bw != NULL) {
+ ro_gui_window_default_options(g);
+ ro_gui_save_options();
+ }
+ break;
+ case BROWSER_WINDOW_DEFAULT:
+ if (g != NULL) {
+ os_error *oserror;
+
+ ro_gui_screen_size(&nsoption_int(window_screen_width),
+ &nsoption_int(window_screen_height));
+ state.w = w;
+ oserror = xwimp_get_window_state(&state);
+ if (oserror) {
+ LOG("xwimp_get_window_state: 0x%x: %s", oserror->errnum, oserror->errmess);
+ ro_warn_user("WimpError", oserror->errmess);
+ }
+ nsoption_set_int(window_x, state.visible.x0);
+ nsoption_set_int(window_y, state.visible.y0);
+ nsoption_set_int(window_width,
+ state.visible.x1 - state.visible.x0);
+ nsoption_set_int(window_height,
+ state.visible.y1 - state.visible.y0);
+ ro_gui_save_options();
+ }
+ break;
+ case BROWSER_WINDOW_STAGGER:
+ nsoption_set_bool(window_stagger,
+ !nsoption_bool(window_stagger));
+ ro_gui_save_options();
+ break;
+ case BROWSER_WINDOW_COPY:
+ nsoption_set_bool(window_size_clone,
+ !nsoption_bool(window_size_clone));
+ ro_gui_save_options();
+ break;
+ case BROWSER_WINDOW_RESET:
+ nsoption_set_int(window_screen_width, 0);
+ nsoption_set_int(window_screen_height, 0);
+ ro_gui_save_options();
+ break;
+
+ /* toolbar actions */
+ case TOOLBAR_BUTTONS:
+ assert(toolbar);
+ ro_toolbar_set_display_buttons(toolbar,
+ !ro_toolbar_get_display_buttons(toolbar));
+ break;
+ case TOOLBAR_ADDRESS_BAR:
+ assert(toolbar);
+ ro_toolbar_set_display_url(toolbar,
+ !ro_toolbar_get_display_url(toolbar));
+ if (ro_toolbar_get_display_url(toolbar))
+ ro_toolbar_take_caret(toolbar);
+ break;
+ case TOOLBAR_THROBBER:
+ assert(toolbar);
+ ro_toolbar_set_display_throbber(toolbar,
+ !ro_toolbar_get_display_throbber(toolbar));
+ break;
+ case TOOLBAR_EDIT:
+ assert(toolbar);
+ ro_toolbar_toggle_edit(toolbar);
+ break;
+
+ default:
+ return false;
+ }
+
+ if (error != NSERROR_OK) {
+ ro_warn_user(messages_get_errorcode(error), 0);
+ }
+
+ return true;
+}
+
+
+/**
+ * Handle the closure of a browser window menu
+ *
+ * \param w The window owning the menu.
+ * \param i The icon owning the menu.
+ * \param *menu The menu that is being closed.
+ */
+
+void ro_gui_window_menu_close(wimp_w w, wimp_i i, wimp_menu *menu)
+{
+ if (menu == ro_gui_browser_window_menu) {
+ current_menu_object = NULL;
+ current_menu_url = NULL;
+ } else if (menu == gui_form_select_menu) {
+ gui_form_select_control = NULL;
+ }
+}
+
+
+/**
+ * Process Scroll_Request events in a browser window.
+ *
+ * \param *scroll The wimp scroll event data block.
+ */
+
+void ro_gui_window_scroll(wimp_scroll *scroll)
+{
+ struct gui_window *g = ro_gui_window_lookup(scroll->w);
+
+ if (g && browser_window_has_content(g->bw) && ro_gui_shift_pressed()) {
+ /* extended scroll request with shift held down; change zoom */
+ float scale, inc;
+
+ if (scroll->ymin & 3)
+ inc = 0.02; /* RO5 sends the msg 5 times;
+ * don't ask me why
+ *
+ * @todo this is liable to break if
+ * HID is configured optimally for
+ * frame scrolling. *5 appears to be
+ * an artifact of non-HID mode scrolling.
+ */
+ else
+ inc = (1 << (ABS(scroll->ymin)>>2)) / 20.0F;
+
+ if (scroll->ymin > 0) {
+ scale = g->scale + inc;
+ if (scale > scale_snap_to[SCALE_SNAP_TO_SIZE - 1])
+ scale = scale_snap_to[SCALE_SNAP_TO_SIZE - 1];
+ } else {
+ scale = g->scale - inc;
+ if (scale < scale_snap_to[0])
+ scale = scale_snap_to[0];
+ }
+ if (g->scale != scale)
+ ro_gui_window_set_scale(g, scale);
+ } else if (g != NULL) {
+ ro_gui_window_scroll_action(g, scroll->xmin, scroll->ymin);
+ }
+}
+
+/**
+ * Process Pointer Entering Window events in a browser window.
+ *
+ * \param *entering The wimp pointer entering event data block.
+ */
+
+static void ro_gui_window_pointer_entering(wimp_entering *entering)
+{
+ struct gui_window *g = ro_gui_window_lookup(entering->w);
+
+ if (g != NULL)
+ ro_mouse_track_start(ro_gui_window_track_end,
+ ro_gui_window_mouse_at, g);
+}
+
+/**
+ * Process Pointer Leaving Window events in a browser window. These arrive via
+ * the termination callback handler from ro_mouse's mouse tracking.
+ *
+ * \param *leaving The wimp pointer leaving event data block.
+ * \param *data The GUI window that the pointer is leaving.
+ */
+
+static void ro_gui_window_track_end(wimp_leaving *leaving, void *data)
+{
+ struct gui_window *g = (struct gui_window *) data;
+
+ if (g != NULL)
+ gui_window_set_pointer(g, GUI_POINTER_DEFAULT);
+}
+
+
+/**
+ * Scroll a browser window, either via the core or directly using the
+ * normal Wimp_OpenWindow interface.
+ *
+ * Scroll steps are supplied in terms of the (extended) Scroll Event direction
+ * values returned by Wimp_Poll. Special values of 0x7fffffff and 0x80000000
+ * are added to mean "Home" and "End".
+ *
+ * \param *g The GUI Window to be scrolled.
+ * \param scroll_x The X scroll step to be applied.
+ * \param scroll_y The Y scroll step to be applied.
+ */
+
+void ro_gui_window_scroll_action(struct gui_window *g,
+ wimp_scroll_direction scroll_x, wimp_scroll_direction scroll_y)
+{
+ int visible_x, visible_y;
+ int step_x = 0, step_y = 0;
+ int toolbar_y;
+ wimp_window_state state;
+ wimp_pointer pointer;
+ os_error *error;
+ os_coord pos;
+ bool handled = false;
+ struct toolbar *toolbar;
+
+ if (g == NULL)
+ return;
+
+ /* Get the current window, toolbar and pointer details. */
+
+ state.w = g->window;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess);
+ return;
+ }
+
+ toolbar = ro_toolbar_parent_window_lookup(g->window);
+ assert(g == NULL || g->toolbar == NULL || g->toolbar == toolbar);
+
+ toolbar_y = (toolbar == NULL) ? 0 : ro_toolbar_full_height(toolbar);
+
+ visible_x = state.visible.x1 - state.visible.x0 - 32;
+ visible_y = state.visible.y1 - state.visible.y0 - 32 - toolbar_y;
+
+ error = xwimp_get_pointer_info(&pointer);
+ if (error) {
+ LOG("xwimp_get_pointer_info 0x%x : %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ /* Turn the scroll requirement from Scroll Event codes into coordinates
+ * that the core can understand.
+ */
+
+ switch (scroll_x) {
+ case wimp_SCROLL_PAGE_LEFT:
+ step_x = SCROLL_PAGE_DOWN;
+ break;
+ case wimp_SCROLL_AUTO_LEFT:
+ case wimp_SCROLL_COLUMN_LEFT:
+ step_x = -16;
+ break;
+ case wimp_SCROLL_AUTO_RIGHT:
+ case wimp_SCROLL_COLUMN_RIGHT:
+ step_x = 16;
+ break;
+ case wimp_SCROLL_PAGE_RIGHT:
+ step_x = SCROLL_PAGE_UP;
+ break;
+ case 0x80000000:
+ step_x = SCROLL_BOTTOM;
+ break;
+ case 0x7fffffff:
+ step_x = SCROLL_TOP;
+ break;
+ default:
+ step_x = (visible_x * (scroll_x>>2)) >> 2;
+ break;
+ }
+
+ switch (scroll_y) {
+ case wimp_SCROLL_PAGE_UP:
+ step_y = SCROLL_PAGE_UP;
+ break;
+ case wimp_SCROLL_AUTO_UP:
+ case wimp_SCROLL_LINE_UP:
+ step_y = -16;
+ break;
+ case wimp_SCROLL_AUTO_DOWN:
+ case wimp_SCROLL_LINE_DOWN:
+ step_y = 16;
+ break;
+ case wimp_SCROLL_PAGE_DOWN:
+ step_y = SCROLL_PAGE_DOWN;
+ break;
+ case 0x80000000:
+ step_y = SCROLL_BOTTOM;
+ break;
+ case 0x7fffffff:
+ step_y = SCROLL_TOP;
+ break;
+ default:
+ step_y = -((visible_y * (scroll_y>>2)) >> 2);
+ break;
+ }
+
+ /* If no scrolling is required, there's no point trying to do any. */
+
+ if (step_x == 0 && step_y == 0)
+ return;
+
+ /* If the pointer is over the window being scrolled, then try to get
+ * the core to do the scrolling on the object under the pointer.
+ */
+
+ if (pointer.w == g->window &&
+ ro_gui_window_to_window_pos(g,
+ pointer.pos.x, pointer.pos.y, &pos))
+ handled = browser_window_scroll_at_point(g->bw, pos.x, pos.y,
+ step_x, step_y);
+
+ /* If the core didn't do the scrolling, handle it via the Wimp.
+ * Windows which contain frames can only be scrolled by the core,
+ * because it implements frame scroll bars.
+ */
+
+ if (!handled && (browser_window_is_frameset(g->bw) == false)) {
+ switch (step_x) {
+ case SCROLL_TOP:
+ state.xscroll -= 0x10000000;
+ break;
+ case SCROLL_BOTTOM:
+ state.xscroll += 0x10000000;
+ break;
+ case SCROLL_PAGE_UP:
+ state.xscroll += visible_x;
+ break;
+ case SCROLL_PAGE_DOWN:
+ state.xscroll -= visible_x;
+ break;
+ default:
+ state.xscroll += 2 * step_x;
+ break;
+ }
+
+ switch (step_y) {
+ case SCROLL_TOP:
+ state.yscroll += 0x10000000;
+ break;
+ case SCROLL_BOTTOM:
+ state.yscroll -= 0x10000000;
+ break;
+ case SCROLL_PAGE_UP:
+ state.yscroll += visible_y;
+ break;
+ case SCROLL_PAGE_DOWN:
+ state.yscroll -= visible_y;
+ break;
+ default:
+ state.yscroll -= 2 * step_y;
+ break;
+ }
+
+ error = xwimp_open_window((wimp_open *) &state);
+ if (error) {
+ LOG("xwimp_open_window: 0x%x: %s", error->errnum, error->errmess);
+ }
+ }
+}
+
+
+/**
+ * Handle Message_DataLoad (file dragged in) for a window.
+ *
+ * \param g window
+ * \param message Message_DataLoad block
+ * \return true if the load was processed
+ *
+ * If the file was dragged into a form file input, it is used as the value.
+ */
+
+bool ro_gui_window_dataload(struct gui_window *g, wimp_message *message)
+{
+ os_error *error;
+ os_coord pos;
+
+ /* Ignore directories etc. */
+ if (0x1000 <= message->data.data_xfer.file_type)
+ return false;
+
+ if (!ro_gui_window_to_window_pos(g, message->data.data_xfer.pos.x,
+ message->data.data_xfer.pos.y, &pos))
+ return false;
+
+ if (browser_window_drop_file_at_point(g->bw, pos.x, pos.y,
+ message->data.data_xfer.file_name) == false)
+ return false;
+
+ /* send DataLoadAck */
+ message->action = message_DATA_LOAD_ACK;
+ message->your_ref = message->my_ref;
+ error = xwimp_send_message(wimp_USER_MESSAGE, message, message->sender);
+ if (error) {
+ LOG("xwimp_send_message: 0x%x: %s\n", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+
+ return true;
+}
+
+
+/**
+ * Handle pointer movements in a browser window.
+ *
+ * \param *pointer new mouse position
+ * \param *data browser window that the pointer is in
+ */
+
+void ro_gui_window_mouse_at(wimp_pointer *pointer, void *data)
+{
+ os_coord pos;
+ struct gui_window *g = (struct gui_window *) data;
+
+ if (ro_gui_window_to_window_pos(g, pointer->pos.x, pointer->pos.y, &pos))
+ browser_window_mouse_track(g->bw,
+ ro_gui_mouse_drag_state(pointer->buttons,
+ wimp_BUTTON_DOUBLE_CLICK_DRAG),
+ pos.x, pos.y);
+}
+
+
+/**
+ * Window is being iconised. Create a suitable thumbnail sprite
+ * (which, sadly, must be in the Wimp sprite pool), and return
+ * the sprite name and truncated title to the iconiser
+ *
+ * \param g the gui window being iconised
+ * \param wi the WindowInfo message from the iconiser
+ */
+
+void ro_gui_window_iconise(struct gui_window *g,
+ wimp_full_message_window_info *wi)
+{
+ /* sadly there is no 'legal' way to get the sprite into
+ * the Wimp sprite pool other than via a filing system */
+ const char *temp_fname = "Pipe:$._tmpfile";
+ struct browser_window *bw = g->bw;
+ osspriteop_header *overlay = NULL;
+ osspriteop_header *sprite_header;
+ struct bitmap *bitmap;
+ osspriteop_area *area;
+ int width = 34, height = 34;
+ hlcache_handle *h;
+ os_error *error;
+ int len, id;
+
+ assert(bw);
+
+ h = browser_window_get_content(bw);
+ if (!h) return;
+
+ /* if an overlay sprite is defined, locate it and gets its dimensions
+ * so that we can produce a thumbnail with the same dimensions */
+ if (!ro_gui_wimp_get_sprite("ic_netsfxx", &overlay)) {
+ error = xosspriteop_read_sprite_info(osspriteop_PTR,
+ (osspriteop_area *)0x100,
+ (osspriteop_id)overlay, &width, &height, NULL,
+ NULL);
+ if (error) {
+ LOG("xosspriteop_read_sprite_info: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("MiscError", error->errmess);
+ overlay = NULL;
+ }
+ else if (sprite_bpp(overlay) != 8) {
+ LOG("overlay sprite is not 8bpp");
+ overlay = NULL;
+ }
+ }
+
+ /* create the thumbnail sprite */
+ bitmap = riscos_bitmap_create(width, height, BITMAP_NEW | BITMAP_OPAQUE |
+ BITMAP_CLEAR_MEMORY);
+ if (!bitmap) {
+ LOG("Thumbnail initialisation failed.");
+ return;
+ }
+ riscos_bitmap_render(bitmap, h);
+ if (overlay) {
+ riscos_bitmap_overlay_sprite(bitmap, overlay);
+ }
+ area = riscos_bitmap_convert_8bpp(bitmap);
+ riscos_bitmap_destroy(bitmap);
+ if (!area) {
+ LOG("Thumbnail conversion failed.");
+ return;
+ }
+
+ /* choose a suitable sprite name */
+ id = 0;
+ while (iconise_used[id])
+ if ((unsigned)++id >= NOF_ELEMENTS(iconise_used)) {
+ id = iconise_next;
+ if ((unsigned)++iconise_next >=
+ NOF_ELEMENTS(iconise_used))
+ iconise_next = 0;
+ break;
+ }
+
+ sprite_header = (osspriteop_header *)(area + 1);
+ len = sprintf(sprite_header->name, "ic_netsf%.2d", id);
+
+ error = xosspriteop_save_sprite_file(osspriteop_USER_AREA,
+ area, temp_fname);
+ if (error) {
+ LOG("xosspriteop_save_sprite_file: 0x%x:%s", error->errnum, error->errmess);
+ ro_warn_user("MiscError", error->errmess);
+ free(area);
+ return;
+ }
+
+ error = xwimpspriteop_merge_sprite_file(temp_fname);
+ if (error) {
+ LOG("xwimpspriteop_merge_sprite_file: 0x%x:%s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ remove(temp_fname);
+ free(area);
+ return;
+ }
+
+ memcpy(wi->sprite_name, sprite_header->name + 3, len - 2); /* inc NUL */
+ strncpy(wi->title, g->title, sizeof(wi->title));
+ wi->title[sizeof(wi->title) - 1] = '\0';
+
+ if (wimptextop_string_width(wi->title, 0) > 182) {
+ /* work around bug in Pinboard where it will fail to display
+ * the icon if the text is very wide */
+ if (strlen(wi->title) > 10)
+ wi->title[10] = '\0'; /* pinboard does this anyway */
+ while (wimptextop_string_width(wi->title, 0) > 182)
+ wi->title[strlen(wi->title) - 1] = '\0';
+ }
+
+ wi->size = sizeof(wimp_full_message_window_info);
+ wi->your_ref = wi->my_ref;
+ error = xwimp_send_message(wimp_USER_MESSAGE, (wimp_message*)wi,
+ wi->sender);
+ if (error) {
+ LOG("xwimp_send_message: 0x%x:%s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+ else {
+ g->iconise_icon = id;
+ iconise_used[id] = true;
+ }
+
+ free(area);
+}
+
+
+/**
+ * Completes scrolling of a browser window
+ *
+ * \param *drag The DragEnd event data block.
+ * \param *data gui window block pointer.
+ */
+
+static void ro_gui_window_scroll_end(wimp_dragged *drag, void *data)
+{
+ wimp_pointer pointer;
+ os_error *error;
+ os_coord pos;
+ struct gui_window *g = (struct gui_window *) data;
+
+ if (!g)
+ return;
+
+ error = xwimp_drag_box((wimp_drag*)-1);
+ if (error) {
+ LOG("xwimp_drag_box: 0x%x : %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+
+ error = xwimp_get_pointer_info(&pointer);
+ if (error) {
+ LOG("xwimp_get_pointer_info 0x%x : %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ error = xwimpspriteop_set_pointer_shape("ptr_default", 0x31, 0, 0, 0, 0);
+ if (error) {
+ LOG("xwimpspriteop_set_pointer_shape: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+
+ if (ro_gui_window_to_window_pos(g, drag->final.x0, drag->final.y0, &pos))
+ browser_window_mouse_track(g->bw, 0, pos.x, pos.y);
+}
+
+
+/**
+ * Process Mouse_Click events in a toolbar's button bar. This does not handle
+ * other clicks in a toolbar: these are handled by the toolbar module itself.
+ *
+ * \param *data The GUI window associated with the click.
+ * \param action_type The action type to be handled.
+ * \param action The action to process.
+ */
+
+void ro_gui_window_toolbar_click(void *data,
+ toolbar_action_type action_type, union toolbar_action action)
+{
+ struct gui_window *g = data;
+ nserror err;
+
+ if (g == NULL)
+ return;
+
+
+ if (action_type == TOOLBAR_ACTION_URL) {
+ switch (action.url) {
+ case TOOLBAR_URL_DRAG_URL:
+ {
+ gui_save_type save_type;
+
+ if (!browser_window_has_content(g->bw))
+ break;
+
+ if (ro_gui_shift_pressed())
+ save_type = GUI_SAVE_LINK_URL;
+ else
+ save_type = GUI_SAVE_LINK_TEXT;
+
+ ro_gui_drag_save_link(save_type,
+ browser_window_get_url(g->bw),
+ browser_window_get_title(g->bw), g);
+ }
+ break;
+
+ case TOOLBAR_URL_SELECT_HOTLIST:
+ ro_gui_window_action_add_bookmark(g);
+ break;
+
+ case TOOLBAR_URL_ADJUST_HOTLIST:
+ ro_gui_window_action_remove_bookmark(g);
+ break;
+
+ default:
+ break;
+ }
+
+ return;
+ }
+
+
+ /* By now, the only valid action left is a button click. If it isn't
+ * one of those, give up.
+ */
+
+ if (action_type != TOOLBAR_ACTION_BUTTON)
+ return;
+
+ switch (action.button) {
+ case TOOLBAR_BUTTON_BACK:
+ if (g->bw != NULL)
+ browser_window_history_back(g->bw, false);
+ break;
+
+ case TOOLBAR_BUTTON_BACK_NEW:
+ if (g->bw != NULL)
+ browser_window_history_back(g->bw, true);
+ break;
+
+ case TOOLBAR_BUTTON_FORWARD:
+ if (g->bw != NULL)
+ browser_window_history_forward(g->bw, false);
+ break;
+
+ case TOOLBAR_BUTTON_FORWARD_NEW:
+ if (g->bw != NULL)
+ browser_window_history_forward(g->bw, true);
+ break;
+
+ case TOOLBAR_BUTTON_STOP:
+ if (g->bw != NULL)
+ browser_window_stop(g->bw);
+ break;
+
+ case TOOLBAR_BUTTON_RELOAD:
+ if (g->bw != NULL)
+ browser_window_reload(g->bw, false);
+ break;
+
+ case TOOLBAR_BUTTON_RELOAD_ALL:
+ if (g->bw != NULL)
+ browser_window_reload(g->bw, true);
+ break;
+
+ case TOOLBAR_BUTTON_HISTORY_LOCAL:
+ ro_gui_window_action_local_history(g);
+ break;
+
+ case TOOLBAR_BUTTON_HISTORY_GLOBAL:
+ ro_gui_global_history_open();
+ break;
+
+ case TOOLBAR_BUTTON_HOME:
+ ro_gui_window_action_home(g);
+ break;
+
+ case TOOLBAR_BUTTON_SEARCH:
+ ro_gui_window_action_search(g);
+ break;
+
+ case TOOLBAR_BUTTON_SCALE:
+ ro_gui_window_action_zoom(g);
+ break;
+
+ case TOOLBAR_BUTTON_BOOKMARK_OPEN:
+ ro_gui_hotlist_open();
+ break;
+
+ case TOOLBAR_BUTTON_BOOKMARK_ADD:
+ ro_gui_window_action_add_bookmark(g);
+ break;
+
+ case TOOLBAR_BUTTON_SAVE_SOURCE:
+ ro_gui_window_action_save(g, GUI_SAVE_SOURCE);
+ break;
+
+ case TOOLBAR_BUTTON_SAVE_COMPLETE:
+ ro_gui_window_action_save(g, GUI_SAVE_COMPLETE);
+ break;
+
+ case TOOLBAR_BUTTON_PRINT:
+ ro_gui_window_action_print(g);
+ break;
+
+ case TOOLBAR_BUTTON_UP:
+ err = browser_window_navigate_up(g->bw, false);
+ if (err != NSERROR_OK) {
+ ro_warn_user(messages_get_errorcode(err), NULL);
+ }
+ break;
+
+ case TOOLBAR_BUTTON_UP_NEW:
+ err = browser_window_navigate_up(g->bw, true);
+ if (err != NSERROR_OK) {
+ ro_warn_user(messages_get_errorcode(err), NULL);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ ro_gui_window_update_toolbar_buttons(g);
+}
+
+
+/**
+ * Handle Message_DataLoad (file dragged in) for a toolbar
+ *
+ * @todo This belongs in the toolbar module, and should be moved there
+ * once the module is able to usefully handle its own events.
+ *
+ * \param g window
+ * \param message Message_DataLoad block
+ * \return true if the load was processed
+ */
+
+bool ro_gui_toolbar_dataload(struct gui_window *g, wimp_message *message)
+{
+ if (message->data.data_xfer.file_type == osfile_TYPE_TEXT &&
+ ro_gui_window_import_text(g,
+ message->data.data_xfer.file_name)) {
+ os_error *error;
+
+ /* send DataLoadAck */
+ message->action = message_DATA_LOAD_ACK;
+ message->your_ref = message->my_ref;
+ error = xwimp_send_message(wimp_USER_MESSAGE, message,
+ message->sender);
+ if (error) {
+ LOG("xwimp_send_message: 0x%x: %s\n", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ }
+ return true;
+ }
+ return false;
+}
+
+
+/*
+ * Helper code for the Wimp Event Handlers.
+ */
+
+/**
+ * Check if a particular menu handle is a browser window menu
+ *
+ * \param *menu The menu in question.
+ * \return true if this menu is a browser window menu
+ */
+
+bool ro_gui_window_check_menu(wimp_menu *menu)
+{
+ return (ro_gui_browser_window_menu == menu) ? true : false;
+}
+
+
+/**
+ * Return boolean flags to show what RISC OS types we can sensibly convert
+ * the given object into.
+ *
+ * \todo This should probably be somewhere else but in window.c, and
+ * should probably even be done in content_().
+ *
+ * \param h The object to test.
+ * \param export_draw true on exit if a drawfile would be possible.
+ * \param export_sprite true on exit if a sprite would be possible.
+ * \return true if valid data is returned; else false.
+ */
+
+bool ro_gui_window_content_export_types(hlcache_handle *h,
+ bool *export_draw, bool *export_sprite)
+{
+ bool found_type = false;
+
+ if (export_draw != NULL)
+ *export_draw = false;
+ if (export_sprite != NULL)
+ *export_sprite = false;
+
+ if (h != NULL && content_get_type(h) == CONTENT_IMAGE) {
+ switch (ro_content_native_type(h)) {
+ case osfile_TYPE_SPRITE:
+ /* bitmap types (Sprite export possible) */
+ found_type = true;
+ if (export_sprite != NULL)
+ *export_sprite = true;
+ break;
+ case osfile_TYPE_DRAW:
+ /* vector types (Draw export possible) */
+ found_type = true;
+ if (export_draw != NULL)
+ *export_draw = true;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return found_type;
+}
+
+
+/**
+ * Prepare the page info window for use.
+ *
+ * \param *g The GUI window block to use.
+ */
+
+void ro_gui_window_prepare_pageinfo(struct gui_window *g)
+{
+ hlcache_handle *h = browser_window_get_content(g->bw);
+ char icon_buf[20] = "file_xxx";
+ char enc_buf[40];
+ const char *icon = icon_buf;
+ const char *title, *url;
+ lwc_string *mime;
+ const char *enc = "-";
+
+ assert(h);
+
+ title = content_get_title(h);
+ if (title == NULL)
+ title = "-";
+ url = nsurl_access(hlcache_handle_get_url(h));
+ if (url == NULL)
+ url = "-";
+ mime = content_get_mime_type(h);
+
+ sprintf(icon_buf, "file_%x", ro_content_filetype(h));
+ if (!ro_gui_wimp_sprite_exists(icon_buf))
+ sprintf(icon_buf, "file_xxx");
+
+ if (content_get_type(h) == CONTENT_HTML) {
+ if (content_get_encoding(h, CONTENT_ENCODING_NORMAL)) {
+ snprintf(enc_buf, sizeof enc_buf, "%s (%s)",
+ content_get_encoding(h, CONTENT_ENCODING_NORMAL),
+ content_get_encoding(h, CONTENT_ENCODING_SOURCE));
+ enc = enc_buf;
+ } else {
+ enc = messages_get("EncodingUnk");
+ }
+ }
+
+ ro_gui_set_icon_string(dialog_pageinfo, ICON_PAGEINFO_ICON,
+ icon, true);
+ ro_gui_set_icon_string(dialog_pageinfo, ICON_PAGEINFO_TITLE,
+ title, true);
+ ro_gui_set_icon_string(dialog_pageinfo, ICON_PAGEINFO_URL,
+ url, true);
+ ro_gui_set_icon_string(dialog_pageinfo, ICON_PAGEINFO_ENC,
+ enc, true);
+ ro_gui_set_icon_string(dialog_pageinfo, ICON_PAGEINFO_TYPE,
+ lwc_string_data(mime), true);
+
+ lwc_string_unref(mime);
+}
+
+
+/**
+ * Prepare the object info window for use
+ *
+ * \param *object the object for which information is to be displayed
+ * \param *target_url corresponding url, if any
+ */
+
+void ro_gui_window_prepare_objectinfo(hlcache_handle *object, nsurl *target_url)
+{
+ char icon_buf[20] = "file_xxx";
+ const char *url;
+ lwc_string *mime;
+ const char *target = "-";
+
+ sprintf(icon_buf, "file_%.3x",ro_content_filetype(object));
+ if (!ro_gui_wimp_sprite_exists(icon_buf)) {
+ sprintf(icon_buf, "file_xxx");
+ }
+
+ url = nsurl_access(hlcache_handle_get_url(object));
+ if (url == NULL) {
+ url = "-";
+ }
+ mime = content_get_mime_type(object);
+
+ if (target_url != NULL) {
+ target = nsurl_access(target_url);
+ }
+
+ ro_gui_set_icon_string(dialog_objinfo, ICON_OBJINFO_ICON,
+ icon_buf, true);
+ ro_gui_set_icon_string(dialog_objinfo, ICON_OBJINFO_URL,
+ url, true);
+ ro_gui_set_icon_string(dialog_objinfo, ICON_OBJINFO_TARGET,
+ target, true);
+ ro_gui_set_icon_string(dialog_objinfo, ICON_OBJINFO_TYPE,
+ lwc_string_data(mime), true);
+
+ lwc_string_unref(mime);
+}
+
+
+/*
+ * User Actions in the browser window
+ */
+
+/**
+ * Launch a new url in the given window.
+ *
+ * \param g gui_window to update
+ * \param url1 url to be launched
+ */
+
+void ro_gui_window_launch_url(struct gui_window *g, const char *url1)
+{
+ nserror error;
+ nsurl *url;
+
+ if (url1 == NULL)
+ return;
+
+ ro_gui_url_complete_close();
+
+ error = nsurl_create(url1, &url);
+ if (error != NSERROR_OK) {
+ ro_warn_user(messages_get_errorcode(error), 0);
+ } else {
+ ro_gui_window_set_url(g, url);
+
+ browser_window_navigate(g->bw, url,
+ NULL, BW_NAVIGATE_HISTORY,
+ NULL, NULL, NULL);
+ nsurl_unref(url);
+ }
+}
+
+
+/**
+ * Perform a Navigate Home action on a browser window.
+ *
+ * \param *g The browser window to act on.
+ */
+
+void ro_gui_window_action_home(struct gui_window *g)
+{
+ static const char *addr = NETSURF_HOMEPAGE;
+ nsurl *url;
+ nserror error;
+
+ if (g == NULL || g->bw == NULL)
+ return;
+
+ if (nsoption_charp(homepage_url) != NULL) {
+ addr = nsoption_charp(homepage_url);
+ }
+
+ error = nsurl_create(addr, &url);
+ if (error == NSERROR_OK) {
+ error = browser_window_navigate(g->bw,
+ url,
+ NULL,
+ BW_NAVIGATE_HISTORY,
+ NULL,
+ NULL,
+ NULL);
+ nsurl_unref(url);
+ }
+ if (error != NSERROR_OK) {
+ ro_warn_user(messages_get_errorcode(error), 0);
+ }
+}
+
+
+/**
+ * Open a new browser window.
+ *
+ * \param *g The browser window to act on.
+ */
+
+void ro_gui_window_action_new_window(struct gui_window *g)
+{
+ nserror error;
+
+ if (g == NULL || g->bw == NULL)
+ return;
+
+ error = browser_window_create(BW_CREATE_CLONE,
+ browser_window_get_url(g->bw),
+ NULL, g->bw, NULL);
+
+ if (error != NSERROR_OK) {
+ ro_warn_user(messages_get_errorcode(error), 0);
+ }
+}
+
+
+/**
+ * Open a local history pane for a browser window.
+ *
+ * \param *g The browser window to act on.
+ */
+
+void ro_gui_window_action_local_history(struct gui_window *g)
+{
+ if (g != NULL && g->bw != NULL)
+ ro_gui_history_open(g, true);
+}
+
+
+/**
+ * Open a save dialogue for a browser window contents.
+ *
+ * \param *g The browser window to act on.
+ * \param save_type The type of save to open.
+ */
+
+void ro_gui_window_action_save(struct gui_window *g, gui_save_type save_type)
+{
+ hlcache_handle *h;
+
+ if (g == NULL || g->bw == NULL || !browser_window_has_content(g->bw))
+ return;
+
+ h = browser_window_get_content(g->bw);
+ if (h == NULL)
+ return;
+
+ ro_gui_save_prepare(save_type, h, NULL, NULL, NULL);
+ ro_gui_dialog_open_persistent(g->window, dialog_saveas, true);
+}
+
+
+/**
+ * Open a text search dialogue for a browser window.
+ *
+ * \param *g The browser window to act on.
+ */
+
+void ro_gui_window_action_search(struct gui_window *g)
+{
+ if (g == NULL || g->bw == NULL || !browser_window_can_search(g->bw))
+ return;
+
+ ro_gui_search_prepare(g->bw);
+ ro_gui_dialog_open_persistent(g->window, dialog_search, true);
+}
+
+
+/**
+ * Open a zoom dialogue for a browser window.
+ *
+ * \param *g The browser window to act on.
+ */
+
+void ro_gui_window_action_zoom(struct gui_window *g)
+{
+ if (g == NULL)
+ return;
+
+ ro_gui_dialog_prepare_zoom(g);
+ ro_gui_dialog_open_persistent(g->window, dialog_zoom, true);
+}
+
+
+/**
+ * Add a hotlist entry for a browser window.
+ *
+ * \param *g The browser window to act on.
+ */
+
+static void ro_gui_window_action_add_bookmark(struct gui_window *g)
+{
+ nsurl *url;
+
+ if (g == NULL || g->bw == NULL || g->toolbar == NULL ||
+ browser_window_has_content(g->bw) == false)
+ return;
+
+ url = browser_window_get_url(g->bw);
+
+ ro_gui_hotlist_add_page(url);
+ ro_toolbar_update_hotlist(g->toolbar);
+}
+
+
+/**
+ * Remove a hotlist entry for a browser window.
+ *
+ * \param *g The browser window to act on.
+ */
+
+static void ro_gui_window_action_remove_bookmark(struct gui_window *g)
+{
+ nsurl *url;
+
+ if (g == NULL || g->bw == NULL || g->toolbar == NULL ||
+ browser_window_has_content(g->bw) == false)
+ return;
+
+ url = browser_window_get_url(g->bw);
+
+ ro_gui_hotlist_remove_page(url);
+}
+
+
+/**
+ * Open a print dialogue for a browser window.
+ *
+ * \param *g The browser window to act on.
+ */
+
+void ro_gui_window_action_print(struct gui_window *g)
+{
+ if (g == NULL)
+ return;
+
+ ro_gui_print_prepare(g);
+ ro_gui_dialog_open_persistent(g->window, dialog_print, true);
+}
+
+
+/**
+ * Open a page info box for a browser window.
+ *
+ * \param *g The browser window to act on.
+ */
+
+void ro_gui_window_action_page_info(struct gui_window *g)
+{
+ if (g == NULL || g->bw == NULL ||
+ browser_window_has_content(g->bw) == false)
+ return;
+
+ ro_gui_window_prepare_pageinfo(g);
+ ro_gui_dialog_open_persistent(g->window, dialog_pageinfo, false);
+}
+
+
+/*
+ * Window and Toolbar Redraw and Update
+ */
+
+/**
+ * Redraws the content for all windows.
+ */
+
+void ro_gui_window_redraw_all(void)
+{
+ struct gui_window *g;
+ for (g = window_list; g; g = g->next)
+ gui_window_redraw_window(g);
+}
+
+
+/**
+ * Remove all pending update boxes for a window
+ *
+ * \param g gui_window
+ */
+void ro_gui_window_remove_update_boxes(struct gui_window *g)
+{
+ struct update_box *cur;
+
+ for (cur = pending_updates; cur != NULL; cur = cur->next) {
+ if (cur->g == g)
+ cur->g = NULL;
+ }
+}
+
+
+/**
+ * Redraw any pending update boxes.
+ */
+void ro_gui_window_update_boxes(void)
+{
+ osbool more;
+ bool use_buffer;
+ wimp_draw update;
+ struct rect clip;
+ os_error *error;
+ struct update_box *cur;
+ struct gui_window *g;
+ struct redraw_context ctx = {
+ .interactive = true,
+ .background_images = true,
+ .plot = &ro_plotters
+ };
+
+ for (cur = pending_updates; cur != NULL; cur = cur->next) {
+ g = cur->g;
+ if (!g)
+ continue;
+
+ use_buffer = cur->use_buffer;
+
+ update.w = g->window;
+ update.box.x0 = cur->x0;
+ update.box.y0 = cur->y0;
+ update.box.x1 = cur->x1;
+ update.box.y1 = cur->y1;
+
+ error = xwimp_update_window(&update, &more);
+ if (error) {
+ LOG("xwimp_update_window: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ continue;
+ }
+
+ /* Set the current redraw gui_window to get options from */
+ ro_gui_current_redraw_gui = g;
+
+ ro_plot_origin_x = update.box.x0 - update.xscroll;
+ ro_plot_origin_y = update.box.y1 - update.yscroll;
+
+ while (more) {
+ clip.x0 = (update.clip.x0 - ro_plot_origin_x) / 2;
+ clip.y0 = (ro_plot_origin_y - update.clip.y1) / 2;
+ clip.x1 = (update.clip.x1 - ro_plot_origin_x) / 2;
+ clip.y1 = (ro_plot_origin_y - update.clip.y0) / 2;
+
+ if (use_buffer)
+ ro_gui_buffer_open(&update);
+
+ browser_window_redraw(g->bw, 0, 0, &clip, &ctx);
+
+ if (use_buffer)
+ ro_gui_buffer_close();
+
+ error = xwimp_get_rectangle(&update, &more);
+ /* RISC OS 3.7 returns an error here if enough buffer
+ * was claimed to cause a new dynamic area to be
+ * created. It doesn't actually stop anything working,
+ * so we mask it out for now until a better fix is
+ * found. This appears to be a bug in RISC OS. */
+ if (error && !(use_buffer &&
+ error->errnum == error_WIMP_GET_RECT)) {
+ LOG("xwimp_get_rectangle: 0x%x: %s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ ro_gui_current_redraw_gui = NULL;
+ continue;
+ }
+ }
+
+ /* Reset the current redraw gui_window to prevent
+ * thumbnails from retaining options */
+ ro_gui_current_redraw_gui = NULL;
+ }
+ while (pending_updates) {
+ cur = pending_updates;
+ pending_updates = pending_updates->next;
+ free(cur);
+ }
+}
+
+
+/**
+ * callback from core to reformat a window.
+ */
+static void riscos_window_reformat(struct gui_window *gw)
+{
+ if (gw != NULL) {
+ browser_window_reformat(gw->bw, false,
+ gw->old_width / 2,
+ gw->old_height / 2);
+ }
+}
+
+/**
+ * Destroy all browser windows.
+ */
+
+void ro_gui_window_quit(void)
+{
+ while (window_list) {
+ struct gui_window *cur = window_list;
+ window_list = window_list->next;
+
+ browser_window_destroy(cur->bw);
+ }
+}
+
+
+/**
+ * Animate the "throbbers" of all browser windows.
+ */
+
+void ro_gui_throb(void)
+{
+ struct gui_window *g;
+
+ for (g = window_list; g; g = g->next) {
+ if (!g->active)
+ continue;
+ if (g->toolbar != NULL)
+ ro_toolbar_throb(g->toolbar);
+ }
+}
+
+
+/**
+ * Update the toolbar buttons for a given browser window to reflect the
+ * current state of its contents.
+ *
+ * Note that the parameters to this function are arranged so that it can be
+ * supplied to the toolbar module as an button state update callback.
+ *
+ * \param *g The browser window to update.
+ */
+
+void ro_gui_window_update_toolbar_buttons(struct gui_window *g)
+{
+ struct browser_window *bw;
+ struct toolbar *toolbar;
+
+ if (g == NULL || g->toolbar == NULL)
+ return;
+
+ bw = g->bw;
+ toolbar = g->toolbar;
+
+ ro_toolbar_set_button_shaded_state(toolbar, TOOLBAR_BUTTON_RELOAD,
+ !browser_window_reload_available(bw));
+
+ ro_toolbar_set_button_shaded_state(toolbar, TOOLBAR_BUTTON_STOP,
+ !browser_window_stop_available(bw));
+
+ ro_toolbar_set_button_shaded_state(toolbar, TOOLBAR_BUTTON_BACK,
+ !browser_window_back_available(bw));
+
+ ro_toolbar_set_button_shaded_state(toolbar, TOOLBAR_BUTTON_FORWARD,
+ !browser_window_forward_available(bw));
+
+ ro_toolbar_set_button_shaded_state(toolbar, TOOLBAR_BUTTON_UP,
+ !browser_window_up_available(bw));
+
+ ro_toolbar_set_button_shaded_state(toolbar, TOOLBAR_BUTTON_SEARCH,
+ !browser_window_can_search(bw));
+
+ ro_toolbar_set_button_shaded_state(toolbar, TOOLBAR_BUTTON_SCALE,
+ !browser_window_has_content(bw));
+
+ ro_toolbar_set_button_shaded_state(toolbar, TOOLBAR_BUTTON_PRINT,
+ !browser_window_has_content(bw));
+
+ ro_toolbar_set_button_shaded_state(toolbar, TOOLBAR_BUTTON_SAVE_SOURCE,
+ !browser_window_has_content(bw));
+
+ ro_toolbar_update_urlsuggest(toolbar);
+}
+
+
+/**
+ * Update a window to reflect a change in toolbar size: used as a callback by
+ * the toolbar module when a toolbar height changes.
+ *
+ * \param *data void pointer the window's gui_window struct
+ */
+
+void ro_gui_window_update_toolbar(void *data)
+{
+ struct gui_window *g = (struct gui_window *) data;
+
+ if (g != NULL)
+ gui_window_update_extent(g);
+}
+
+
+/**
+ * Save a new toolbar button configuration: used as a callback by the toolbar
+ * module when a buttonbar edit has finished.
+ *
+ * \param *data void pointer to the window's gui_window struct
+ * \param *config pointer to a malloc()'d button config string.
+ */
+
+void ro_gui_window_save_toolbar_buttons(void *data, char *config)
+{
+ nsoption_set_charp(toolbar_browser, config);
+ ro_gui_save_options();
+}
+
+
+/**
+ * Update a window and its toolbar to reflect a new theme: used as a callback
+ * by the toolbar module when a theme change affects a toolbar.
+ *
+ * \param *data void pointer to the window's gui_window struct
+ * \param ok true if the bar still exists; else false.
+ */
+
+void ro_gui_window_update_theme(void *data, bool ok)
+{
+ struct gui_window *g = (struct gui_window *) data;
+
+ if (g != NULL && g->toolbar != NULL) {
+ if (ok) {
+ gui_window_update_extent(g);
+ } else {
+ g->toolbar = NULL;
+ }
+ }
+}
+
+
+/*
+ * General Window Support
+ */
+
+/**
+ * Import text file into window
+ *
+ * \param g gui window containing textarea
+ * \param filename pathname of file to be imported
+ * \return true iff successful
+ */
+
+bool ro_gui_window_import_text(struct gui_window *g, const char *filename)
+{
+ fileswitch_object_type obj_type;
+ os_error *error;
+ char *buf, *utf8_buf, *sp;
+ int size;
+ nserror ret;
+ const char *ep;
+ char *p;
+
+ error = xosfile_read_stamped(filename, &obj_type, NULL, NULL,
+ &size, NULL, NULL);
+ if (error) {
+ LOG("xosfile_read_stamped: 0x%x:%s", error->errnum, error->errmess);
+ ro_warn_user("FileError", error->errmess);
+ return true; /* was for us, but it didn't work! */
+ }
+
+ /* Allocate one byte more than needed to ensure that the buffer is
+ * always terminated, regardless of file contents.
+ */
+
+ buf = calloc(size + 1, sizeof(char));
+ if (!buf) {
+ ro_warn_user("NoMemory", NULL);
+ return true;
+ }
+
+ error = xosfile_load_stamped(filename, (byte*)buf,
+ NULL, NULL, NULL, NULL, NULL);
+
+ if (error) {
+ LOG("xosfile_load_stamped: 0x%x:%s", error->errnum, error->errmess);
+ ro_warn_user("LoadError", error->errmess);
+ free(buf);
+ return true;
+ }
+
+ ret = utf8_from_local_encoding(buf, size, &utf8_buf);
+ if (ret != NSERROR_OK) {
+ /* bad encoding shouldn't happen */
+ assert(ret != NSERROR_BAD_ENCODING);
+ LOG("utf8_from_local_encoding failed");
+ free(buf);
+ ro_warn_user("NoMemory", NULL);
+ return true;
+ }
+ size = strlen(utf8_buf);
+
+ ep = utf8_buf + size;
+ p = utf8_buf;
+
+ /* skip leading whitespace */
+ while (isspace(*p)) p++;
+
+ sp = p;
+ while (*p && *p != '\r' && *p != '\n')
+ p += utf8_next(p, ep - p, 0);
+ *p = '\0';
+
+ if (p > sp)
+ ro_gui_window_launch_url(g, sp);
+
+ free(buf);
+ free(utf8_buf);
+ return true;
+}
+
+
+/**
+ * Clones a browser window's options.
+ *
+ * \param new_gui the new gui window
+ * \param old_gui the gui window to clone from, or NULL for default
+ */
+
+void ro_gui_window_clone_options(
+ struct gui_window *new_gui,
+ struct gui_window *old_gui)
+{
+ assert(new_gui);
+
+ /* Clone the basic options
+ */
+ if (!old_gui) {
+ new_gui->option.buffer_animations = nsoption_bool(buffer_animations);
+ new_gui->option.buffer_everything = nsoption_bool(buffer_everything);
+ } else {
+ new_gui->option = old_gui->option;
+ }
+
+ /* Set up the toolbar
+ */
+ if (new_gui->toolbar) {
+ ro_toolbar_set_display_buttons(new_gui->toolbar,
+ nsoption_bool(toolbar_show_buttons));
+ ro_toolbar_set_display_url(new_gui->toolbar,
+ nsoption_bool(toolbar_show_address));
+ ro_toolbar_set_display_throbber(new_gui->toolbar,
+ nsoption_bool(toolbar_show_throbber));
+ if ((old_gui) && (old_gui->toolbar)) {
+ ro_toolbar_set_display_buttons(new_gui->toolbar,
+ ro_toolbar_get_display_buttons(
+ old_gui->toolbar));
+ ro_toolbar_set_display_url(new_gui->toolbar,
+ ro_toolbar_get_display_url(
+ old_gui->toolbar));
+ ro_toolbar_set_display_throbber(new_gui->toolbar,
+ ro_toolbar_get_display_throbber(
+ old_gui->toolbar));
+ ro_toolbar_process(new_gui->toolbar, -1, true);
+ }
+ }
+}
+
+
+/**
+ * Makes a browser window's options the default.
+ *
+ * \param gui The riscos gui window to set default options in.
+ */
+
+void ro_gui_window_default_options(struct gui_window *gui)
+{
+ if (gui == NULL)
+ return;
+
+ /* Save the basic options
+ */
+ nsoption_set_int(scale, gui->scale * 100);
+ nsoption_set_bool(buffer_animations, gui->option.buffer_animations);
+ nsoption_set_bool(buffer_everything, gui->option.buffer_everything);
+
+ /* Set up the toolbar
+ */
+ if (gui->toolbar != NULL) {
+ nsoption_set_bool(toolbar_show_buttons,
+ ro_toolbar_get_display_buttons(gui->toolbar));
+ nsoption_set_bool(toolbar_show_address,
+ ro_toolbar_get_display_url(gui->toolbar));
+ nsoption_set_bool(toolbar_show_throbber,
+ ro_toolbar_get_display_throbber(gui->toolbar));
+ }
+ if (gui->status_bar != NULL)
+ nsoption_set_int(toolbar_status_size,
+ ro_gui_status_bar_get_width(gui->status_bar));
+}
+
+
+/*
+ * Custom Menu Support
+ */
+
+/**
+ * Prepare or reprepare a form select menu, setting up the menu handle
+ * globals in the process.
+ *
+ * \param g The RISC OS gui window the menu is in.
+ * \param control The form control needing a menu.
+ * \return true if the menu is OK to be opened; else false.
+ */
+
+bool ro_gui_window_prepare_form_select_menu(struct gui_window *g,
+ struct form_control *control)
+{
+ unsigned int item, entries;
+ char *text_convert, *temp;
+ struct form_option *option;
+ bool reopen = true;
+ nserror err;
+
+ assert(control);
+
+ /* enumerate the entries */
+ entries = 0;
+ option = form_select_get_option(control, entries);
+ while (option != NULL) {
+ entries++;
+ option = form_select_get_option(control, entries);
+ }
+
+ if (entries == 0) {
+ /* no menu to display */
+ ro_gui_menu_destroy();
+ return false;
+ }
+
+ /* free riscos menu if there already is one */
+ if ((gui_form_select_menu) && (control != gui_form_select_control)) {
+ for (item = 0; ; item++) {
+ free(gui_form_select_menu->entries[item].data.
+ indirected_text.text);
+ if (gui_form_select_menu->entries[item].menu_flags &
+ wimp_MENU_LAST)
+ break;
+ }
+ free(gui_form_select_menu->title_data.indirected_text.text);
+ free(gui_form_select_menu);
+ gui_form_select_menu = 0;
+ }
+
+ /* allocate new riscos menu */
+ if (!gui_form_select_menu) {
+ reopen = false;
+ gui_form_select_menu = malloc(wimp_SIZEOF_MENU(entries));
+ if (!gui_form_select_menu) {
+ ro_warn_user("NoMemory", 0);
+ ro_gui_menu_destroy();
+ return false;
+ }
+ err = utf8_to_local_encoding(messages_get("SelectMenu"), 0,
+ &text_convert);
+ if (err != NSERROR_OK) {
+ /* badenc should never happen */
+ assert(err != NSERROR_BAD_ENCODING);
+ LOG("utf8_to_local_encoding failed");
+ ro_warn_user("NoMemory", 0);
+ ro_gui_menu_destroy();
+ return false;
+ }
+ gui_form_select_menu->title_data.indirected_text.text =
+ text_convert;
+ ro_gui_menu_init_structure(gui_form_select_menu, entries);
+ }
+
+ /* initialise menu entries from form control */
+ for (item = 0; item < entries; item++) {
+ option = form_select_get_option(control, item);
+ gui_form_select_menu->entries[item].menu_flags = 0;
+ if (option->selected)
+ gui_form_select_menu->entries[item].menu_flags =
+ wimp_MENU_TICKED;
+ if (!reopen) {
+
+ /* convert spaces to hard spaces to stop things
+ * like 'Go Home' being treated as if 'Home' is a
+ * keyboard shortcut and right aligned in the menu.
+ */
+
+ temp = cnv_space2nbsp(option->text);
+ if (!temp) {
+ LOG("cnv_space2nbsp failed");
+ ro_warn_user("NoMemory", 0);
+ ro_gui_menu_destroy();
+ return false;
+ }
+
+ err = utf8_to_local_encoding(temp,
+ 0, &text_convert);
+ if (err != NSERROR_OK) {
+ /* A bad encoding should never happen,
+ * so assert this */
+ assert(err != NSERROR_BAD_ENCODING);
+ LOG("utf8_to_enc failed");
+ ro_warn_user("NoMemory", 0);
+ ro_gui_menu_destroy();
+ return false;
+ }
+
+ free(temp);
+
+ gui_form_select_menu->entries[item].data.indirected_text.text =
+ text_convert;
+ gui_form_select_menu->entries[item].data.indirected_text.size =
+ strlen(gui_form_select_menu->entries[item].
+ data.indirected_text.text) + 1;
+ }
+ }
+
+ gui_form_select_menu->entries[0].menu_flags |=
+ wimp_MENU_TITLE_INDIRECTED;
+ gui_form_select_menu->entries[item - 1].menu_flags |= wimp_MENU_LAST;
+
+ return true;
+}
+
+/**
+ * Process selections from a form select menu, passing them back to the core.
+ *
+ * \param *g The browser window affected by the menu.
+ * \param *selection The menu selection.
+ */
+
+void ro_gui_window_process_form_select_menu(struct gui_window *g,
+ wimp_selection *selection)
+{
+ assert(g != NULL);
+
+ if (selection->items[0] >= 0)
+ form_select_process_selection(gui_form_select_control,
+ selection->items[0]);
+}
+
+
+/*
+ * Window and Toolbar Lookup
+ */
+
+/**
+ * Convert a RISC OS window handle to a gui_window.
+ *
+ * \param window RISC OS window handle.
+ * \return A pointer to a riscos gui window if found or NULL.
+ */
+
+struct gui_window *ro_gui_window_lookup(wimp_w window)
+{
+ struct gui_window *g;
+ for (g = window_list; g; g = g->next)
+ if (g->window == window)
+ return g;
+ return NULL;
+}
+
+
+/**
+ * Convert a toolbar RISC OS window handle to a gui_window.
+ *
+ * \param window RISC OS window handle of a toolbar
+ * \return pointer to a structure if found, NULL otherwise
+ */
+
+struct gui_window *ro_gui_toolbar_lookup(wimp_w window)
+{
+ struct gui_window *g = NULL;
+ struct toolbar *toolbar;
+ wimp_w parent;
+
+ toolbar = ro_toolbar_window_lookup(window);
+
+ if (toolbar != NULL) {
+ parent = ro_toolbar_get_parent_window(toolbar);
+ g = ro_gui_window_lookup(parent);
+ }
+
+ return g;
+}
+
+
+/*
+ * Core to RISC OS Conversions
+ */
+
+/**
+ * Convert x,y screen co-ordinates into window co-ordinates.
+ *
+ * \param g gui window
+ * \param x x ordinate
+ * \param y y ordinate
+ * \param pos receives position in window co-ordinatates
+ * \return true iff conversion successful
+ */
+
+bool ro_gui_window_to_window_pos(struct gui_window *g, int x, int y,
+ os_coord *pos)
+{
+ wimp_window_state state;
+ os_error *error;
+
+ assert(g);
+
+ state.w = g->window;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x:%s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return false;
+ }
+ pos->x = (x - (state.visible.x0 - state.xscroll)) / 2 / g->scale;
+ pos->y = ((state.visible.y1 - state.yscroll) - y) / 2 / g->scale;
+ return true;
+}
+
+
+/**
+ * Convert x,y window co-ordinates into screen co-ordinates.
+ *
+ * \param g gui window
+ * \param x x ordinate
+ * \param y y ordinate
+ * \param pos receives position in screen co-ordinatates
+ * \return true iff conversion successful
+ */
+
+bool ro_gui_window_to_screen_pos(struct gui_window *g, int x, int y,
+ os_coord *pos)
+{
+ wimp_window_state state;
+ os_error *error;
+
+ assert(g);
+
+ state.w = g->window;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG("xwimp_get_window_state: 0x%x:%s", error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return false;
+ }
+ pos->x = (x * 2 * g->scale) + (state.visible.x0 - state.xscroll);
+ pos->y = (state.visible.y1 - state.yscroll) - (y * 2 * g->scale);
+ return true;
+}
+
+
+/*
+ * Miscellaneous Functions
+ *
+ * \TODO -- These items might well belong elsewhere.
+ */
+
+/**
+ * Returns the state of the mouse buttons and modifiers keys for a
+ * mouse action, suitable for passing to the OS-independent
+ * browser window/ treeview/ etc code.
+ *
+ * \param buttons Wimp button state.
+ * \param type Wimp work-area/icon type for decoding.
+ * \return NetSurf core button state.
+ */
+
+browser_mouse_state ro_gui_mouse_click_state(wimp_mouse_state buttons,
+ wimp_icon_flags type)
+{
+ browser_mouse_state state = 0; /* Blank state with nothing set */
+ static struct {
+ enum { CLICK_SINGLE, CLICK_DOUBLE, CLICK_TRIPLE } type;
+ uint64_t time;
+ } last_click;
+
+ switch (type) {
+ case wimp_BUTTON_CLICK_DRAG:
+ /* Handle single clicks. */
+
+ /* We fire core PRESS and CLICK events together for "action on
+ * press" behaviour. */
+ if (buttons & (wimp_CLICK_SELECT)) /* Select click */
+ state |= BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_CLICK_1;
+ if (buttons & (wimp_CLICK_ADJUST)) /* Adjust click */
+ state |= BROWSER_MOUSE_PRESS_2 | BROWSER_MOUSE_CLICK_2;
+ break;
+
+ case wimp_BUTTON_DOUBLE_CLICK_DRAG:
+ /* Handle single, double, and triple clicks. */
+
+ /* Single clicks: Fire PRESS and CLICK events together
+ * for "action on press" behaviour. */
+ if (buttons & (wimp_SINGLE_SELECT)) {
+ /* Select single click */
+ state |= BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_CLICK_1;
+ } else if (buttons & (wimp_SINGLE_ADJUST)) {
+ /* Adjust single click */
+ state |= BROWSER_MOUSE_PRESS_2 | BROWSER_MOUSE_CLICK_2;
+ }
+
+ /* Double clicks: Fire PRESS, CLICK, and DOUBLE_CLICK
+ * events together for "action on 2nd press" behaviour. */
+ if (buttons & (wimp_DOUBLE_SELECT)) {
+ /* Select double click */
+ state |= BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_CLICK_1 |
+ BROWSER_MOUSE_DOUBLE_CLICK;
+ } else if (buttons & (wimp_DOUBLE_ADJUST)) {
+ /* Adjust double click */
+ state |= BROWSER_MOUSE_PRESS_2 | BROWSER_MOUSE_CLICK_2 |
+ BROWSER_MOUSE_DOUBLE_CLICK;
+ }
+
+ /* Need to consider what we have and decide whether to fire
+ * triple click instead */
+ if ((state == (BROWSER_MOUSE_PRESS_1 |
+ BROWSER_MOUSE_CLICK_1)) ||
+ (state == (BROWSER_MOUSE_PRESS_2 |
+ BROWSER_MOUSE_CLICK_2))) {
+ /* WIMP told us single click, but maybe we want to call
+ * it a triple click */
+
+ if (last_click.type == CLICK_DOUBLE) {
+ uint64_t ms_now;
+ nsu_getmonotonic_ms(&ms_now);
+
+ if (ms_now < (last_click.time + 500)) {
+ /* Triple click! Fire PRESS, CLICK, and
+ * TRIPLE_CLICK events together for
+ * "action on 3nd press" behaviour. */
+ last_click.type = CLICK_TRIPLE;
+ state |= BROWSER_MOUSE_TRIPLE_CLICK;
+ } else {
+ /* Single click */
+ last_click.type = CLICK_SINGLE;
+ }
+ } else {
+ /* Single click */
+ last_click.type = CLICK_SINGLE;
+ }
+ } else if ((state == (BROWSER_MOUSE_PRESS_1 |
+ BROWSER_MOUSE_CLICK_1 |
+ BROWSER_MOUSE_DOUBLE_CLICK)) ||
+ (state == (BROWSER_MOUSE_PRESS_2 |
+ BROWSER_MOUSE_CLICK_2 |
+ BROWSER_MOUSE_DOUBLE_CLICK))) {
+ /* Wimp told us double click, but we may want to
+ * call it single click */
+
+ if (last_click.type == CLICK_TRIPLE) {
+ state &= ~BROWSER_MOUSE_DOUBLE_CLICK;
+ last_click.type = CLICK_SINGLE;
+ } else {
+ last_click.type = CLICK_DOUBLE;
+ nsu_getmonotonic_ms(&last_click.time);
+ }
+ } else {
+ last_click.type = CLICK_SINGLE;
+ }
+ break;
+ }
+
+ /* Check if a drag has started */
+ if (buttons & (wimp_DRAG_SELECT)) {
+ /* A drag was _started_ with Select; Fire DRAG_1. */
+ state |= BROWSER_MOUSE_DRAG_1;
+ mouse_drag_select = true;
+ }
+ if (buttons & (wimp_DRAG_ADJUST)) {
+ /* A drag was _started_ with Adjust; Fire DRAG_2. */
+ state |= BROWSER_MOUSE_DRAG_2;
+ mouse_drag_adjust = true;
+ }
+
+ /* Set modifier key state */
+ if (ro_gui_shift_pressed()) state |= BROWSER_MOUSE_MOD_1;
+ if (ro_gui_ctrl_pressed()) state |= BROWSER_MOUSE_MOD_2;
+ if (ro_gui_alt_pressed()) state |= BROWSER_MOUSE_MOD_3;
+
+ return state;
+}
+
+
+/**
+ * Returns the state of the mouse buttons and modifiers keys whilst
+ * dragging, for passing to the OS-independent browser window/ treeview/
+ * etc code
+ *
+ * \param buttons Wimp button state.
+ * \param type Wimp work-area/icon type for decoding.
+ * \return NetSurf core button state.
+ */
+
+browser_mouse_state ro_gui_mouse_drag_state(wimp_mouse_state buttons,
+ wimp_icon_flags type)
+{
+ browser_mouse_state state = 0; /* Blank state with nothing set */
+
+ /* If mouse buttons aren't held, turn off drags */
+ if (!(buttons & (wimp_CLICK_SELECT | wimp_CLICK_ADJUST))) {
+ mouse_drag_select = false;
+ mouse_drag_adjust = false;
+ }
+
+ /* If there's a drag happening, set DRAG_ON and record which button
+ * the drag is happening with, i.e. HOLDING_1 or HOLDING_2 */
+ if (mouse_drag_select) {
+ state |= BROWSER_MOUSE_DRAG_ON | BROWSER_MOUSE_HOLDING_1;
+ }
+ if (mouse_drag_adjust) {
+ state |= BROWSER_MOUSE_DRAG_ON | BROWSER_MOUSE_HOLDING_2;
+ }
+
+ /* Set modifier key state */
+ if (ro_gui_shift_pressed()) state |= BROWSER_MOUSE_MOD_1;
+ if (ro_gui_ctrl_pressed()) state |= BROWSER_MOUSE_MOD_2;
+ if (ro_gui_alt_pressed()) state |= BROWSER_MOUSE_MOD_3;
+
+ return state;
+}
+
+
+/**
+ * Returns true iff one or more Shift keys is held down
+ */
+
+bool ro_gui_shift_pressed(void)
+{
+ int shift = 0;
+ xosbyte1(osbyte_SCAN_KEYBOARD, 0 ^ 0x80, 0, &shift);
+ return (shift == 0xff);
+}
+
+
+/**
+ * Returns true iff one or more Ctrl keys is held down
+ */
+
+bool ro_gui_ctrl_pressed(void)
+{
+ int ctrl = 0;
+ xosbyte1(osbyte_SCAN_KEYBOARD, 1 ^ 0x80, 0, &ctrl);
+ return (ctrl == 0xff);
+}
+
+
+/**
+ * Returns true iff one or more Alt keys is held down
+ */
+
+bool ro_gui_alt_pressed(void)
+{
+ int alt = 0;
+ xosbyte1(osbyte_SCAN_KEYBOARD, 2 ^ 0x80, 0, &alt);
+ return (alt == 0xff);
+}
+
+static struct gui_window_table window_table = {
+ .create = gui_window_create,
+ .destroy = gui_window_destroy,
+ .redraw = gui_window_redraw_window,
+ .update = gui_window_update_box,
+ .get_scroll = gui_window_get_scroll,
+ .set_scroll = gui_window_set_scroll,
+ .get_dimensions = gui_window_get_dimensions,
+ .update_extent = gui_window_update_extent,
+ .reformat = riscos_window_reformat,
+
+ .set_title = gui_window_set_title,
+ .set_url = ro_gui_window_set_url,
+ .set_icon = gui_window_set_icon,
+ .set_status = riscos_window_set_status,
+ .set_pointer = gui_window_set_pointer,
+ .place_caret = gui_window_place_caret,
+ .remove_caret = gui_window_remove_caret,
+ .save_link = gui_window_save_link,
+ .drag_start = gui_window_drag_start,
+ .scroll_visible = gui_window_scroll_visible,
+ .scroll_start = gui_window_scroll_start,
+ .new_content = gui_window_new_content,
+ .start_throbber = gui_window_start_throbber,
+ .stop_throbber = gui_window_stop_throbber,
+ .create_form_select_menu = gui_window_create_form_select_menu,
+
+ /* from save */
+ .drag_save_object = gui_drag_save_object,
+ .drag_save_selection =gui_drag_save_selection,
+
+ /* from textselection */
+ .start_selection = gui_start_selection,
+};
+
+struct gui_window_table *riscos_window_table = &window_table;
diff --git a/frontends/riscos/window.h b/frontends/riscos/window.h
new file mode 100644
index 000000000..2e6f6e9aa
--- /dev/null
+++ b/frontends/riscos/window.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2010, 2011 Stephen Fryatt <stevef@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Browser window handling (interface).
+ */
+
+#include <stdbool.h>
+
+#ifndef _NETSURF_RISCOS_WINDOW_H_
+#define _NETSURF_RISCOS_WINDOW_H_
+
+struct gui_window;
+struct nsurl;
+
+extern struct gui_window_table *riscos_window_table;
+
+void ro_gui_window_initialise(void);
+
+bool ro_gui_window_check_menu(wimp_menu *menu);
+
+/**
+ * Set the contents of a window's address bar.
+ *
+ * \param g gui_window to update
+ * \param url new url for address bar
+ */
+nserror ro_gui_window_set_url(struct gui_window *g, struct nsurl *url);
+
+#endif
+