summaryrefslogtreecommitdiff
path: root/frontends/atari
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/atari
parent2cbb337756d9af5bda4d594964d446439f602551 (diff)
downloadnetsurf-d21447d096a320a08b3efb2b8768fad0dcdcfd64.tar.gz
netsurf-d21447d096a320a08b3efb2b8768fad0dcdcfd64.tar.bz2
move frontends into sub directory
Diffstat (limited to 'frontends/atari')
-rw-r--r--frontends/atari/Makefile208
-rw-r--r--frontends/atari/Makefile.defaults58
-rw-r--r--frontends/atari/about.c206
-rw-r--r--frontends/atari/about.h24
-rw-r--r--frontends/atari/bitmap.c455
-rw-r--r--frontends/atari/bitmap.h137
-rw-r--r--frontends/atari/certview.c296
-rw-r--r--frontends/atari/certview.h51
-rw-r--r--frontends/atari/clipboard.c88
-rw-r--r--frontends/atari/clipboard.h25
-rw-r--r--frontends/atari/cookies.c220
-rw-r--r--frontends/atari/cookies.h39
-rw-r--r--frontends/atari/ctxmenu.c321
-rw-r--r--frontends/atari/ctxmenu.h24
-rw-r--r--frontends/atari/deskmenu.c828
-rw-r--r--frontends/atari/deskmenu.h11
-rwxr-xr-xfrontends/atari/doc/DejaVu.txt99
-rwxr-xr-xfrontends/atari/doc/bugs4
-rwxr-xr-xfrontends/atari/doc/changes.txt53
-rwxr-xr-xfrontends/atari/doc/faq.txt74
-rwxr-xr-xfrontends/atari/doc/readme.txt125
-rwxr-xr-xfrontends/atari/doc/todo.txt18
-rw-r--r--frontends/atari/download.c453
-rw-r--r--frontends/atari/download.h63
-rw-r--r--frontends/atari/encoding.c81
-rw-r--r--frontends/atari/encoding.h35
-rwxr-xr-xfrontends/atari/extract.php10
-rw-r--r--frontends/atari/file.c294
-rw-r--r--frontends/atari/file.h27
-rw-r--r--frontends/atari/filetype.c91
-rw-r--r--frontends/atari/filetype.h24
-rw-r--r--frontends/atari/findfile.c144
-rw-r--r--frontends/atari/findfile.h26
-rw-r--r--frontends/atari/font.c156
-rw-r--r--frontends/atari/font.h25
-rw-r--r--frontends/atari/gemtk/aestabs.c191
-rw-r--r--frontends/atari/gemtk/aestabs.h56
-rwxr-xr-xfrontends/atari/gemtk/dragdrop.c515
-rwxr-xr-xfrontends/atari/gemtk/dragdrop.h4
-rw-r--r--frontends/atari/gemtk/gemtk.h298
-rw-r--r--frontends/atari/gemtk/guiwin.c1430
-rw-r--r--frontends/atari/gemtk/guiwin.h4
-rw-r--r--frontends/atari/gemtk/msgbox.c110
-rw-r--r--frontends/atari/gemtk/msgbox.h5
-rw-r--r--frontends/atari/gemtk/objc.c522
-rw-r--r--frontends/atari/gemtk/objc.h7
-rw-r--r--frontends/atari/gemtk/redrawslots.c123
-rw-r--r--frontends/atari/gemtk/redrawslots.h25
-rw-r--r--frontends/atari/gemtk/utils.c144
-rw-r--r--frontends/atari/gemtk/utils.h5
-rw-r--r--frontends/atari/gemtk/vaproto.c170
-rw-r--r--frontends/atari/gemtk/vaproto.h121
-rw-r--r--frontends/atari/gui.c1217
-rw-r--r--frontends/atari/gui.h183
-rw-r--r--frontends/atari/history.c191
-rw-r--r--frontends/atari/history.h39
-rw-r--r--frontends/atari/hotlist.c315
-rw-r--r--frontends/atari/hotlist.h52
-rw-r--r--frontends/atari/login.c71
-rw-r--r--frontends/atari/login.h26
-rw-r--r--frontends/atari/misc.c408
-rw-r--r--frontends/atari/misc.h106
-rw-r--r--frontends/atari/options.h48
-rw-r--r--frontends/atari/osspec.c132
-rw-r--r--frontends/atari/osspec.h45
-rw-r--r--frontends/atari/plot/eddi.h54
-rw-r--r--frontends/atari/plot/eddi.s42
-rw-r--r--frontends/atari/plot/font_freetype.c714
-rw-r--r--frontends/atari/plot/font_freetype.h52
-rw-r--r--frontends/atari/plot/font_internal.c2386
-rw-r--r--frontends/atari/plot/font_internal.h37
-rw-r--r--frontends/atari/plot/font_vdi.c310
-rw-r--r--frontends/atari/plot/font_vdi.h26
-rw-r--r--frontends/atari/plot/fontplot.c132
-rw-r--r--frontends/atari/plot/fontplot.h86
-rw-r--r--frontends/atari/plot/plot.c2247
-rw-r--r--frontends/atari/plot/plot.h158
-rw-r--r--frontends/atari/redrawslots.c125
-rw-r--r--frontends/atari/redrawslots.h54
-rw-r--r--frontends/atari/res/blank39
-rw-r--r--frontends/atari/res/favicon.icobin0 -> 9862 bytes
-rw-r--r--frontends/atari/res/icons/toolbar/atfact/main.pngbin0 -> 12555 bytes
-rw-r--r--frontends/atari/res/icons/toolbar/atfact/throbber.pngbin0 -> 6135 bytes
-rw-r--r--frontends/atari/res/icons/toolbar/default/main.pngbin0 -> 46417 bytes
-rw-r--r--frontends/atari/res/icons/toolbar/default/main.xcfbin0 -> 16404 bytes
-rw-r--r--frontends/atari/res/icons/toolbar/default/throbber.pngbin0 -> 20960 bytes
-rw-r--r--frontends/atari/res/icons/toolbar/default/throbber.xcfbin0 -> 10231 bytes
-rw-r--r--frontends/atari/res/languages261
-rwxr-xr-xfrontends/atari/res/netsurf.rscbin0 -> 38896 bytes
-rwxr-xr-xfrontends/atari/res/netsurf.rsh241
-rwxr-xr-xfrontends/atari/res/netsurf.rsm225
-rw-r--r--frontends/atari/rootwin.c1540
-rw-r--r--frontends/atari/rootwin.h97
-rw-r--r--frontends/atari/save.h22
-rw-r--r--frontends/atari/schedule.c228
-rw-r--r--frontends/atari/schedule.h48
-rwxr-xr-xfrontends/atari/scripts/env-v4e.sh7
-rwxr-xr-xfrontends/atari/scripts/env-x86.sh9
-rw-r--r--frontends/atari/search.c303
-rw-r--r--frontends/atari/search.h53
-rw-r--r--frontends/atari/settings.c990
-rw-r--r--frontends/atari/settings.h26
-rw-r--r--frontends/atari/statusbar.c232
-rw-r--r--frontends/atari/statusbar.h40
-rw-r--r--frontends/atari/toolbar.c1041
-rw-r--r--frontends/atari/toolbar.h96
-rw-r--r--frontends/atari/treeview.c794
-rw-r--r--frontends/atari/treeview.h124
-rw-r--r--frontends/atari/verify_ssl.c269
-rw-r--r--frontends/atari/verify_ssl.h24
110 files changed, 24488 insertions, 0 deletions
diff --git a/frontends/atari/Makefile b/frontends/atari/Makefile
new file mode 100644
index 000000000..60b7f879c
--- /dev/null
+++ b/frontends/atari/Makefile
@@ -0,0 +1,208 @@
+# ----------------------------------------------------------------------------
+# Atari target setup
+# ----------------------------------------------------------------------------
+
+# !!!IMPORTANT!!!
+# On regular m68k-atari-mint installation, these must be set
+# manually via env. variables, because the m68k-atari-mint
+# toolchain is located in /usr/bin and the wildcard matching
+# fails then. So this wildcard matches only works for
+# the netsurf environment!
+STRIP := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*strip)
+STACK := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*stack)
+FT2CF := $(GCCSDK_INSTALL_ENV)/bin/freetype-config
+
+ifeq ($(ATARIARCH),68000)
+PRGSUFFIX := 000.app
+PKGNAME := ns000.zip
+endif
+
+ifeq ($(ATARIARCH),68020-60)
+CFLAGS += -m68020-60
+LDFLAGS += -m68020-60
+PRGSUFFIX := 020.app
+PKGNAME := ns020.zip
+endif
+
+ifeq ($(ATARIARCH),v4e)
+CFLAGS += -mcpu=5475
+LDFLAGS += -mcpu=5475
+PRGSUFFIX := v4e.app
+PKGNAME := nsv4e.zip
+endif
+
+# non-pkgconfig components
+
+FREETYPE_FONT_CFLAGS := $(shell $(FT2CF) --cflags) -DWITH_FREETYPE_FONT_DRIVER
+SPIDERMONKEY_CFLAGS := -DXP_UNIX -DJS_HAS_FILE_OBJECT=0 -DJSOPTION_JIT=0 -DPOSIX_SOURCE -D_BSD_SOURCE
+
+$(eval $(call feature_enabled,ATARI_FREETYPE_FONT,$(FREETYPE_FONT_CFLAGS),-lfreetype,(Freetype)))
+$(eval $(call feature_enabled,ATARI_NETSURF_FONT,-DWITH_INTERNAL_FONT_DRIVER,,(Internal Font)))
+$(eval $(call feature_enabled,ATARI_VDI_FONT,-DWITH_VDI_FONT_DRIVER,,(VDI Font)))
+$(eval $(call feature_enabled,ATARI_8BPP_SUPPORT,-DWITH_8BPP_SUPPORT,,(Indexed screen format support)))
+
+$(eval $(call pkg_config_find_and_add,libcares,Cares))
+
+CFLAGS += -U__STRICT_ANSI__ -std=c99 -Dsmall -Dnsatari \
+ -D_BSD_SOURCE \
+ -D_XOPEN_SOURCE=600 \
+ -D_POSIX_C_SOURCE=200112L \
+ $(shell $(PKG_CONFIG) --cflags openssl ) \
+ $(shell $(PKG_CONFIG) --cflags libcurl )
+
+LDFLAGS += -lcflib -lcurl
+LDFLAGS += -lssl -lcrypto
+LDFLAGS += -lz -lHermes -lgem -lm
+LDFLAGS += -L$(GCCSDK_INSTALL_ENV)/lib
+
+
+# sources purely for the Atari FreeMiNT build
+S_FRONTEND := \
+ about.c \
+ bitmap.c \
+ clipboard.c \
+ ctxmenu.c \
+ cookies.c \
+ certview.c \
+ deskmenu.c \
+ download.c \
+ encoding.c \
+ file.c \
+ findfile.c \
+ filetype.c \
+ font.c \
+ gui.c \
+ hotlist.c \
+ history.c \
+ login.c \
+ misc.c \
+ osspec.c \
+ redrawslots.c \
+ rootwin.c \
+ schedule.c \
+ search.c \
+ statusbar.c \
+ settings.c \
+ toolbar.c \
+ treeview.c \
+ plot/plot.c \
+ plot/fontplot.c \
+ plot/eddi.s \
+ plot/font_freetype.c \
+ plot/font_internal.c \
+ plot/font_vdi.c \
+ gemtk/aestabs.c \
+ gemtk/dragdrop.c \
+ gemtk/guiwin.c \
+ gemtk/msgbox.c \
+ gemtk/utils.c \
+ gemtk/objc.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 := ns$(SUBTARGET)$(PRGSUFFIX)
+
+# ----------------------------------------------------------------------------
+# Install target
+# ----------------------------------------------------------------------------
+
+ATARI_TARGET_DIR := netsurf/
+ATARI_RES_DIR := $(FRONTEND_RESOURCES_DIR)/
+ATARI_DOC_DIR := $(FRONTEND_SOURCE_DIR)/doc/
+ATARI_FONT_NAME := ttf-bitstream-vera-1.10
+ATARI_FONT_SOURCE_URL := http://ftp.gnome.org/pub/GNOME/sources/ttf-bitstream-vera/1.10/$(ATARI_FONT_NAME).tar.gz
+#ATARI_FONT_SOURCE_URL := http://localhost/$(ATARI_FONT_NAME).tar.gz
+ATARI_FONT_TMP_DIR := $(DEPROOT)/../
+ATARI_FONT_SOURCE_DIR := $(ATARI_FONT_TMP_DIR)$(ATARI_FONT_NAME)/
+ATARI_GENERIC_RESOURCES := de en it ja
+ATARI_RESOURCES := $(addprefix \!NetSurf/Resources/,$(ATARI_GENERIC_RESOURCES))
+
+# ----------------------------------------------------------------------------
+# Install target
+# ----------------------------------------------------------------------------
+
+install-atari:
+
+# ----------------------------------------------------------------------------
+# Package target
+# ----------------------------------------------------------------------------
+
+$(ATARI_FONT_TMP_DIR)$(ATARI_FONT_NAME):
+ $(Q)wget $(ATARI_FONT_SOURCE_URL) -O $(ATARI_FONT_TMP_DIR)$(ATARI_FONT_NAME).tar.gz
+ tar xfz $(ATARI_FONT_TMP_DIR)/$(ATARI_FONT_NAME).tar.gz -C $(ATARI_FONT_TMP_DIR)
+
+package-atari: $(ATARI_FONT_TMP_DIR)$(ATARI_FONT_NAME) $(PKGNAME)
+ $(VQ)echo Creating $(PKGNAME)
+
+$(PKGNAME): $(EXETARGET)
+ifneq ($(strip $(STRIP)),)
+ $(Q)echo Stripping symbols from $(EXETARGET) with $(STRIP)
+ $(Q)$(STRIP) $(EXETARGET)
+endif
+ifneq ($(strip $(STACK)),)
+ $(Q)$(STACK) -S 256k $(EXETARGET)
+endif
+ $(Q)rm -rf $(ATARI_TARGET_DIR)
+ $(Q)rm -rf $(PKGNAME)
+ $(Q)mkdir $(ATARI_TARGET_DIR)
+ $(Q)mkdir $(ATARI_TARGET_DIR)doc
+ $(Q)mkdir $(ATARI_TARGET_DIR)downloads
+ $(Q)mkdir $(ATARI_TARGET_DIR)res
+ $(Q)mkdir $(ATARI_TARGET_DIR)res/fonts
+ $(Q)mkdir $(ATARI_TARGET_DIR)res/icons
+ $(Q)mkdir $(ATARI_TARGET_DIR)res/cache
+ $(Q)touch $(ATARI_TARGET_DIR)cookies
+ $(Q)touch $(ATARI_TARGET_DIR)url.db
+
+ $(Q)cp $(ATARI_DOC_DIR)bugs $(ATARI_TARGET_DIR)doc/
+ $(Q)cp $(ATARI_DOC_DIR)faq.txt $(ATARI_TARGET_DIR)doc/
+ $(Q)cp $(ATARI_DOC_DIR)readme.txt $(ATARI_TARGET_DIR)doc/
+ $(Q)cp $(ATARI_DOC_DIR)todo.txt $(ATARI_TARGET_DIR)doc/
+
+# GUI resources:
+ $(Q)cp -r $(ATARI_RESOURCES) $(ATARI_TARGET_DIR)res/
+ $(Q)cp $(ATARI_RES_DIR)/netsurf.rsc $(ATARI_TARGET_DIR)res/netsurf.rsc
+ $(Q)cp $(ATARI_RES_DIR)/languages $(ATARI_TARGET_DIR)res/languages
+ $(Q)cp $(ATARI_RES_DIR)/icons/toolbar -R $(ATARI_TARGET_DIR)res/icons
+ $(Q)cp \!NetSurf/Resources/Icons/* -R $(ATARI_TARGET_DIR)res/icons/
+
+ $(Q)cp \!NetSurf/Resources/netsurf.png,b60 $(ATARI_TARGET_DIR)res/netsurf.png
+ $(Q)cp \!NetSurf/Resources/AdBlock,f79 $(ATARI_TARGET_DIR)res/adblock.css
+ $(Q)cp \!NetSurf/Resources/CSS,f79 $(ATARI_TARGET_DIR)res/default.css
+ $(Q)cp \!NetSurf/Resources/Quirks,f79 $(ATARI_TARGET_DIR)res/quirks.css
+ $(Q)cp \!NetSurf/Resources/internal.css,f79 $(ATARI_TARGET_DIR)res/internal.css
+ $(Q)cp \!NetSurf/Resources/SearchEngines $(ATARI_TARGET_DIR)res/search
+ $(Q)cp \!NetSurf/Resources/ca-bundle $(ATARI_TARGET_DIR)res/cabundle
+ $(Q)cp \!NetSurf/Resources/ca-bundle $(ATARI_TARGET_DIR)res/cabundle
+ $(Q)$(SPLIT_MESSAGES) -l en -p atari -f messages resources/FatMessages > $(ATARI_TARGET_DIR)res/messages
+ $(Q)cp \!NetSurf/Resources/en/welcome.html,faf $(ATARI_TARGET_DIR)res/welcome.html
+ $(Q)cp \!NetSurf/Resources/en/maps.html,faf $(ATARI_TARGET_DIR)res/maps.html
+ $(Q)cp \!NetSurf/Resources/en/licence.html,faf $(ATARI_TARGET_DIR)res/licence.html
+ $(Q)cp \!NetSurf/Resources/en/credits.html,faf $(ATARI_TARGET_DIR)res/credits.html
+
+# copy "Bitstream Vera" font:
+ $(Q)cp $(ATARI_FONT_SOURCE_DIR)RELEASENOTES.TXT $(ATARI_TARGET_DIR)res/fonts/
+ $(Q)cp $(ATARI_FONT_SOURCE_DIR)README.TXT $(ATARI_TARGET_DIR)res/fonts/
+ $(Q)cp $(ATARI_FONT_SOURCE_DIR)COPYRIGHT.TXT $(ATARI_TARGET_DIR)res/fonts/
+
+ $(Q)cp $(ATARI_FONT_SOURCE_DIR)Vera.ttf $(ATARI_TARGET_DIR)res/fonts/ss.ttf
+ $(Q)cp $(ATARI_FONT_SOURCE_DIR)VeraBd.ttf $(ATARI_TARGET_DIR)res/fonts/ssb.ttf
+ $(Q)cp $(ATARI_FONT_SOURCE_DIR)VeraIt.ttf $(ATARI_TARGET_DIR)res/fonts/ssi.ttf
+ $(Q)cp $(ATARI_FONT_SOURCE_DIR)VeraBI.ttf $(ATARI_TARGET_DIR)res/fonts/ssib.ttf
+ $(Q)cp $(ATARI_FONT_SOURCE_DIR)VeraSe.ttf $(ATARI_TARGET_DIR)res/fonts/s.ttf
+ $(Q)cp $(ATARI_FONT_SOURCE_DIR)VeraSeBd.ttf $(ATARI_TARGET_DIR)res/fonts/sb.ttf
+ $(Q)cp $(ATARI_FONT_SOURCE_DIR)VeraMono.ttf $(ATARI_TARGET_DIR)res/fonts/mono.ttf
+ $(Q)cp $(ATARI_FONT_SOURCE_DIR)VeraMoBd.ttf $(ATARI_TARGET_DIR)res/fonts/monob.ttf
+ $(Q)cp $(ATARI_FONT_SOURCE_DIR)VeraMoIt.ttf $(ATARI_TARGET_DIR)res/fonts/cursive.ttf
+ $(Q)cp $(ATARI_FONT_SOURCE_DIR)VeraMoBI.ttf $(ATARI_TARGET_DIR)res/fonts/fantasy.ttf
+
+ $(Q)cp $(EXETARGET) $(ATARI_TARGET_DIR)$(EXETARGET)
+
+# zip files
+ $(Q)zip $(PKGNAME) -9 -r ./$(ATARI_TARGET_DIR)
+
+# delete temporary folders
+ $(Q)rm -rf $(ATARI_TARGET_DIR)
diff --git a/frontends/atari/Makefile.defaults b/frontends/atari/Makefile.defaults
new file mode 100644
index 000000000..b738b48a2
--- /dev/null
+++ b/frontends/atari/Makefile.defaults
@@ -0,0 +1,58 @@
+# ----------------------------------------------------------------------------
+# Atari-specific options
+# ----------------------------------------------------------------------------
+
+# Force using glibc internal iconv implementation instead of external libiconv
+# Valid options: YES, NO
+NETSURF_USE_LIBICONV_PLUG := NO
+
+# 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 librsvg in conjunction with Cairo to display SVGs
+# Valid options: YES, NO, AUTO
+NETSURF_USE_RSVG := AUTO
+
+# Enable NetSurf's use of libsvgtiny for displaying SVGs
+# Valid options: YES, NO, AUTO
+NETSURF_USE_NSSVG := AUTO
+
+# Enable Spidermonkey JavaScript engine
+# Valid options: YES, NO
+NETSURF_USE_MOZJS := NO
+
+# Enable building the source object cache filesystem based backing store.
+# implementation.
+# Valid options: YES, NO
+NETSURF_FS_BACKING_STORE := YES
+
+# enable true type fonts via freetype2
+# Valid options: YES, NO
+NETSURF_USE_ATARI_FREETYPE_FONT := YES
+
+# Enable use of netsurf embedded font
+# Valid options: YES, NO
+NETSURF_USE_ATARI_NETSURF_FONT := YES
+
+# Enable VDI Font rendering
+# Valid options: YES, NO
+NETSURF_USE_ATARI_VDI_FONT := NO
+
+# Configure support for screen drivers with no true colour mode
+# Valid options: YES, NO
+NETSURF_USE_ATARI_8BPP_SUPPORT := NO
+
+# Configure the CPU target
+# Valid options: 68000, 68020-60, 5475 (coldfire)
+ATARIARCH = 68020-60
+
+# enable optimizations
+# -O2 is currently broken with m68000 / m68020-60 builds
+CFLAGS += -O3
+
+# override warning flags removing -Wall
+WARNFLAGS = -W -Wundef -Wpointer-arith \
+ -Wcast-align -Wwrite-strings -Wstrict-prototypes \
+ -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls \
+ -Wnested-externs -Wuninitialized -Wl,-t
diff --git a/frontends/atari/about.c b/frontends/atari/about.c
new file mode 100644
index 000000000..105037aab
--- /dev/null
+++ b/frontends/atari/about.c
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2013 Ole Loots <ole@monochrom.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 <limits.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "testament.h"
+#include "utils/useragent.h"
+#include "utils/nsurl.h"
+#include "utils/messages.h"
+#include "desktop/version.h"
+#include "desktop/browser.h"
+
+#include "curl/curlver.h"
+
+#include "cflib.h"
+#include "atari/gui.h"
+#include "atari/misc.h"
+#include "atari/plot/plot.h"
+#include "atari/gemtk/gemtk.h"
+#include "atari/res/netsurf.rsh"
+#include "atari/about.h"
+
+static OBJECT * about_form = NULL;
+static char * infocontent;
+static char version[32];
+VdiHdl vdihandle;
+
+static short __CDECL about_userdraw(PARMBLK *parmblock)
+{
+ short pxy[8];
+ short dummy;
+ short cheight = 8, cwidth = gl_wchar;
+ char c[2] = {0,0};
+
+ /* Setup area to the full area...: */
+ GRECT area = {
+ .g_x = parmblock->pb_x,
+ .g_y = parmblock->pb_y,
+ .g_w = parmblock->pb_w-8,
+ .g_h = parmblock->pb_h
+ };
+
+ /* Setup clip: */
+ GRECT clip = {
+ .g_x = parmblock->pb_xc,
+ .g_y = parmblock->pb_yc,
+ .g_w = parmblock->pb_wc,
+ .g_h = parmblock->pb_hc
+ };
+
+ if(parmblock->pb_currstate == parmblock->pb_prevstate){
+ short cur_x, cur_y;
+ char *content;
+ int content_len;
+
+ content = (char*)parmblock->pb_parm;
+ content_len = strlen(content);
+ cur_x = area.g_x;
+ cur_y = area.g_y;
+
+
+ if(!rc_intersect(&area, &clip)){
+ return (0);
+ }
+
+ pxy[0] = clip.g_x;
+ pxy[1] = clip.g_y;
+ pxy[2] = pxy[0] + clip.g_w-1;
+ pxy[3] = pxy[1] + clip.g_h-1;
+ vs_clip(vdihandle, 1, pxy);
+ vst_alignment(vdihandle, 0, 5, &dummy, &dummy);
+ vst_height(vdihandle, sys_sml_height, &dummy, &dummy, &dummy, &cheight);
+ vswr_mode(vdihandle, 2);
+
+ for (int i=0; i<content_len; i++) {
+ if (content[i] == '\n') {
+ cur_y += cheight;
+ cur_x = area.g_x;
+ } else {
+ if (cur_x >= clip.g_x
+ && cur_x < (clip.g_x + clip.g_w)
+ && cur_y > clip.g_y
+ && cur_y < (clip.g_w + clip.g_h)) {
+ c[0] = content[i];
+ v_gtext(vdihandle, cur_x, cur_y, c);
+ }
+ cur_x += cwidth;
+ }
+ }
+
+ vs_clip(vdihandle, 0, pxy);
+ }
+ return(0);
+}
+
+void atari_about_show(void)
+{
+ static USERBLK userblk;
+ short elem = 0;
+ const char * goto_url = NULL;
+ nserror nserr;
+ nsurl *url;
+
+ vdihandle = plot_get_vdi_handle();
+
+ infocontent = malloc(8000);
+ memset(infocontent, 0, 8000);
+
+ snprintf(infocontent, 8000,
+ "Netsurf : %s\n"
+ "Build ID : %s\n"
+ "Date : %s\n"
+ "MiNTLib : %d.%d-%d%s\n"
+ "GEMLib : %d.%d-%d%s\n"
+ "CFLib : %d.%d-%d%s\n"
+ "cURL : %s\n",
+ user_agent_string(),
+ WT_REVID,
+ WT_COMPILEDATE,
+ __MINTLIB_MAJOR__, __MINTLIB_MINOR__, __MINTLIB_REVISION__,
+ __MINTLIB_BETATAG__,
+ __GEMLIB_MAJOR__, __GEMLIB_MINOR__, __GEMLIB_REVISION__,
+ __GEMLIB_BETATAG__,
+ __CFLIB_MAJOR__, __CFLIB_MINOR__, __CFLIB_REVISION__,
+ __CFLIB_BETATAG__,
+ LIBCURL_VERSION);
+
+ about_form = gemtk_obj_get_tree(ABOUT);
+ snprintf(version, 32, "%s%s", "NetSurf ", (char*)netsurf_version);
+ set_string(about_form, ABOUT_LBL_VERSION, version);
+
+ userblk.ub_code = about_userdraw;
+ userblk.ub_parm = (long) infocontent;
+ about_form[ABOUT_CONTENT].ob_spec.userblk = &userblk;
+
+ elem = simple_dial(about_form, 0);
+ switch (elem) {
+ case ABOUT_CREDITS:
+ goto_url = "about:credits";
+ break;
+
+ case ABOUT_LICENSE:
+ goto_url = "about:licence";
+ break;
+ };
+
+ free(infocontent);
+
+ if (goto_url != NULL) {
+ nserr = nsurl_create(goto_url, &url);
+ if (nserr == NSERROR_OK) {
+ nserr = browser_window_create(BW_CREATE_HISTORY,
+ url,
+ NULL,
+ NULL,
+ NULL);
+ nsurl_unref(url);
+ }
+ if (nserr != NSERROR_OK) {
+ atari_warn_user(messages_get_errorcode(nserr), 0);
+ }
+ }
+/*
+ dlg = open_mdial(about_form, 0);
+ do {
+ elem = do_mdial(dlg);
+ printf ("elem: %d\n", elem);
+ switch (elem) {
+ case ABOUT_OK:
+ close_dlg = true;
+ break;
+
+ case ABOUT_CREDITS:
+ close_dlg = true;
+ break;
+
+ case ABOUT_LICENSE:
+ close_dlg = true;
+ break;
+ }
+ } while (close_dlg == false);
+
+ close_mdial(dlg);
+*/
+
+}
diff --git a/frontends/atari/about.h b/frontends/atari/about.h
new file mode 100644
index 000000000..dff6eaeee
--- /dev/null
+++ b/frontends/atari/about.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2013 Ole Loots <ole@monochrom.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 NS_ATARI_ABOUT_H_INCLUDED
+#define NS_ATARI_ABOUT_H_INCLUDED
+
+void atari_about_show(void);
+
+#endif // NS_ATARI_ABOUT_H_INCLUDED
diff --git a/frontends/atari/bitmap.c b/frontends/atari/bitmap.c
new file mode 100644
index 000000000..a159a6659
--- /dev/null
+++ b/frontends/atari/bitmap.c
@@ -0,0 +1,455 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.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 <inttypes.h>
+#include <sys/types.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "utils/nsoption.h"
+#include "utils/log.h"
+#include "image/bitmap.h"
+#include "desktop/mouse.h"
+
+#include "atari/bitmap.h"
+#include "atari/plot/plot.h"
+
+
+/*
+ * param bpp bits per pixel,
+ * param w width of the buffer (in pixel)
+ * param h height of the buffer (in pixel)
+ * param flags MFDB_FLAG_NOALLOC | MFDB_FLAG_ZEROMEM | MFDB_FLAG_STAND
+ * returns size of the fd_addr buffer required or allocated
+*/
+int init_mfdb(int bpp, int w, int h, uint32_t flags, MFDB * out )
+{
+ int dststride;
+ dststride = MFDB_STRIDE( w );
+ int size = MFDB_SIZE( bpp, dststride, h );
+ if( bpp > 0 ) {
+ if( (flags & MFDB_FLAG_NOALLOC) == 0 ) {
+ out->fd_addr = malloc( size );
+ if( out->fd_addr == NULL ){
+ return( 0 );
+ }
+ if( (flags & MFDB_FLAG_ZEROMEM) ){
+ memset( out->fd_addr, 0, size );
+ }
+ }
+ out->fd_stand = (flags & MFDB_FLAG_STAND) ? 1 : 0;
+ out->fd_nplanes = (short)bpp;
+ out->fd_r1 = out->fd_r2 = out->fd_r3 = 0;
+ } else {
+ memset( out, 0, sizeof(MFDB) );
+ }
+ out->fd_w = dststride;
+ out->fd_h = h;
+ out->fd_wdwidth = dststride >> 4;
+ return( size );
+}
+
+
+/**
+ * Create a bitmap.
+ *
+ * \param w width of image in pixels
+ * \param h height of image in pixels
+ * \param bpp number of BYTES per pixel
+ * \param rowstride linewidth in bytes
+ * \param state a flag word indicating the initial state
+ * \param pixdata NULL or an memory address to use as the bitmap pixdata
+ * \return an opaque struct bitmap, or NULL on memory exhaustion
+ */
+static void *atari_bitmap_create_ex( int w, int h, short bpp, int rowstride, unsigned int state, void * pixdata )
+{
+ struct bitmap * bitmap;
+
+ LOG("width %d (rowstride: %d, bpp: %d), height %d, state %u", w, rowstride, bpp, h, state);
+
+ if( rowstride == 0) {
+ rowstride = bpp * w;
+ }
+
+ assert( rowstride >= (w * bpp) );
+ bitmap = calloc(1 , sizeof(struct bitmap) );
+ if (bitmap) {
+ if( pixdata == NULL) {
+ bitmap->pixdata = calloc(1, (rowstride * h)+128);
+ }
+ else {
+ bitmap->pixdata = pixdata;
+ }
+
+ if (bitmap->pixdata != NULL) {
+ bitmap->width = w;
+ bitmap->height = h;
+ bitmap->opaque = (state & BITMAP_OPAQUE) ? true : false;
+ bitmap->bpp = bpp;
+ bitmap->resized = NULL;
+ bitmap->rowstride = rowstride;
+ } else {
+ free(bitmap);
+ bitmap=NULL;
+ LOG("Out of memory!");
+ }
+ }
+ LOG("bitmap %p", bitmap);
+ return bitmap;
+}
+
+
+/* exported interface documented in atari/bitmap.h */
+void *atari_bitmap_create(int w, int h, unsigned int state)
+{
+ return atari_bitmap_create_ex( w, h, NS_BMP_DEFAULT_BPP, w * NS_BMP_DEFAULT_BPP, state, NULL );
+}
+
+/**
+ * The bitmap image has changed, so flush any persistant cache.
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ */
+static void bitmap_modified(void *bitmap)
+{
+ struct bitmap *bm = bitmap;
+ if( bm->resized != NULL ) {
+ atari_bitmap_destroy( bm->resized );
+ bm->resized = NULL;
+ }
+ if( bm->converted ){
+ if( bm->pixdata != bm->native.fd_addr ){
+ free( bm->native.fd_addr );
+ }
+ bm->native.fd_addr = NULL;
+ bm->converted = false;
+ }
+}
+
+
+/* exported interface documented in atari/bitmap.h */
+void *atari_bitmap_realloc( int w, int h, short bpp, int rowstride, unsigned int state, void * bmp )
+{
+ struct bitmap * bitmap = bmp;
+ int newsize = rowstride * h;
+
+ if( bitmap == NULL ) {
+ return( NULL );
+ }
+
+ assert( bitmap->pixdata != NULL );
+ int oldsize = bitmap->rowstride * bitmap->height;
+ bool doalloc = (state & BITMAP_GROW) ? (newsize > oldsize) : (newsize != oldsize);
+ if( newsize > oldsize )
+ assert( doalloc == true );
+ if( doalloc ) {
+ // TODO: set red band to a specific value and check the red band
+ // on bitmap_destroy()
+ bitmap->pixdata = realloc( bitmap->pixdata, newsize + 128 );
+ if( bitmap->pixdata == NULL )
+ return( NULL );
+ }
+
+ if( state & BITMAP_CLEAR ){
+ memset( bitmap->pixdata, 0x00, newsize + 128 );
+ }
+
+ bitmap->width = w;
+ bitmap->height = h;
+ bitmap->bpp = bpp;
+ bitmap->resized = NULL;
+ bitmap->rowstride = rowstride;
+ bitmap_modified( bitmap );
+ return( bitmap );
+}
+
+
+/**
+ * Return a pointer to the pixel data in a bitmap.
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ * \return pointer to the pixel buffer
+ *
+ * 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 bitmap_get_rowstride().
+ */
+static unsigned char *bitmap_get_buffer(void *bitmap)
+{
+ struct bitmap *bm = bitmap;
+
+ if (bitmap == NULL) {
+ LOG("NULL bitmap!");
+ return NULL;
+ }
+
+ return bm->pixdata;
+}
+
+
+/* exported interface documented in atari/bitmap.h */
+size_t atari_bitmap_buffer_size(void *bitmap)
+{
+ struct bitmap * bm = bitmap;
+ if( bm == NULL )
+ return 0;
+ return( bm->rowstride * bm->height );
+}
+
+
+/* exported interface documented in atari/bitmap.h */
+size_t atari_bitmap_get_rowstride(void *bitmap)
+{
+ struct bitmap *bm = bitmap;
+
+ if (bitmap == NULL) {
+ LOG("NULL bitmap!");
+ return 0;
+ }
+ return bm->rowstride;
+}
+
+
+/* exported interface documented in atari/bitmap.h */
+void atari_bitmap_destroy(void *bitmap)
+{
+ struct bitmap *bm = bitmap;
+
+ if (bitmap == NULL) {
+ LOG("NULL bitmap!");
+ return;
+ }
+
+ if( bm->resized != NULL ) {
+ atari_bitmap_destroy(bm->resized);
+ }
+ if( bm->converted && ( bm->native.fd_addr != bm->pixdata ) ) {
+ free( bm->native.fd_addr );
+ }
+ free(bm->pixdata);
+ free(bm);
+}
+
+
+/**
+ * Save a bitmap in the platform's native format.
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ * \param path pathname for file
+ * \param flags flags controlling how the bitmap is saved.
+ * \return true on success, false on error and error reported
+ */
+
+static bool bitmap_save(void *bitmap, const char *path, unsigned flags)
+{
+ return true;
+}
+
+
+/**
+ * Sets whether a bitmap should be plotted opaque
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ * \param opaque whether the bitmap should be plotted opaque
+ */
+static void bitmap_set_opaque(void *bitmap, bool opaque)
+{
+ struct bitmap *bm = bitmap;
+
+ if (bitmap == NULL) {
+ LOG("NULL bitmap!");
+ return;
+ }
+
+ LOG("setting bitmap %p to %s", bm, opaque ? "opaque" : "transparent");
+ bm->opaque = opaque;
+}
+
+
+/**
+ * Tests whether a bitmap has an opaque alpha channel
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ * \return whether the bitmap is opaque
+ */
+static bool bitmap_test_opaque(void *bitmap)
+{
+ int tst;
+ struct bitmap *bm = bitmap;
+
+ if (bitmap == NULL) {
+ LOG("NULL bitmap!");
+ return false;
+ }
+
+ if( nsoption_int(atari_transparency) == 0 ){
+ return( true );
+ }
+
+ tst = bm->width * bm->height;
+
+ while (tst-- > 0) {
+ if (bm->pixdata[(tst << 2) + 3] != 0xff) {
+ LOG("bitmap %p has transparency", bm);
+ return false;
+ }
+ }
+ LOG("bitmap %p is opaque", bm);
+ return true;
+}
+
+
+/* exported interface documented in atari/bitmap.h */
+bool atari_bitmap_get_opaque(void *bitmap)
+{
+ struct bitmap *bm = bitmap;
+
+ if (bitmap == NULL) {
+ LOG("NULL bitmap!");
+ return false;
+ }
+
+ return bm->opaque;
+}
+
+
+/* exported interface documented in atari/bitmap.h */
+int atari_bitmap_get_width(void *bitmap)
+{
+ struct bitmap *bm = bitmap;
+
+ if (bitmap == NULL) {
+ LOG("NULL bitmap!");
+ return 0;
+ }
+
+ return(bm->width);
+}
+
+
+/* exported interface documented in atari/bitmap.h */
+int atari_bitmap_get_height(void *bitmap)
+{
+ struct bitmap *bm = bitmap;
+
+ if (bitmap == NULL) {
+ LOG("NULL bitmap!");
+ return 0;
+ }
+ return(bm->height);
+}
+
+
+/**
+ * Gets the number of BYTES per pixel.
+ */
+static size_t bitmap_get_bpp(void *bitmap)
+{
+ struct bitmap *bm = bitmap;
+ return bm->bpp;
+}
+
+/* exported interface documented in atari/bitmap.h */
+bool atari_bitmap_resize(struct bitmap *img, HermesHandle hermes_h,
+ HermesFormat *fmt, int nw, int nh)
+{
+ unsigned int state = 0;
+ short bpp = bitmap_get_bpp( img );
+ int stride = atari_bitmap_get_rowstride( img );
+ int err;
+
+ if( img->resized != NULL ) {
+ if( img->resized->width != nw || img->resized->height != nh ) {
+ atari_bitmap_destroy( img->resized );
+ img->resized = NULL;
+ } else {
+ /* the bitmap is already resized */
+ return(true);
+ }
+ }
+
+ /* allocate the mem for resized bitmap */
+ if (img->opaque == true) {
+ state |= BITMAP_OPAQUE;
+ }
+ img->resized = atari_bitmap_create_ex( nw, nh, bpp, nw*bpp, state, NULL );
+ if( img->resized == NULL ) {
+ printf("W: %d, H: %d, bpp: %d\n", nw, nh, bpp);
+ assert(img->resized);
+ return(false);
+ }
+
+ /* allocate an converter, only for resizing */
+ err = Hermes_ConverterRequest( hermes_h,
+ fmt,
+ fmt
+ );
+ if( err == 0 ) {
+ return(false);
+ }
+
+ err = Hermes_ConverterCopy( hermes_h,
+ img->pixdata,
+ 0, /* x src coord of top left in pixel coords */
+ 0, /* y src coord of top left in pixel coords */
+ atari_bitmap_get_width( img ),
+ atari_bitmap_get_height( img ),
+ stride, /* stride as bytes */
+ img->resized->pixdata,
+ 0, /* x dst coord of top left in pixel coords */
+ 0, /* y dst coord of top left in pixel coords */
+ nw, nh,
+ atari_bitmap_get_rowstride(img->resized) /* stride as bytes */
+ );
+ if( err == 0 ) {
+ atari_bitmap_destroy( img->resized );
+ img->resized = NULL;
+ return(false);
+ }
+
+ return(true);
+}
+
+static nserror bitmap_render(struct bitmap *bitmap, struct hlcache_handle *content)
+{
+ return NSERROR_NOT_IMPLEMENTED;
+}
+
+static struct gui_bitmap_table bitmap_table = {
+ .create = atari_bitmap_create,
+ .destroy = atari_bitmap_destroy,
+ .set_opaque = bitmap_set_opaque,
+ .get_opaque = atari_bitmap_get_opaque,
+ .test_opaque = bitmap_test_opaque,
+ .get_buffer = bitmap_get_buffer,
+ .get_rowstride = atari_bitmap_get_rowstride,
+ .get_width = atari_bitmap_get_width,
+ .get_height = atari_bitmap_get_height,
+ .get_bpp = bitmap_get_bpp,
+ .save = bitmap_save,
+ .modified = bitmap_modified,
+ .render = bitmap_render,
+};
+
+struct gui_bitmap_table *atari_bitmap_table = &bitmap_table;
+
+/*
+ * Local Variables:
+ * c-basic-offset:8
+ * End:
+ */
diff --git a/frontends/atari/bitmap.h b/frontends/atari/bitmap.h
new file mode 100644
index 000000000..b0fa18069
--- /dev/null
+++ b/frontends/atari/bitmap.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.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
+ * Atari bitmap handling implementation.
+ */
+
+#ifndef NS_ATARI_BITMAP_H
+#define NS_ATARI_BITMAP_H
+
+#include <gem.h>
+#include <Hermes/Hermes.h>
+
+#define NS_BMP_DEFAULT_BPP 4
+
+/* Flags for init_mfdb function: */
+#define MFDB_FLAG_STAND 0x01
+#define MFDB_FLAG_ZEROMEM 0x02
+#define MFDB_FLAG_NOALLOC 0x04
+
+#define BITMAP_SHRINK 0
+#define BITMAP_GROW 1024 /* Don't realloc when bitmap size shrinks */
+#define BITMAP_CLEAR 2048 /* Zero bitmap memory */
+
+
+/**
+ * Calculates MFDB compatible rowstride (in number of bits)
+ */
+#define MFDB_STRIDE( w ) (((w & 15) != 0) ? (w | 15)+1 : w)
+
+
+/**
+ * Calculate size of an mfdb,
+ *
+ * \param bpp Bits per pixel.
+ * \param stride Word aligned rowstride (width) as returned by MFDB_STRIDE,
+ * \param h Height in pixels.
+*/
+#define MFDB_SIZE( bpp, stride, h ) ( ((stride >> 3) * h) * bpp )
+
+struct gui_bitmap_table *atari_bitmap_table;
+
+struct bitmap {
+ int width;
+ int height;
+ uint8_t *pixdata;
+ bool opaque;
+ short bpp; /* number of BYTES! per pixel */
+ size_t rowstride;
+ struct bitmap * resized;
+ MFDB native;
+ bool converted;
+};
+
+
+
+/**
+ * setup an MFDB struct and allocate memory for it when it is needed.
+ *
+ * If bpp == 0, this function assumes that the MFDB shall point to the
+ * screen and will not allocate any memory (mfdb.fd_addr == 0).
+ *
+ * \return 0 when the memory allocation fails (out of memory),
+ * otherwise it returns the size of the mfdb.fd_addr as number
+ * of bytes.
+ */
+int init_mfdb(int bpp, int w, int h, uint32_t flags, MFDB * out );
+
+/**
+ * Create a bitmap.
+ *
+ * \param w width of image in pixels
+ * \param h width of image in pixels
+ * \param state a flag word indicating the initial state
+ * \return an opaque struct bitmap, or NULL on memory exhaustion
+ */
+void *atari_bitmap_create(int w, int h, unsigned int state);
+
+/**
+ * Find the width of a pixel row in bytes.
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ * \return width of a pixel row in the bitmap
+ */
+size_t atari_bitmap_get_rowstride(void *bitmap);
+
+/**
+ * Free a bitmap.
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ */
+void atari_bitmap_destroy(void *bitmap);
+
+/**
+ * Get bitmap width
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ */
+int atari_bitmap_get_width(void *bitmap);
+
+/**
+ * Get bitmap height
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ */
+int atari_bitmap_get_height(void *bitmap);
+
+/**
+ * Gets whether a bitmap should be plotted opaque
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ */
+bool atari_bitmap_get_opaque(void *bitmap);
+
+size_t atari_bitmap_buffer_size(void *bitmap);
+
+bool atari_bitmap_resize(struct bitmap *img, HermesHandle hermes_h, HermesFormat *fmt, int nw, int nh);
+
+void *atari_bitmap_realloc( int w, int h, short bpp, int rowstride, unsigned int state, void * bmp );
+
+#endif
diff --git a/frontends/atari/certview.c b/frontends/atari/certview.c
new file mode 100644
index 000000000..7f0a29528
--- /dev/null
+++ b/frontends/atari/certview.c
@@ -0,0 +1,296 @@
+/*
+ * Copyright 2013 Ole Loots <ole@monochrom.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 <ctype.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "utils/nsoption.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/utils.h"
+#include "content/urldb.h"
+#include "content/hlcache.h"
+#include "desktop/sslcert_viewer.h"
+#include "desktop/core_window.h"
+
+#include "atari/gui.h"
+#include "atari/misc.h"
+#include "atari/treeview.h"
+#include "atari/certview.h"
+#include "atari/findfile.h"
+#include "atari/gemtk/gemtk.h"
+#include "atari/res/netsurf.rsh"
+
+extern GRECT desk_area;
+
+
+/* Setup Atari Treeview Callbacks: */
+static nserror atari_sslcert_viewer_init_phase2(struct core_window *cw,
+ struct core_window_callback_table * default_callbacks);
+static void atari_sslcert_viewer_finish(struct core_window *cw);
+static void atari_sslcert_viewer_keypress(struct core_window *cw,
+ uint32_t ucs4);
+static void atari_sslcert_viewer_mouse_action(struct core_window *cw,
+ browser_mouse_state mouse,
+ int x, int y);
+static void atari_sslcert_viewer_draw(struct core_window *cw, int x,
+ int y, struct rect *clip,
+ const struct redraw_context *ctx);
+static short handle_event(GUIWIN *win, EVMULT_OUT *ev_out, short msg[8]);
+
+static struct atari_treeview_callbacks atari_sslcert_viewer_treeview_callbacks = {
+ .init_phase2 = atari_sslcert_viewer_init_phase2,
+ .finish = atari_sslcert_viewer_finish,
+ .draw = atari_sslcert_viewer_draw,
+ .keypress = atari_sslcert_viewer_keypress,
+ .mouse_action = atari_sslcert_viewer_mouse_action,
+ .gemtk_user_func = handle_event
+};
+
+/* static functions */
+static void atari_sslcert_viewer_destroy(struct atari_sslcert_viewer_s * cvwin);
+
+
+static nserror atari_sslcert_viewer_init_phase2(struct core_window *cw,
+ struct core_window_callback_table *cb_t)
+{
+ struct atari_sslcert_viewer_s *cvwin;
+ struct sslcert_session_data *ssl_d;
+
+ cvwin = (struct atari_sslcert_viewer_s *)atari_treeview_get_user_data(cw);
+
+ assert(cvwin);
+
+ ssl_d = cvwin->ssl_session_data;
+
+ assert(ssl_d);
+
+ LOG("cw %p", cw);
+
+ return(sslcert_viewer_init(cb_t, cw, ssl_d));
+}
+
+static void atari_sslcert_viewer_finish(struct core_window *cw)
+{
+ struct atari_sslcert_viewer_s *cvwin;
+
+ assert(cw);
+
+ cvwin = (struct atari_sslcert_viewer_s *)atari_treeview_get_user_data(cw);
+
+ /* This will also free the session data: */
+ sslcert_viewer_fini(cvwin->ssl_session_data);
+
+ LOG("cw %p", cw);
+}
+
+static void atari_sslcert_viewer_draw(struct core_window *cw, int x,
+ int y, struct rect *clip,
+ const struct redraw_context *ctx)
+{
+ struct atari_sslcert_viewer_s *cvwin;
+
+ assert(cw);
+
+ cvwin = (struct atari_sslcert_viewer_s *)atari_treeview_get_user_data(cw);
+
+ assert(cvwin);
+
+ sslcert_viewer_redraw(cvwin->ssl_session_data, x, y, clip, ctx);
+}
+
+static void atari_sslcert_viewer_keypress(struct core_window *cw, uint32_t ucs4)
+{
+ struct atari_sslcert_viewer_s *cvwin;
+
+ assert(cw);
+
+ cvwin = (struct atari_sslcert_viewer_s *)atari_treeview_get_user_data(cw);
+
+ LOG("ucs4: %"PRIu32, ucs4);
+ sslcert_viewer_keypress(cvwin->ssl_session_data, ucs4);
+}
+
+static void atari_sslcert_viewer_mouse_action(struct core_window *cw,
+ browser_mouse_state mouse,
+ int x, int y)
+{
+ struct atari_sslcert_viewer_s *cvwin;
+
+ assert(cw);
+
+ cvwin = (struct atari_sslcert_viewer_s *)atari_treeview_get_user_data(cw);
+
+ sslcert_viewer_mouse_action(cvwin->ssl_session_data, mouse, x, y);
+}
+
+
+static short handle_event(GUIWIN *win, EVMULT_OUT *ev_out, short msg[8])
+{
+ struct core_window *tv=NULL;
+ GRECT tb_area;
+ GUIWIN * gemtk_win;
+ struct atari_sslcert_viewer_s *cvwin = NULL;
+ short retval = 0;
+ OBJECT *toolbar;
+
+ LOG("win %p", win);
+
+ if(ev_out->emo_events & MU_MESAG){
+ switch (msg[0]) {
+
+ case WM_TOOLBAR:
+ toolbar = gemtk_obj_get_tree(TOOLBAR_SSL_CERT);
+ LOG("CERTVIEWER WM_TOOLBAR");
+ tv = (struct core_window*) gemtk_wm_get_user_data(win);
+ assert(tv);
+ cvwin = (struct atari_sslcert_viewer_s *)
+ atari_treeview_get_user_data(tv);
+ switch (msg[4]) {
+
+ case TOOLBAR_SSL_CERT_TRUSTED:
+
+ if (toolbar[msg[4]].ob_state & OS_SELECTED) {
+
+ } else {
+
+ }
+ break;
+ }
+
+
+ gemtk_win = atari_treeview_get_gemtk_window(tv);
+ assert(gemtk_win);
+ //gemtk_obj_get_tree(TOOLBAR_HOTLIST)[msg[4]].ob_state &= ~OS_SELECTED;
+ atari_treeview_get_grect(tv, TREEVIEW_AREA_TOOLBAR, &tb_area);
+ evnt_timer(150);
+ gemtk_wm_exec_redraw(gemtk_win, &tb_area);
+ retval = 1;
+ break;
+
+ case WM_CLOSED:
+ // TODO set perrmissions
+ toolbar = gemtk_obj_get_tree(TOOLBAR_SSL_CERT);
+ tv = (struct core_window*) gemtk_wm_get_user_data(win);
+ assert(tv);
+ cvwin = (struct atari_sslcert_viewer_s *)
+ atari_treeview_get_user_data(tv);
+ if (toolbar[TOOLBAR_SSL_CERT_TRUSTED].ob_state & OS_SELECTED) {
+ sslcert_viewer_accept(cvwin->ssl_session_data);
+ } else {
+ sslcert_viewer_reject(cvwin->ssl_session_data);
+ }
+ atari_sslcert_viewer_destroy(cvwin);
+ retval = 1;
+ break;
+
+ default: break;
+ }
+ }
+
+ return(retval);
+}
+
+static void atari_sslcert_viewer_init(struct atari_sslcert_viewer_s * cvwin,
+ struct sslcert_session_data *ssl_d)
+{
+ assert(cvwin->init == false);
+ assert(cvwin->window == NULL);
+ assert(cvwin->tv == NULL);
+
+ int flags = ATARI_TREEVIEW_WIDGETS;
+ short handle = -1;
+ OBJECT * tree = gemtk_obj_get_tree(TOOLBAR_SSL_CERT);
+ assert( tree );
+
+ handle = wind_create(flags, 0, 0, desk_area.g_w, desk_area.g_h);
+ cvwin->window = gemtk_wm_add(handle,
+ GEMTK_WM_FLAG_DEFAULTS, NULL);
+ if (cvwin->window == NULL ) {
+ gemtk_msg_box_show(GEMTK_MSG_BOX_ALERT,
+ "Failed to allocate Treeview:\nCertviewer");
+ return;
+ }
+ wind_set_str(handle, WF_NAME, (char*)"SSL Certificate");
+ gemtk_wm_set_toolbar(cvwin->window, tree, 0, 0);
+ gemtk_wm_unlink(cvwin->window);
+
+ cvwin->ssl_session_data = ssl_d;
+ cvwin->tv = atari_treeview_create(cvwin->window,
+ &atari_sslcert_viewer_treeview_callbacks,
+ cvwin, flags);
+
+ if (cvwin->tv == NULL) {
+ /* handle it properly, clean up previous allocs */
+ LOG("Failed to allocate treeview");
+ return;
+ }
+
+ cvwin->init = true;
+}
+
+/*
+ * documented in certview.h
+ */
+void atari_sslcert_viewer_open(struct sslcert_session_data *ssl_d)
+{
+ struct atari_sslcert_viewer_s * cvwin;
+
+ cvwin = calloc(1, sizeof(struct atari_sslcert_viewer_s));
+
+ assert(cvwin);
+
+ atari_sslcert_viewer_init(cvwin, ssl_d);
+
+ if (atari_treeview_is_open(cvwin->tv) == false) {
+
+ GRECT pos;
+ pos.g_x = desk_area.g_w - desk_area.g_w / 4;
+ pos.g_y = desk_area.g_y;
+ pos.g_w = desk_area.g_w / 4;
+ pos.g_h = desk_area.g_h;
+
+ atari_treeview_open(cvwin->tv, &pos);
+ } else {
+ wind_set(gemtk_wm_get_handle(cvwin->window), WF_TOP, 1, 0,
+ 0, 0);
+ }
+}
+
+
+static void atari_sslcert_viewer_destroy(struct atari_sslcert_viewer_s * cvwin)
+{
+ assert(cvwin);
+ assert(cvwin->init);
+ assert(cvwin->window);
+
+ LOG("cvwin %p", cvwin);
+
+ if (atari_treeview_is_open(cvwin->tv))
+ atari_treeview_close(cvwin->tv);
+ wind_delete(gemtk_wm_get_handle(cvwin->window));
+ gemtk_wm_remove(cvwin->window);
+ cvwin->window = NULL;
+ atari_treeview_delete(cvwin->tv);
+ free(cvwin);
+ LOG("done");
+}
diff --git a/frontends/atari/certview.h b/frontends/atari/certview.h
new file mode 100644
index 000000000..ff15d8076
--- /dev/null
+++ b/frontends/atari/certview.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2013 Ole Loots <ole@monochrom.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 CERTVIEW_H_INCLUDED
+#define CERTVIEW_H_INCLUDED
+
+#include <inttypes.h>
+#include <sys/types.h>
+#include <string.h>
+
+
+#include "assert.h"
+#include "utils/nsoption.h"
+#include "utils/log.h"
+#include "desktop/sslcert_viewer.h"
+
+struct core_window;
+
+struct atari_sslcert_viewer_s {
+ GUIWIN * window;
+ //struct atari_treeview_window *tv;/*< The hotlist treeview handle. */
+ struct core_window *tv;
+ struct sslcert_session_data *ssl_session_data;
+ bool init;
+};
+
+/**
+ * Initializes and opens an certificate inspector window
+ * \param ssl_d ssl session data created by sslcert_viewer_create_session_data
+ *
+ * The window takes ownership of the session data and free's the memory on exit.
+ */
+void atari_sslcert_viewer_open(struct sslcert_session_data *ssl_d);
+
+
+#endif // CERTVIEW_H_INCLUDED
diff --git a/frontends/atari/clipboard.c b/frontends/atari/clipboard.c
new file mode 100644
index 000000000..3464e4bca
--- /dev/null
+++ b/frontends/atari/clipboard.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2013 Ole Loots <ole@monochrom.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/>.
+ *
+ * Module Description:
+ *
+ *
+ *
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+#include <mint/osbind.h>
+#include <cflib.h>
+#include "atari/clipboard.h"
+#include "atari/gemtk/gemtk.h"
+
+
+static int filesize(char * path)
+{
+ FILE *f;
+ int fs;
+
+ f = fopen( path, "r+b");
+ if(!f)
+ return(-1);
+
+ fseek(f, 0L, SEEK_END);
+ fs = ftell(f);
+ fclose(f);
+
+ return(fs);
+}
+
+int scrap_txt_write(char *str)
+{
+ scrap_wtxt(str);
+
+
+ // Send SC_CHANGED message:
+ gemtk_send_msg(SC_CHANGED, 0, 2, 0, 0, 0, 0);
+
+ return(0);
+
+}
+
+char *scrap_txt_read(void)
+{
+ char * buf = NULL;
+ char path[80];
+
+ if (get_scrapdir (path))
+ {
+ int len;
+ strcat (path, "scrap.txt");
+ len = filesize(path);
+ if(len > 0){
+ int file;
+ if ((file = (int) Fopen (path, 0)) >= 0)
+ {
+ buf = malloc(len);
+ if(buf){
+ len = Fread (file, len, buf);
+ Fclose (file);
+ buf[len] = '\0';
+ return buf;
+ }
+ }
+ }
+ }
+ return buf;
+}
+
diff --git a/frontends/atari/clipboard.h b/frontends/atari/clipboard.h
new file mode 100644
index 000000000..aeecc9a5f
--- /dev/null
+++ b/frontends/atari/clipboard.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.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 NS_ATARI_CLIPBOARD_H
+#define NS_ATARI_CLIPBOARD_H
+
+int scrap_txt_write(char *str);
+char *scrap_txt_read(void);
+
+#endif
diff --git a/frontends/atari/cookies.c b/frontends/atari/cookies.c
new file mode 100644
index 000000000..6019b4730
--- /dev/null
+++ b/frontends/atari/cookies.c
@@ -0,0 +1,220 @@
+/*
+ * Copyright 2013 Ole Loots <ole@monochrom.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 "utils/log.h"
+#include "utils/messages.h"
+#include "desktop/mouse.h"
+#include "desktop/plotters.h"
+#include "desktop/cookie_manager.h"
+#include "desktop/core_window.h"
+
+#include "atari/treeview.h"
+#include "atari/cookies.h"
+#include "atari/gemtk/gemtk.h"
+#include "atari/res/netsurf.rsh"
+
+extern GRECT desk_area;
+
+struct atari_cookie_manager_s atari_cookie_manager;
+
+
+/* Setup Atari Treeview Callbacks: */
+static nserror atari_cookie_manager_init_phase2(struct core_window *cw,
+ struct core_window_callback_table * default_callbacks);
+static void atari_cookie_manager_finish(struct core_window *cw);
+static void atari_cookie_manager_keypress(struct core_window *cw,
+ uint32_t ucs4);
+static void atari_cookie_manager_mouse_action(struct core_window *cw,
+ browser_mouse_state mouse,
+ int x, int y);
+static void atari_cookie_manager_draw(struct core_window *cw, int x,
+ int y, struct rect *clip,
+ const struct redraw_context *ctx);
+static short handle_event(GUIWIN *win, EVMULT_OUT *ev_out, short msg[8]);
+
+static struct atari_treeview_callbacks atari_cookie_manager_treeview_callbacks = {
+ .init_phase2 = atari_cookie_manager_init_phase2,
+ .finish = atari_cookie_manager_finish,
+ .draw = atari_cookie_manager_draw,
+ .keypress = atari_cookie_manager_keypress,
+ .mouse_action = atari_cookie_manager_mouse_action,
+ .gemtk_user_func = handle_event
+};
+
+
+static nserror
+atari_cookie_manager_init_phase2(struct core_window *cw,
+ struct core_window_callback_table *cb_t)
+{
+ LOG("cw %p",cw);
+ return(cookie_manager_init(cb_t, cw));
+}
+
+
+static void
+atari_cookie_manager_finish(struct core_window *cw)
+{
+ LOG("cw %p",cw);
+ cookie_manager_fini();
+}
+
+
+static void
+atari_cookie_manager_draw(struct core_window *cw,
+ int x, int y,
+ struct rect *clip,
+ const struct redraw_context *ctx)
+{
+ cookie_manager_redraw(x, y, clip, ctx);
+}
+
+
+static void
+atari_cookie_manager_keypress(struct core_window *cw, uint32_t ucs4)
+{
+ LOG("ucs4: %"PRIu32, ucs4);
+ cookie_manager_keypress(ucs4);
+}
+
+
+static void
+atari_cookie_manager_mouse_action(struct core_window *cw,
+ browser_mouse_state mouse,
+ int x, int y)
+{
+ cookie_manager_mouse_action(mouse, x, y);
+}
+
+
+
+static short handle_event(GUIWIN *win, EVMULT_OUT *ev_out, short msg[8])
+{
+ short retval = 0;
+
+ LOG("win %p", win);
+
+ if (ev_out->emo_events & MU_MESAG) {
+ switch (msg[0]) {
+
+ case WM_TOOLBAR:
+ LOG("WM_TOOLBAR");
+ break;
+
+ case WM_CLOSED:
+ atari_cookie_manager_close();
+ retval = 1;
+ break;
+
+ default: break;
+ }
+ }
+
+ return(retval);
+}
+
+void atari_cookie_manager_init(void)
+{
+ if (atari_cookie_manager.init == false) {
+
+ if (atari_cookie_manager.window == NULL) {
+ int flags = ATARI_TREEVIEW_WIDGETS;
+ short handle = -1;
+ OBJECT * tree = gemtk_obj_get_tree(TOOLBAR_COOKIES);
+ assert( tree );
+
+ handle = wind_create(flags, 0, 0, desk_area.g_w, desk_area.g_h);
+ atari_cookie_manager.window = gemtk_wm_add(handle,
+ GEMTK_WM_FLAG_DEFAULTS, NULL);
+ if( atari_cookie_manager.window == NULL ) {
+ gemtk_msg_box_show(GEMTK_MSG_BOX_ALERT,
+ "Failed to allocate Treeview:\nCookies");
+ return;
+ }
+ wind_set_str(handle, WF_NAME, (char*)messages_get("Cookies"));
+ gemtk_wm_set_toolbar(atari_cookie_manager.window, tree, 0, 0);
+ gemtk_wm_unlink(atari_cookie_manager.window);
+
+ atari_cookie_manager.tv = atari_treeview_create(
+ atari_cookie_manager.window,
+ &atari_cookie_manager_treeview_callbacks,
+ NULL, flags);
+
+ if (atari_cookie_manager.tv == NULL) {
+ /* handle it properly, clean up previous allocs */
+ LOG("Failed to allocate treeview");
+ return;
+ }
+
+ } else {
+
+ }
+ }
+ atari_cookie_manager.init = true;
+}
+
+void atari_cookie_manager_open(void)
+{
+ assert(atari_cookie_manager.init);
+
+ if (atari_treeview_is_open(atari_cookie_manager.tv) == false) {
+
+ GRECT pos;
+ pos.g_x = desk_area.g_w - desk_area.g_w / 4;
+ pos.g_y = desk_area.g_y;
+ pos.g_w = desk_area.g_w / 4;
+ pos.g_h = desk_area.g_h;
+
+ atari_treeview_open(atari_cookie_manager.tv, &pos);
+ } else {
+ wind_set(gemtk_wm_get_handle(atari_cookie_manager.window), WF_TOP, 1, 0,
+ 0, 0);
+ }
+}
+
+
+void atari_cookie_manager_close(void)
+{
+ atari_treeview_close(atari_cookie_manager.tv);
+}
+
+
+void atari_cookie_manager_destroy(void)
+{
+ if( atari_cookie_manager.init == false) {
+ return;
+ }
+ if( atari_cookie_manager.window != NULL ) {
+ if (atari_treeview_is_open(atari_cookie_manager.tv))
+ atari_cookie_manager_close();
+ wind_delete(gemtk_wm_get_handle(atari_cookie_manager.window));
+ gemtk_wm_remove(atari_cookie_manager.window);
+ atari_cookie_manager.window = NULL;
+ atari_treeview_delete(atari_cookie_manager.tv);
+ atari_cookie_manager.init = false;
+ }
+ LOG("done");
+
+}
+
+
+void atari_cookie_manager_redraw(void)
+{
+ atari_treeview_redraw(atari_cookie_manager.tv);
+}
diff --git a/frontends/atari/cookies.h b/frontends/atari/cookies.h
new file mode 100644
index 000000000..3649c8c60
--- /dev/null
+++ b/frontends/atari/cookies.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2013 Ole Loots <ole@monochrom.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 NS_ATARI_COOKIE_MANAGER_H
+ #define NS_ATARI_COOKIE_MANAGER_H
+
+struct core_window;
+
+struct atari_cookie_manager_s {
+ GUIWIN * window;
+ //struct atari_treeview_window * tv;/*< The hotlist treeview handle. */
+ struct core_window *tv;
+ bool init;
+};
+
+extern struct atari_cookie_manager_s atari_cookie_manager;
+
+void atari_cookie_manager_init(void);
+void atari_cookie_manager_open(void);
+void atari_cookie_manager_close(void);
+void atari_cookie_manager_destroy(void);
+void atari_cookie_manager_redraw(void);
+
+#endif
diff --git a/frontends/atari/ctxmenu.c b/frontends/atari/ctxmenu.c
new file mode 100644
index 000000000..0343b20c7
--- /dev/null
+++ b/frontends/atari/ctxmenu.c
@@ -0,0 +1,321 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.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/log.h"
+#include "utils/messages.h"
+#include "utils/nsoption.h"
+#include "desktop/browser.h"
+#include "desktop/textinput.h"
+#include "content/hlcache.h"
+
+#include "atari/gui.h"
+#include "atari/misc.h"
+#include "atari/rootwin.h"
+#include "atari/clipboard.h"
+#include "atari/gemtk/gemtk.h"
+#include "atari/res/netsurf.rsh"
+#include "atari/ctxmenu.h"
+
+
+#define CNT_INVALID 0
+#define CNT_BROWSER 64
+#define CNT_HREF 128
+#define CNT_SELECTION 256
+#define CNT_INTERACTIVE 512
+#define CNT_IMG 1024
+
+bool gui_window_get_scroll(struct gui_window *w, int *sx, int *sy);
+
+struct s_context_info {
+ unsigned long flags;
+ struct browser_window_features ccdata;
+};
+
+struct s_context_info ctxinfo;
+
+static struct s_context_info * get_context_info( struct gui_window * gw, short mx, short my )
+{
+ hlcache_handle *h;
+ GRECT area;
+ struct browser_window * bw = gw->browser->bw;
+ int sx, sy;
+
+ h = browser_window_get_content(bw);
+ ctxinfo.flags = 0;
+
+ window_get_grect(gw->root, BROWSER_AREA_CONTENT, &area);
+ if (POINT_WITHIN(mx, my, area)) {
+
+ mx -= area.g_x;
+ my -= area.g_y;
+
+ if (browser_window_has_content(bw) == false ||
+ content_get_type(h) != CONTENT_HTML){
+ return(&ctxinfo);
+ }
+
+ ctxinfo.flags |= CNT_BROWSER;
+
+ gui_window_get_scroll(gw, &sx, &sy);
+
+ browser_window_get_features( gw->browser->bw, mx+sx, my+sy,
+ &ctxinfo.ccdata);
+
+ if( ctxinfo.ccdata.link ){
+ ctxinfo.flags |= CNT_HREF;
+ }
+ if( ctxinfo.ccdata.object) {
+ if( content_get_type(ctxinfo.ccdata.object) == CONTENT_IMAGE ){
+ ctxinfo.flags |= CNT_IMG;
+ }
+ }
+ if ( ctxinfo.ccdata.form_features == CTX_FORM_TEXT )
+ ctxinfo.flags |= (CNT_INTERACTIVE | CNT_SELECTION);
+ }
+
+ return(&ctxinfo);
+
+
+}
+
+/***
+ * Generates an unique filename for temp. files
+ * The generated filename includes the path.
+ * If TMPDIR environmenrt vairable is set, this will be used as path,
+ * otherwise U:\tmp\
+ * \param prefix
+ * \param sufffix
+ * \return pointer to static buffer owned by get_tmpfilename()
+ */
+static char * get_tmpfilename(const char * prefix, const char * suffix)
+{
+ int i=0;
+ static char tmpfilename[PATH_MAX];
+ char * tmpdir;
+ const char * tmp_path_suffix = "";
+
+ // TODO: make function public?
+ tmpdir = getenv("TMPDIR");
+ if(tmpdir == NULL){
+ tmpdir = (char*)"u:\\tmp\\";
+ }
+
+ if(tmpdir[strlen(tmpdir)-1] != '\\'){
+ tmp_path_suffix = "\\";
+ }
+
+ do{
+ /* generate a new filename: */
+ snprintf(tmpfilename, PATH_MAX, "%s%s%s%d%s", tmpdir,
+ tmp_path_suffix, prefix, i++, suffix);
+ /* check with cflib: */
+ } while(file_exists(tmpfilename));
+
+ return(tmpfilename);
+}
+
+//TODO: do not open popup for gui_window, but for a rootwin?
+void context_popup(struct gui_window * gw, short x, short y)
+{
+
+#define POP_FIRST_ITEM POP_CTX_CUT_SEL
+#define POP_LAST_ITEM POP_CTX_SAVE_LINK_AS
+
+ OBJECT * pop;
+ int choice;
+ struct s_context_info * ctx;
+ unsigned long size;
+ const char * data;
+ FILE * fp_tmpfile;
+ char cmdline[128];
+ /* skip first byte, which must hold length of commandline: */
+ char * tempfile = &cmdline[1];
+ char * editor;
+ MENU pop_menu, me_data;
+
+ pop = gemtk_obj_get_tree( POP_CTX );
+ if (pop == NULL)
+ return;
+ ctx = get_context_info(gw, x, y);
+
+ /*
+ Disable all items by default:
+ */
+ for( choice = POP_FIRST_ITEM; choice<=POP_LAST_ITEM; choice++ ){
+ SET_BIT(pop[ choice ].ob_state, OS_DISABLED, 1);
+ }
+
+ if( ctx->flags & CNT_INTERACTIVE ){
+ SET_BIT(pop[ POP_CTX_PASTE_SEL ].ob_state, OS_DISABLED, 0);
+ }
+
+ if( (ctx->flags & CNT_BROWSER) ){
+ SET_BIT(pop[ POP_CTX_SELECT_ALL ].ob_state, OS_DISABLED, 0);
+ SET_BIT(pop[ POP_CTX_COPY_SEL ].ob_state, OS_DISABLED, 0);
+ SET_BIT(pop[ POP_CTX_VIEW_SOURCE ].ob_state, OS_DISABLED, 0);
+ }
+
+ if( ctx->flags & CNT_HREF ){
+ SET_BIT(pop[ POP_CTX_COPY_LINK ].ob_state, OS_DISABLED, 0);
+ SET_BIT(pop[ POP_CTX_OPEN_NEW ].ob_state, OS_DISABLED, 0);
+ SET_BIT(pop[ POP_CTX_SAVE_LINK_AS ].ob_state, OS_DISABLED, 0);
+ }
+
+ if( ctx->flags & CNT_IMG ){
+ SET_BIT(pop[ POP_CTX_SAVE_AS ].ob_state, OS_DISABLED, 0);
+ SET_BIT(pop[ POP_CTX_COPY_URL ].ob_state, OS_DISABLED, 0);
+ SET_BIT(pop[ POP_CTX_OPEN_NEW ].ob_state, OS_DISABLED, 0);
+ }
+
+ // point mn_tree tree to states popup:
+ pop_menu.mn_tree = gemtk_obj_get_tree(POP_CTX);
+ pop_menu.mn_menu = 0;
+ pop_menu.mn_item = POP_CTX_CUT_SEL;
+ pop_menu.mn_scroll = SCROLL_NO;
+ pop_menu.mn_keystate = 0;
+
+ menu_popup(&pop_menu, x, y, &me_data);
+ choice = me_data.mn_item;
+
+ switch( choice ){
+ case POP_CTX_COPY_SEL:
+ browser_window_key_press(gw->browser->bw, NS_KEY_COPY_SELECTION);
+ break;
+
+ case POP_CTX_CUT_SEL:
+ browser_window_key_press(gw->browser->bw, NS_KEY_CUT_SELECTION);
+ break;
+
+ case POP_CTX_PASTE_SEL:
+ browser_window_key_press(gw->browser->bw, NS_KEY_PASTE);
+ break;
+
+ case POP_CTX_SELECT_ALL:
+ browser_window_key_press(gw->browser->bw, NS_KEY_SELECT_ALL);
+ break;
+
+ case POP_CTX_SAVE_AS:
+ if (ctx->ccdata.object != NULL) {
+ if( hlcache_handle_get_url(ctx->ccdata.object) != NULL ) {
+ browser_window_navigate(
+ gw->browser->bw,
+ hlcache_handle_get_url(ctx->ccdata.object),
+ browser_window_get_url(gw->browser->bw),
+ BW_NAVIGATE_DOWNLOAD,
+ NULL,
+ NULL,
+ NULL
+ );
+ }
+ }
+
+ case POP_CTX_SAVE_LINK_AS:
+ if (ctx->ccdata.link != NULL) {
+ nserror error;
+
+ error = browser_window_navigate(
+ gw->browser->bw,
+ ctx->ccdata.link,
+ browser_window_get_url(gw->browser->bw),
+ BW_NAVIGATE_DOWNLOAD,
+ NULL,
+ NULL,
+ NULL);
+
+ if (error != NSERROR_OK) {
+ atari_warn_user(messages_get_errorcode(error), 0);
+ }
+ }
+
+ break;
+
+ case POP_CTX_COPY_URL:
+ if ((ctx->flags & CNT_IMG) && (ctx->ccdata.object != NULL)) {
+ if( hlcache_handle_get_url(ctx->ccdata.object) != NULL ){
+ scrap_txt_write((char*)nsurl_access(
+ hlcache_handle_get_url(ctx->ccdata.object)));
+ }
+ }
+ break;
+
+ case POP_CTX_COPY_LINK:
+ if ((ctx->flags & CNT_HREF) &&
+ (ctx->ccdata.link != NULL)) {
+ scrap_txt_write((char*)nsurl_access(ctx->ccdata.link));
+ }
+ break;
+
+ case POP_CTX_OPEN_NEW:
+ if ((ctx->flags & CNT_HREF) &&
+ (ctx->ccdata.link != NULL)) {
+ nserror error;
+
+ error = browser_window_create(
+ BW_CREATE_HISTORY | BW_CREATE_CLONE,
+ ctx->ccdata.link,
+ browser_window_get_url(gw->browser->bw),
+ gw->browser->bw,
+ NULL);
+ if (error != NSERROR_OK) {
+ atari_warn_user(messages_get_errorcode(error), 0);
+ }
+ }
+ break;
+
+ case POP_CTX_VIEW_SOURCE:
+ editor = nsoption_charp(atari_editor);
+ if (editor != NULL && strlen(editor)>0) {
+ data = content_get_source_data(browser_window_get_content(gw->browser->bw),
+ &size);
+ if (size > 0 && data != NULL){
+ snprintf(tempfile, 127, "%s", get_tmpfilename("ns-", ".html"));
+ /* the GEMDOS cmdline contains the length of the commandline
+ in the first byte: */
+ cmdline[0] = (unsigned char)strlen(tempfile);
+ LOG("Creating temporay source file: %s\n", tempfile);
+ fp_tmpfile = fopen(tempfile, "w");
+ if (fp_tmpfile != NULL){
+ fwrite(data, size, 1, fp_tmpfile);
+ fclose(fp_tmpfile);
+
+ // Send SH_WDRAW to notify files changed:
+ gemtk_send_msg(SH_WDRAW, 0, -1, 0, 0, 0, 0);
+
+ // start application:
+ if(strlen(tempfile)<=125){
+ shel_write(1, 1, 1, editor, cmdline);
+ }
+ } else {
+ printf("Could not open temp file: %s!\n", tempfile );
+ }
+
+ } else {
+ LOG("Invalid content!");
+ }
+ } else {
+ form_alert(0, "[1][Set option \"atari_editor\".][OK]");
+ }
+ break;
+
+ default: break;
+ }
+
+#undef POP_FIRST_ITEM
+#undef POP_LAST_ITEM
+
+}
diff --git a/frontends/atari/ctxmenu.h b/frontends/atari/ctxmenu.h
new file mode 100644
index 000000000..73a96637a
--- /dev/null
+++ b/frontends/atari/ctxmenu.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2012 Ole Loots <ole@monochrom.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 CTXMENU_H_INCLUDED
+#define CTXMENU_H_INCLUDED
+
+void context_popup( struct gui_window * gw, short x, short y );
+
+#endif // CTXMENU_H_INCLUDED
diff --git a/frontends/atari/deskmenu.c b/frontends/atari/deskmenu.c
new file mode 100644
index 000000000..723835873
--- /dev/null
+++ b/frontends/atari/deskmenu.c
@@ -0,0 +1,828 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.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 <cflib.h>
+
+#include "utils/log.h"
+#include "utils/nsurl.h"
+#include "utils/messages.h"
+#include "utils/nsoption.h"
+#include "desktop/browser.h"
+#include "desktop/save_complete.h"
+#include "desktop/textinput.h"
+
+#include "atari/res/netsurf.rsh"
+#include "atari/gemtk/gemtk.h"
+#include "atari/deskmenu.h"
+#include "atari/hotlist.h"
+#include "atari/history.h"
+#include "atari/cookies.h"
+#include "atari/toolbar.h"
+#include "atari/settings.h"
+#include "atari/misc.h"
+#include "atari/gui.h"
+#include "atari/findfile.h"
+#include "atari/about.h"
+#include "atari/plot/plot.h"
+#include "atari/rootwin.h"
+
+typedef void __CDECL (*menu_evnt_func)(short item, short title, void * data);
+
+struct s_accelerator
+{
+ char ascii; /* either ascii or */
+ long keycode; /* normalised keycode is valid */
+ short mod; /* shift / ctrl etc */
+};
+
+struct s_menu_item_evnt {
+ short title; /* to which menu this item belongs */
+ short rid; /* resource ID */
+ menu_evnt_func menu_func; /* click handler */
+ struct s_accelerator accel; /* accelerator info */
+ char * menustr;
+};
+
+static void register_menu_str(struct s_menu_item_evnt * mi);
+//static void __CDECL evnt_menu(WINDOW * win, short buff[8]);
+
+extern void *h_gem_rsrc;
+extern bool html_redraw_debug;
+extern struct gui_window * input_window;
+extern char options[PATH_MAX];
+extern const char * option_homepage_url;
+extern int option_window_width;
+extern int option_window_height;
+extern int option_window_x;
+extern int option_window_y;
+
+static OBJECT * h_gem_menu;
+
+
+/* Zero based resource tree ids: */
+#define T_ABOUT 0
+#define T_FILE MAINMENU_T_FILE - MAINMENU_T_FILE + 1
+#define T_EDIT MAINMENU_T_EDIT - MAINMENU_T_FILE + 1
+#define T_VIEW MAINMENU_T_VIEW - MAINMENU_T_FILE + 1
+#define T_NAV MAINMENU_T_NAVIGATE - MAINMENU_T_FILE + 1
+#define T_UTIL MAINMENU_T_UTIL - MAINMENU_T_FILE + 1
+#define T_HELP MAINMENU_T_NAVIGATE - MAINMENU_T_FILE + 1
+/* Count of the above defines: */
+#define NUM_MENU_TITLES 7
+
+
+static void __CDECL menu_about(short item, short title, void *data);
+static void __CDECL menu_new_win(short item, short title, void *data);
+static void __CDECL menu_open_url(short item, short title, void *data);
+static void __CDECL menu_open_file(short item, short title, void *data);
+static void __CDECL menu_close_win(short item, short title, void *data);
+static void __CDECL menu_save_page(short item, short title, void *data);
+static void __CDECL menu_quit(short item, short title, void *data);
+static void __CDECL menu_cut(short item, short title, void *data);
+static void __CDECL menu_copy(short item, short title, void *data);
+static void __CDECL menu_paste(short item, short title, void *data);
+static void __CDECL menu_find(short item, short title, void *data);
+static void __CDECL menu_choices(short item, short title, void *data);
+static void __CDECL menu_stop(short item, short title, void *data);
+static void __CDECL menu_reload(short item, short title, void *data);
+static void __CDECL menu_dec_scale(short item, short title, void *data);
+static void __CDECL menu_inc_scale(short item, short title, void *data);
+static void __CDECL menu_toolbars(short item, short title, void *data);
+static void __CDECL menu_savewin(short item, short title, void *data);
+static void __CDECL menu_debug_render(short item, short title, void *data);
+static void __CDECL menu_fg_images(short item, short title, void *data);
+static void __CDECL menu_bg_images(short item, short title, void *data);
+static void __CDECL menu_back(short item, short title, void *data);
+static void __CDECL menu_forward(short item, short title, void *data);
+static void __CDECL menu_home(short item, short title, void *data);
+static void __CDECL menu_lhistory(short item, short title, void *data);
+static void __CDECL menu_ghistory(short item, short title, void *data);
+static void __CDECL menu_add_bookmark(short item, short title, void *data);
+static void __CDECL menu_bookmarks(short item, short title, void *data);
+static void __CDECL menu_cookies(short item, short title, void *data);
+static void __CDECL menu_vlog(short item, short title, void *data);
+static void __CDECL menu_help_content(short item, short title, void *data);
+
+struct s_menu_item_evnt menu_evnt_tbl[] =
+{
+ {T_ABOUT,MAINMENU_M_ABOUT, menu_about, {0,0,0}, NULL },
+ {T_FILE, MAINMENU_M_NEWWIN, menu_new_win, {0,0,0}, NULL},
+ {T_FILE, MAINMENU_M_OPENURL, menu_open_url, {'G',0,K_CTRL}, NULL},
+ {T_FILE, MAINMENU_M_OPENFILE, menu_open_file, {'O',0,K_CTRL}, NULL},
+ {T_FILE, MAINMENU_M_CLOSEWIN, menu_close_win, {0,0,0}, NULL},
+ {T_FILE, MAINMENU_M_SAVEPAGE, menu_save_page, {0,NK_F3,0}, NULL},
+ {T_FILE, MAINMENU_M_QUIT, menu_quit, {'Q',0,K_CTRL}, NULL},
+ {T_EDIT, MAINMENU_M_CUT, menu_cut, {'X',0,K_CTRL}, NULL},
+ {T_EDIT, MAINMENU_M_COPY, menu_copy, {'C',0,K_CTRL}, NULL},
+ {T_EDIT, MAINMENU_M_PASTE, menu_paste, {'V',0,K_CTRL}, NULL},
+ {T_EDIT, MAINMENU_M_FIND, menu_find, {0,NK_F4,0}, NULL},
+ {T_VIEW, MAINMENU_M_RELOAD, menu_reload, {0,NK_F5,0}, NULL},
+ {T_VIEW, MAINMENU_INC_SCALE, menu_inc_scale, {'+',0,K_CTRL}, NULL},
+ {T_VIEW, MAINMENU_DEC_SCALE, menu_dec_scale, {'-',0,K_CTRL}, NULL},
+ {T_VIEW, MAINMENU_M_TOOLBARS, menu_toolbars, {0,NK_F1,K_CTRL}, NULL},
+ {T_VIEW, MAINMENU_M_SAVEWIN, menu_savewin, {0,0,0}, NULL},
+ {T_VIEW, MAINMENU_M_DEBUG_RENDER, menu_debug_render, {0,0,0}, NULL},
+ {T_VIEW, MAINMENU_M_FG_IMAGES, menu_fg_images, {0,0,0}, NULL},
+ {T_VIEW, MAINMENU_M_BG_IMAGES, menu_bg_images, {0,0,0}, NULL},
+ {T_VIEW, MAINMENU_M_STOP, menu_stop, {0,NK_ESC,K_ALT}, NULL},
+ {T_NAV, MAINMENU_M_BACK, menu_back, {0,NK_LEFT,K_ALT}, NULL},
+ {T_NAV, MAINMENU_M_FORWARD, menu_forward, {0,NK_RIGHT,K_ALT}, NULL},
+ {T_NAV, MAINMENU_M_HOME, menu_home, {0,0,0}, NULL},
+ {T_UTIL, MAINMENU_M_LHISTORY,menu_lhistory, {0,NK_F7,0}, NULL},
+ {T_UTIL, MAINMENU_M_GHISTORY, menu_ghistory, {0,NK_F7,K_CTRL}, NULL},
+ {T_UTIL, MAINMENU_M_ADD_BOOKMARK, menu_add_bookmark, {'D',0,K_CTRL}, NULL},
+ {T_UTIL, MAINMENU_M_BOOKMARKS, menu_bookmarks, {0,NK_F6,0}, NULL},
+ {T_UTIL, MAINMENU_M_COOKIES, menu_cookies, {0,0,0}, NULL},
+ {T_UTIL, MAINMENU_M_CHOICES, menu_choices, {0,0,0}, NULL},
+ {T_UTIL, MAINMENU_M_VLOG, menu_vlog, {'V',0,K_ALT}, NULL},
+ {T_HELP, MAINMENU_M_HELP_CONTENT, menu_help_content, {0,NK_F1,0}, NULL},
+ {-1, -1, NULL,{0,0,0}, NULL }
+};
+
+
+/*
+ static void __CDECL evnt_menu(WINDOW * win, short buff[8])
+ {
+ int title = buff[3];
+ INT16 x,y;
+ char *str;
+ struct gui_window * gw = window_list;
+ int i=0;
+
+ deskmenu_dispatch_item(buff[3], buff[4]);
+ }
+*/
+
+/*
+ Menu item event handlers:
+*/
+
+static void __CDECL menu_about(short item, short title, void *data)
+{
+ /*
+ nsurl *url;
+ nserror error;
+ char buf[PATH_MAX];
+
+ LOG("%s", __FUNCTION__);
+ strcpy((char*)&buf, "file://");
+ strncat((char*)&buf, (char*)"./doc/README.TXT",
+ PATH_MAX - (strlen("file://")+1) );
+
+ error = nsurl_create(buf, &url);
+ if (error == NSERROR_OK) {
+ error = browser_window_create(BW_CREATE_HISTORY,
+ url,
+ NULL,
+ NULL,
+ NULL);
+ nsurl_unref(url);
+ }
+ if (error != NSERROR_OK) {
+ atari_warn_user(messages_get_errorcode(error), 0);
+ }
+ */
+ atari_about_show();
+}
+
+static void __CDECL menu_new_win(short item, short title, void *data)
+{
+ nsurl *url;
+ nserror error;
+ const char *addr;
+
+ LOG("%s", __FUNCTION__);
+
+ if (nsoption_charp(homepage_url) != NULL) {
+ addr = nsoption_charp(homepage_url);
+ } else {
+ addr = NETSURF_HOMEPAGE;
+ }
+
+ /* create an initial browser window */
+ error = nsurl_create(addr, &url);
+ if (error == NSERROR_OK) {
+ error = browser_window_create(BW_CREATE_HISTORY,
+ url,
+ NULL,
+ NULL,
+ NULL);
+ nsurl_unref(url);
+
+ }
+ if (error != NSERROR_OK) {
+ atari_warn_user(messages_get_errorcode(error), 0);
+ }
+}
+
+static void __CDECL menu_open_url(short item, short title, void *data)
+{
+ struct gui_window * gw;
+ struct browser_window * bw ;
+ LOG("%s", __FUNCTION__);
+
+ gw = input_window;
+ if( gw == NULL ) {
+ browser_window_create(BW_CREATE_HISTORY,
+ NULL,
+ NULL,
+ NULL,
+ &bw);
+ }
+}
+
+static void __CDECL menu_open_file(short item, short title, void *data)
+{
+
+ LOG("%s", __FUNCTION__);
+
+ const char * filename = file_select(messages_get("OpenFile"), "");
+ if( filename != NULL ){
+ char * urltxt = local_file_to_url( filename );
+ if( urltxt ){
+ nsurl *url;
+ nserror error;
+
+ error = nsurl_create(urltxt, &url);
+ if (error == NSERROR_OK) {
+ error = browser_window_create(BW_CREATE_HISTORY,
+ url,
+ NULL,
+ NULL,
+ NULL);
+ nsurl_unref(url);
+
+ }
+ if (error != NSERROR_OK) {
+ atari_warn_user(messages_get_errorcode(error), 0);
+ }
+ free( urltxt );
+ }
+ }
+}
+
+static void __CDECL menu_close_win(short item, short title, void *data)
+{
+ LOG("%s", __FUNCTION__);
+ if( input_window == NULL )
+ return;
+ gui_window_destroy( input_window );
+}
+
+static void __CDECL menu_save_page(short item, short title, void *data)
+{
+ LOG("%s", __FUNCTION__);
+ static bool init = true;
+ bool is_folder=false;
+ const char * path;
+
+ if( !input_window )
+ return;
+
+ if( init ){
+ init = false;
+ save_complete_init();
+ }
+
+ do {
+ // TODO: localize string
+ path = file_select("Select folder", "");
+ if (path)
+ is_folder = is_dir(path);
+ } while ((is_folder == false) && (path != NULL));
+
+ if( path != NULL ){
+ save_complete(browser_window_get_content(
+ input_window->browser->bw), path, NULL);
+ }
+
+}
+
+static void __CDECL menu_quit(short item, short title, void *data)
+{
+ short buff[8];
+ memset( &buff, 0, sizeof(short)*8 );
+ LOG("%s", __FUNCTION__);
+ gemtk_wm_send_msg(NULL, AP_TERM, 0, 0, 0, 0);
+}
+
+static void __CDECL menu_cut(short item, short title, void *data)
+{
+ if( input_window != NULL )
+ browser_window_key_press( input_window->browser->bw, NS_KEY_CUT_SELECTION);
+}
+
+static void __CDECL menu_copy(short item, short title, void *data)
+{
+ LOG("%s", __FUNCTION__);
+ if( input_window != NULL )
+ browser_window_key_press( input_window->browser->bw, NS_KEY_COPY_SELECTION);
+}
+
+static void __CDECL menu_paste(short item, short title, void *data)
+{
+ LOG("%s", __FUNCTION__);
+ if( input_window != NULL )
+ browser_window_key_press( input_window->browser->bw, NS_KEY_PASTE);
+}
+
+static void __CDECL menu_find(short item, short title, void *data)
+{
+ LOG("%s", __FUNCTION__);
+ if (input_window != NULL) {
+ if (input_window->search) {
+ window_close_search(input_window->root);
+ }
+ else {
+ window_open_search(input_window->root, true);
+ }
+ }
+}
+
+static void __CDECL menu_choices(short item, short title, void *data)
+{
+ LOG("%s", __FUNCTION__);
+ open_settings();
+}
+
+static void __CDECL menu_stop(short item, short title, void *data)
+{
+ LOG("%s", __FUNCTION__);
+ if( input_window == NULL )
+ return;
+
+ assert(input_window && input_window->root);
+ toolbar_stop_click(input_window->root->toolbar);
+
+}
+
+static void __CDECL menu_reload(short item, short title, void *data)
+{
+ if(input_window == NULL)
+ return;
+ toolbar_reload_click(input_window->root->toolbar);
+ LOG("%s", __FUNCTION__);
+}
+
+
+static void __CDECL menu_inc_scale(short item, short title, void *data)
+{
+ if(input_window == NULL)
+ return;
+
+ browser_window_set_scale(input_window->browser->bw,
+ browser_window_get_scale(input_window->browser->bw) + 0.25,
+ true);
+}
+
+
+static void __CDECL menu_dec_scale(short item, short title, void *data)
+{
+ if(input_window == NULL)
+ return;
+
+ browser_window_set_scale(input_window->browser->bw,
+ browser_window_get_scale(input_window->browser->bw) - 0.25,
+ true);
+}
+
+
+
+static void __CDECL menu_toolbars(short item, short title, void *data)
+{
+ static int state = 0;
+ LOG("%s", __FUNCTION__);
+ if( input_window != null && input_window->root->toolbar != null ){
+ state = !state;
+ // TODO: implement toolbar hide
+ //toolbar_hide(input_window->root->toolbar, state );
+ }
+}
+
+static void __CDECL menu_savewin(short item, short title, void *data)
+{
+ LOG("%s", __FUNCTION__);
+ if (input_window && input_window->browser) {
+ GRECT rect;
+ wind_get_grect(gemtk_wm_get_handle(input_window->root->win), WF_CURRXYWH,
+ &rect);
+ option_window_width = rect.g_w;
+ option_window_height = rect.g_h;
+ option_window_x = rect.g_x;
+ option_window_y = rect.g_y;
+ nsoption_set_int(window_width, rect.g_w);
+ nsoption_set_int(window_height, rect.g_h);
+ nsoption_set_int(window_x, rect.g_x);
+ nsoption_set_int(window_y, rect.g_y);
+ nsoption_write((const char*)&options, NULL, NULL);
+ }
+
+}
+
+static void __CDECL menu_debug_render(short item, short title, void *data)
+{
+ LOG("%s", __FUNCTION__);
+ html_redraw_debug = !html_redraw_debug;
+ if( input_window != NULL ) {
+ if ( input_window->browser != NULL
+ && input_window->browser->bw != NULL) {
+ GRECT rect;
+ window_get_grect(input_window->root, BROWSER_AREA_CONTENT, &rect);
+ browser_window_reformat(input_window->browser->bw, false,
+ rect.g_w, rect.g_h );
+ menu_icheck(h_gem_menu, MAINMENU_M_DEBUG_RENDER,
+ (html_redraw_debug) ? 1 : 0);
+ }
+ }
+}
+
+static void __CDECL menu_fg_images(short item, short title, void *data)
+{
+ nsoption_set_bool(foreground_images, !nsoption_bool(foreground_images));
+ menu_icheck(h_gem_menu, MAINMENU_M_FG_IMAGES,
+ (nsoption_bool(foreground_images)) ? 1 : 0);
+}
+
+static void __CDECL menu_bg_images(short item, short title, void *data)
+{
+ nsoption_set_bool(background_images, !nsoption_bool(background_images));
+ menu_icheck(h_gem_menu, MAINMENU_M_BG_IMAGES,
+ (nsoption_bool(background_images)) ? 1 : 0);
+}
+
+static void __CDECL menu_back(short item, short title, void *data)
+{
+ LOG("%s", __FUNCTION__);
+ if( input_window == NULL )
+ return;
+ toolbar_back_click(input_window->root->toolbar);
+}
+
+static void __CDECL menu_forward(short item, short title, void *data)
+{
+ LOG("%s", __FUNCTION__);
+ if( input_window == NULL )
+ return;
+ toolbar_forward_click(input_window->root->toolbar);
+}
+
+static void __CDECL menu_home(short item, short title, void *data)
+{
+ LOG("%s", __FUNCTION__);
+ if( input_window == NULL )
+ return;
+ toolbar_home_click(input_window->root->toolbar);
+}
+
+static void __CDECL menu_lhistory(short item, short title, void *data)
+{
+ LOG("%s", __FUNCTION__);
+ if( input_window == NULL )
+ return;
+}
+
+static void __CDECL menu_ghistory(short item, short title, void *data)
+{
+ LOG("%s", __FUNCTION__);
+ atari_global_history_open();
+}
+
+static void __CDECL menu_add_bookmark(short item, short title, void *data)
+{
+ LOG("%s", __FUNCTION__);
+ if (input_window) {
+ if( browser_window_has_content(input_window->browser->bw) ){
+ atari_hotlist_add_page(
+ nsurl_access(browser_window_get_url(input_window->browser->bw)),
+ NULL
+ );
+ }
+ }
+}
+
+static void __CDECL menu_bookmarks(short item, short title, void *data)
+{
+ LOG("%s", __FUNCTION__);
+ atari_hotlist_open();
+}
+
+static void __CDECL menu_cookies(short item, short title, void *data)
+{
+ LOG("%s", __FUNCTION__);
+ atari_cookie_manager_open();
+}
+
+static void __CDECL menu_vlog(short item, short title, void *data)
+{
+ LOG("%s", __FUNCTION__);
+ verbose_log = !verbose_log;
+ menu_icheck(h_gem_menu, MAINMENU_M_VLOG, (verbose_log) ? 1 : 0);
+}
+
+static void __CDECL menu_help_content(short item, short title, void *data)
+{
+ LOG("%s", __FUNCTION__);
+}
+
+/*
+ Public deskmenu interface:
+*/
+
+
+/*
+ Parse encoded menu key shortcut
+
+ The format is:
+
+ "[" - marks start of the shortcut
+ "@,^,<" - If the keyshortcut is only valid
+ with modifier keys, one of these characters must directly
+ follow the start mark.
+ Meaning:
+ @ -> Alternate
+ ^ -> Control
+ "#" - keycode or ascii character.
+ The value is handled as keycode if the character value
+ is <= 28 ( Atari chracter table )
+ or if it is interpreted as function key string.
+ (strings: F1 - F10)
+
+*/
+static void register_menu_str( struct s_menu_item_evnt * mi )
+{
+ assert(h_gem_menu != NULL);
+
+ struct s_accelerator * accel = &mi->accel;
+ int i, l=0, x=-1;
+ char str[255];
+ bool is_std_shortcut = false;
+
+ get_string(h_gem_menu, mi->rid, str);
+
+ i = l = strlen(str);
+ while (i > 2) {
+ if ((strncmp(" ", &str[i], 2) == 0) && (strlen(&str[i]) > 2)) {
+ // "Standard" Keyboard Shortcut Element found:
+ LOG("Standard Keyboard Shortcut: \"%s\"\n", &str[i]);
+ x = i+2;
+ is_std_shortcut = true;
+ break;
+ }
+
+ if( str[i] == '['){
+ LOG("Keyboard Shortcut: \"%s\"\n", &str[i]);
+ // "Custom" Keyboard Shortcut Element found (identified by [):
+ x = i;
+ break;
+ }
+ i--;
+ }
+
+ // Parse keyboard shortcut value:
+ if( x > -1 ){
+
+ if (is_std_shortcut == false) {
+ // create a new menu string to hide the "[" mark:
+ mi->menustr = malloc( l+1 );
+ strcpy(mi->menustr, str);
+ mi->menustr[x]=' ';
+ x++;
+ }
+
+ // find & register modifiers:
+ if (str[x] == '@') {
+ accel->mod = K_ALT;
+ if (is_std_shortcut == false) {
+ // only modify menu items when it is malloc'd:
+ mi->menustr[x] = 0x07;
+ }
+ x++;
+ }
+ else if (str[x] == '^') {
+ accel->mod = K_CTRL;
+ x++;
+ }
+ else if (str[x] == 0x01) { // the arrow up chracter (atari-st encoding)
+ accel->mod = K_LSHIFT;
+ x++;
+ }
+
+ // find keycodes / chracters:
+ if( str[x] <= 28 ){
+ // parse symbol
+ switch( str[x] ){
+ case 0x03:
+ accel->keycode = NK_RIGHT;
+ break;
+ case 0x04:
+ accel->keycode = NK_LEFT;
+ break;
+ case 0x1B:
+ accel->keycode = NK_ESC;
+ break;
+ default:
+ break;
+ }
+ } else {
+ if(str[x] == 'F' && ( str[x+1] >= '1' && str[x+1] <= '9') ){
+ // parse function key
+ short fkey = atoi( &str[x+1] );
+ if( (fkey >= 0) && (fkey <= 10) ){
+ accel->keycode = NK_F1 - 1 + fkey;
+ }
+ }
+ else if (strncmp(&str[x], "Home", 4) == 0) {
+ accel->keycode = NK_CLRHOME;
+ }
+ else if (strncmp(&str[x], "Undo", 4) == 0) {
+ accel->keycode = NK_UNDO;
+ }
+ else if (strncmp(&str[x], "Help", 4) == 0) {
+ accel->keycode = NK_HELP;
+ }
+ else {
+ accel->ascii = str[x];
+ }
+ }
+
+ LOG("Registered keyboard shortcut for \"%s\" => mod: %d, ""keycode: %ld, ascii: %c\n",
+ str, accel->mod, accel->keycode, accel->ascii);
+ }
+}
+
+/**
+ * Setup & display an desktop menu.
+ */
+
+void deskmenu_init(void)
+{
+ int i;
+
+ h_gem_menu = gemtk_obj_get_tree(MAINMENU);
+
+
+ /* Install menu: */
+ menu_bar(h_gem_menu, MENU_INSTALL);
+
+ /* parse and update menu items: */
+ i = 0;
+ while (menu_evnt_tbl[i].rid != -1) {
+ if(menu_evnt_tbl[i].rid > 0 && menu_evnt_tbl[i].title > 0){
+ register_menu_str( &menu_evnt_tbl[i] );
+ /* Update menu string if not null: */
+ if( menu_evnt_tbl[i].menustr != NULL ){
+ menu_text(h_gem_menu, menu_evnt_tbl[i].rid,
+ menu_evnt_tbl[i].menustr);
+ }
+ }
+ i++;
+ }
+ deskmenu_update();
+ /* Redraw menu: */
+ menu_bar(h_gem_menu, MENU_UPDATE);
+}
+
+/**
+ * Uninstall the desktop menu
+ */
+void deskmenu_destroy(void)
+{
+ int i;
+
+ /* Remove menu from desktop: */
+ menu_bar(h_gem_menu, MENU_REMOVE);
+
+ /* Free modified menu titles: */
+ i=0;
+ while(menu_evnt_tbl[i].rid != -1) {
+ if( menu_evnt_tbl[i].menustr != NULL )
+ free(menu_evnt_tbl[i].menustr);
+ i++;
+ }
+}
+
+/**
+ * Return the deskmenu AES OBJECT tree
+ */
+OBJECT * deskmenu_get_obj_tree(void)
+{
+ return(h_gem_menu);
+}
+
+/**
+ * Handle an menu item event
+ */
+int deskmenu_dispatch_item(short title, short item)
+{
+ int i=0;
+ int retval = 0;
+ OBJECT * menu_root = deskmenu_get_obj_tree();
+
+ menu_tnormal(menu_root, item, 1);
+ menu_tnormal(menu_root, title, 1);
+ menu_bar(menu_root, 1);
+
+ // legacy code, is this sensible?:
+ /*
+ while( gw ) {
+ window_set_focus( gw, WIDGET_NONE, NULL );
+ gw = gw->next;
+ }
+ */
+
+
+ while (menu_evnt_tbl[i].rid != -1) {
+ if (menu_evnt_tbl[i].rid == item) {
+ if (menu_evnt_tbl[i].menu_func != NULL) {
+ menu_evnt_tbl[i].menu_func(item, title, NULL);
+ }
+ break;
+ }
+ i++;
+ }
+
+ return(retval);
+}
+
+/**
+ * Handle an keypress (check for accelerator)
+ */
+int deskmenu_dispatch_keypress(unsigned short kcode, unsigned short kstate,
+ unsigned short nkc)
+{
+ char sascii;
+ bool done = 0;
+ int i = 0;
+
+ sascii = gemtk_keybd2ascii(kcode, 0);
+ if(sascii >= 'a' && sascii <= 'z'){
+ sascii = gemtk_keybd2ascii(kcode, K_LSHIFT);
+ }
+
+ /* Iterate through the menu function table: */
+ while( menu_evnt_tbl[i].rid != -1 && done == false) {
+ if( kstate == menu_evnt_tbl[i].accel.mod
+ && menu_evnt_tbl[i].accel.ascii != 0) {
+ if( menu_evnt_tbl[i].accel.ascii == sascii) {
+ if (menu_evnt_tbl[i].title > 0 && menu_evnt_tbl[i].rid > 0) {
+ deskmenu_dispatch_item(menu_evnt_tbl[i].title,
+ menu_evnt_tbl[i].rid);
+ }
+ else {
+ /* Keyboard shortcut not displayed within menu: */
+ menu_evnt_tbl[i].menu_func(0, 0, NULL);
+ }
+ done = true;
+ break;
+ }
+ } else {
+ /* the accel code hides in the keycode: */
+ if( menu_evnt_tbl[i].accel.keycode != 0) {
+ if( menu_evnt_tbl[i].accel.keycode == (nkc & 0xFF) &&
+ kstate == menu_evnt_tbl[i].accel.mod) {
+ if (menu_evnt_tbl[i].title > 0 && menu_evnt_tbl[i].rid > 0) {
+ deskmenu_dispatch_item(menu_evnt_tbl[i].title,
+ menu_evnt_tbl[i].rid);
+ }
+ else {
+ /* Keyboard shortcut not displayed within menu: */
+ menu_evnt_tbl[i].menu_func(0, 0, NULL);
+ }
+ done = true;
+ break;
+ }
+ }
+ }
+ i++;
+ }
+ return((done==true) ? 1 : 0);
+}
+
+/**
+ * Refresh the desk menu, reflecting netsurf current state.
+ */
+void deskmenu_update(void)
+{
+ menu_icheck(h_gem_menu, MAINMENU_M_DEBUG_RENDER, (html_redraw_debug) ? 1 : 0);
+ menu_icheck(h_gem_menu, MAINMENU_M_FG_IMAGES,
+ (nsoption_bool(foreground_images)) ? 1 : 0);
+ menu_icheck(h_gem_menu, MAINMENU_M_BG_IMAGES,
+ (nsoption_bool(background_images)) ? 1 : 0);
+ menu_icheck(h_gem_menu, MAINMENU_M_VLOG, ((verbose_log == true) ? 1 : 0));
+}
diff --git a/frontends/atari/deskmenu.h b/frontends/atari/deskmenu.h
new file mode 100644
index 000000000..d1b157a2d
--- /dev/null
+++ b/frontends/atari/deskmenu.h
@@ -0,0 +1,11 @@
+#ifndef DESKMENU_H_INCLUDED
+#define DESKMENU_H_INCLUDED
+
+void deskmenu_init(void);
+void deskmenu_destroy(void);
+int deskmenu_dispatch_item(short title, short item);
+int deskmenu_dispatch_keypress(unsigned short kcode, unsigned short kstate, unsigned short nkc);
+OBJECT * deskmenu_get_obj_tree(void);
+void deskmenu_update( void );
+
+#endif // DESKMENU_H_INCLUDED
diff --git a/frontends/atari/doc/DejaVu.txt b/frontends/atari/doc/DejaVu.txt
new file mode 100755
index 000000000..254e2cc42
--- /dev/null
+++ b/frontends/atari/doc/DejaVu.txt
@@ -0,0 +1,99 @@
+Fonts are (c) Bitstream (see below). DejaVu changes are in public domain.
+Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below)
+
+Bitstream Vera Fonts Copyright
+------------------------------
+
+Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is
+a trademark of Bitstream, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of the fonts accompanying this license ("Fonts") and associated
+documentation files (the "Font Software"), to reproduce and distribute the
+Font Software, including without limitation the rights to use, copy, merge,
+publish, distribute, and/or sell copies of the Font Software, and to permit
+persons to whom the Font Software is furnished to do so, subject to the
+following conditions:
+
+The above copyright and trademark notices and this permission notice shall
+be included in all copies of one or more of the Font Software typefaces.
+
+The Font Software may be modified, altered, or added to, and in particular
+the designs of glyphs or characters in the Fonts may be modified and
+additional glyphs or characters may be added to the Fonts, only if the fonts
+are renamed to names not containing either the words "Bitstream" or the word
+"Vera".
+
+This License becomes null and void to the extent applicable to Fonts or Font
+Software that has been modified and is distributed under the "Bitstream
+Vera" names.
+
+The Font Software may be sold as part of a larger software package but no
+copy of one or more of the Font Software typefaces may be sold by itself.
+
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT,
+TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME
+FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING
+ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE
+FONT SOFTWARE.
+
+Except as contained in this notice, the names of Gnome, the Gnome
+Foundation, and Bitstream Inc., shall not be used in advertising or
+otherwise to promote the sale, use or other dealings in this Font Software
+without prior written authorization from the Gnome Foundation or Bitstream
+Inc., respectively. For further information, contact: fonts at gnome dot
+org.
+
+Arev Fonts Copyright
+------------------------------
+
+Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the fonts accompanying this license ("Fonts") and
+associated documentation files (the "Font Software"), to reproduce
+and distribute the modifications to the Bitstream Vera Font Software,
+including without limitation the rights to use, copy, merge, publish,
+distribute, and/or sell copies of the Font Software, and to permit
+persons to whom the Font Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright and trademark notices and this permission notice
+shall be included in all copies of one or more of the Font Software
+typefaces.
+
+The Font Software may be modified, altered, or added to, and in
+particular the designs of glyphs or characters in the Fonts may be
+modified and additional glyphs or characters may be added to the
+Fonts, only if the fonts are renamed to names not containing either
+the words "Tavmjong Bah" or the word "Arev".
+
+This License becomes null and void to the extent applicable to Fonts
+or Font Software that has been modified and is distributed under the
+"Tavmjong Bah Arev" names.
+
+The Font Software may be sold as part of a larger software package but
+no copy of one or more of the Font Software typefaces may be sold by
+itself.
+
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL
+TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
+
+Except as contained in this notice, the name of Tavmjong Bah shall not
+be used in advertising or otherwise to promote the sale, use or other
+dealings in this Font Software without prior written authorization
+from Tavmjong Bah. For further information, contact: tavmjong @ free
+. fr.
+
+$Id: LICENSE 2133 2007-11-28 02:46:28Z lechimp $
diff --git a/frontends/atari/doc/bugs b/frontends/atari/doc/bugs
new file mode 100755
index 000000000..74576f67d
--- /dev/null
+++ b/frontends/atari/doc/bugs
@@ -0,0 +1,4 @@
+KNOWN BUGS
+
+- "View Source" only works when the configured editor is already launched.
+- Wrong redraw area when parts of the window move out of the screen area.
diff --git a/frontends/atari/doc/changes.txt b/frontends/atari/doc/changes.txt
new file mode 100755
index 000000000..969a44bff
--- /dev/null
+++ b/frontends/atari/doc/changes.txt
@@ -0,0 +1,53 @@
+
+
+ ===========================
+ FreeMiNT Frontend Changelog
+ ===========================
+
+
+ NetSurf 3.1
+========================================
+
+As there was no atari NetSurf 3.0 Release FreeMiNT, this Changelog contains
+the FreeMint specific changes from
+NetSurf 2.9-PL1 Release (Sunday, April 15 2012) to Netsurf 3.1 Release.
+
+
+ - Removed WinDom dependency (heavy GUI code change)
+ - Implemented "paste clipboard" for toolbar URL textbox.
+ - Implemented file drop on browser window handling when netsurf core
+ ignores the file drop event.
+ - Implemented basic browser window scaling
+ - Integrated "search page" dialog into browser window
+ - New settings dialog
+ - New treeview implementation
+ - Added global history window.
+ - Added SSL information treeview
+ - Added about dialog
+ - Improved keyboard-shortcut handling
+ - Improved caret redraw
+ - Improved favicon display
+ - Improved warning display (now shows a message box)
+ - Improved bitmap blitting
+ - Fixed FreeMiNT's unified filesystem handling (it's not Linux! - but DOS!)
+ - Fixed default download directoy
+ - Fixed integer overflow in download completed calculation
+ - Fixed commandline filepath handling
+
+
+ NetSurf 2.9
+========================================
+ - Fixed redraw of rectangle outlines.
+ - Fixed redraw of Hotlist, looks better now.
+ - Use netsurfs textarea implementation for URL, to reduce code size.
+ - Fixed several redraw glitches.
+ - Added a context menu, offering some handy functions.
+ - NetSurf core now supports frames & iframes.
+ - Debug rendering works now ( fixed redraw of rectangle outlines )
+ - process commandline parameter w (width) / h (height) for default window size
+ - improved mouse drag within treeview, browser win, toolbar.
+ - Fixed file drop in frames
+ - Implemented option dialog
+ - Improved GUI speed by fixing throbber code.
+ - Implemented "Save as" ( no improvements where made to core-functions ).
+ - Implemented settings dialog
diff --git a/frontends/atari/doc/faq.txt b/frontends/atari/doc/faq.txt
new file mode 100755
index 000000000..53dbe81f2
--- /dev/null
+++ b/frontends/atari/doc/faq.txt
@@ -0,0 +1,74 @@
+
+NETSURF ATARI FAQ
+
+Date: 12.04.2012
+
+01.) CAN NETSURF ALSO BE RUN WITHIN AN TOS ENVIRONMENT?
+02.) I DON'T HAVE AN 15 BIT GRAPHICS CARD, HOW TO RUN NETSURF ANYWAY?
+03.) WHEN I WANT TO RUN NETSURF IT SAYS: "SOCKET NOT CONNECTED".
+04.) I'M GETTING "INSUFFICENT MEMORY" MESSAGES WHEN RUNNING NETSURF.
+05.) SSL DOES NOT WORK - WHAT'S WRONG?
+06.) I'M GETTING THE ERROR: "BASE STYLESHEET FAILED TO LOAD" - WHAT'S WRONG?
+05.) A PAGE CRASHES - WHAT CAN I DO?
+
+1.) Question:
+ CAN NETSURF ALSO BE RUN WITHIN AN TOS ENVIRONMENT?
+
+ Answer:
+ Yes NS can run on classic TOS. More or less.
+ It is intended to run within the FreeMint environment.
+ However there is no support for networking
+ right now. Networking support for FireTOS is maybe possible
+ in the future.
+ NS also has problems with Path conversions on all FileSystems
+ running under TOS. Try setting full paths within the Choices file.
+
+
+2.) Question:
+ I DON'T HAVE AN 15 BIT GRAPHICS CARD, HOW TO RUN NETSURF ANYWAY?
+
+ Answer:
+ You need to trigger the config a bit.
+ enable the following Choices settings:
+
+ atari_font_driver:vdi
+ atari_transparency:0
+ suppress_images:1
+
+ This will run netsurf as a bloat textmode browser :)
+
+3.) Question:
+ WHEN I WANT TO RUN NETSURF IT SAYS: "SOCKET NOT CONNECTED"
+
+ Answer:
+ Take a look at the system requirements! I statet NetSurf needs
+ the latest FreeMiNT 1.17 RELEASE. There was a bug within previous
+ Versions. Please update your kernel. OR install polipo proxy
+ provided as RPM within sparemint distribution. This is an
+ workaround, it should work out of the box. But if you want to
+ use the polipo disk-cache you should edit the config file.
+
+4.) Question:
+ I'M GETTING "INSUFFICENT MEMORY" MESSAGES WHEN RUNNING NETSURF.
+
+ Answer:
+ Try to increase the TPA_INITIALMEM Configuration value within MINT.CNF
+
+5.) Question:
+ SSL DOES NOT WORK - WHAT TO DO?
+
+ Answer:
+ Try to move the shipped cabundle.crt file to the path where NetSurf
+ looks for the SSL certificates (Displayed within statusbar and also
+ verbose log).
+
+6.) Question:
+ I'M GETTING THE ERROR: "BASE STYLESHEET FAILED TO LOAD" - WHAT'S WRONG?
+
+ Answer:
+ NetSurf checks if the base stylesheet is modified. For that - it
+ requires that the system clock is returning reasonable valid values.
+ Make your your system clock is set. (Rember empty NVRAM....)
+ If that doesn't help - make sure the netsurf package was unpacked
+ completly and that all files can be read.
+
diff --git a/frontends/atari/doc/readme.txt b/frontends/atari/doc/readme.txt
new file mode 100755
index 000000000..829b59ec8
--- /dev/null
+++ b/frontends/atari/doc/readme.txt
@@ -0,0 +1,125 @@
+
+
+ NETSURF
+
+ -
+
+ NATIVE ATARI ALPHA
+
+ Version 2.9 (Release Version)
+
+Ported by: m0n0
+Release date: xx.xx.xx
+Contact: ole@monochrom.net
+WWW: http://netsurf-browser.org
+
+
+Table of Contents:
+------------------
+
+0x01 - What is it?
+0x02 - System Requirements
+0x03 - Features
+0x04 - Missing features
+0x05 - Things to test
+0x06 - Additional Notes
+0x07 - Known bugs
+0x08 - Technical information
+
+
+What is it? A web browser!
+--------------------------
+
+ NetSurf is a multi-platform web browser which is written with
+ portability and speed in mind.
+ This is the native Port for the FreeMiNT OS.
+ More info at project website: www.netsurf-browser.org
+
+
+Minimum System Requirements:
+----------------------------
+
+ - 32 MB RAM ( 48 MB recommended for demanding websites )
+ - 32 MHz ( 60 Mhz recommended )
+ - At least 15 Bit Graphics card.
+ - FreeMiNT 1.17.0 release kernel (Please look at FAQ to read
+ about TOS support) for full & correct network support.
+
+
+Main Features:
+--------------
+
+ - Very good HTML 4 & CSS 2.1 rendering
+ - HTTPS
+ - Freetype2 font rendering
+
+
+Missing Features:
+-----------------
+
+ This section describes Features that NetSurf-Core offers but which are not
+ handled by the GEM frontend currently.
+
+ - Grapical website history dialog
+
+
+Installation Notes:
+-------------------
+
+ Unpack the compressed archive that you downloaded,
+ change into the new directory and run ns.prg.
+ If something isn't working - run ns.prg within an console and
+ enable logging:
+
+ ./ns.prg -v
+
+ that makes it possible, that you can identify the problem.
+
+
+Additional Notes
+----------------
+
+ If you would like to see the above mentioned features or
+ can't run NetSurf because you only have a 16 or 256 Color system
+ get in contact.
+
+ Please also check the FAQ document.
+
+ Want to have other software ported? Get in contact and make me rich >;-)
+ If you want to help with netsurf, contact me for further info
+ or visit the netsurf svn and add something usefull :)
+
+ This is "just an early" alpha release. I wanted to get things moving on
+ and I think it is good to show the Atari-Users what has been archived
+ so far. This release lacks some features and some of the code written
+ was just coded with an "I have to get this done quickly" attitude.
+ This is especially true for the drawin routines... It doesn't offer
+ offscreen bitmaps, which was one of my goals for a release. But
+ I dropped that in favor of an not-so-delayed release.
+
+
+Known Bugs
+----------
+
+ - "View Source" only works when the configured editor is already launched.
+ - Wrong redraw area when parts of the window move out of the screen area.
+
+Technical info & outlook
+------------------------
+
+
+Greetings & Thanks
+------------------
+
+ - AtFact for providing help with resource files & images
+ - The MiNT Mailing list, they all helped me a lot!
+ - The NetSurf Mailing list guys, especially the Amiga guys.
+ - The NetSurf developers that did a great job!
+ - Everyone that tested this Browser!
+ - Everyone that provides feedback!
+ - The forum.atari-home.de members for giving me much help
+ during setup of my atari!
+
+
+----
+M0N0 - 09.09.2011
diff --git a/frontends/atari/doc/todo.txt b/frontends/atari/doc/todo.txt
new file mode 100755
index 000000000..49f8e6570
--- /dev/null
+++ b/frontends/atari/doc/todo.txt
@@ -0,0 +1,18 @@
+TODO's (no priority order) for NetSurf 3.1 - 4.0
+
+ - Optimize drawing of bitmaps on Low-Memory machines
+ - Restore the Palette when Windows get's the Focus
+ -> only needed for <= 256 colors
+ - Make drawing of tiled bitmaps optional ( they are slooow )
+ -> already optimized, still needed?
+ - Make context menu more stable (grab all available context data at popup display)
+ - Implement SystemColor Choices dialog
+ - Add at least one offscreen plotter implementation
+ - Fix utf8 to atari character conversion (legacy VDI text plotter
+ must be able to handle the text argument characters correctly)
+ - Add URL history when typing URL's into url textarea
+ - Have browser_window specific cursor, window specifc cursor
+ - When minimized (not iconyfied) NetSurf doesn't recognize that.
+ - Implement Tabs (up to 4 tab favicons when iconyfied)
+ - merge treeview and gui_window handling
+
diff --git a/frontends/atari/download.c b/frontends/atari/download.c
new file mode 100644
index 000000000..9ebe78751
--- /dev/null
+++ b/frontends/atari/download.c
@@ -0,0 +1,453 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/utils.h"
+#include "utils/nsoption.h"
+#include "utils/string.h"
+#include "content/urldb.h"
+#include "content/fetch.h"
+#include "desktop/save_complete.h"
+#include "desktop/textinput.h"
+#include "desktop/download.h"
+#include "desktop/browser.h"
+#include "desktop/gui_download.h"
+
+#include "atari/gui.h"
+#include "atari/misc.h"
+#include "atari/res/netsurf.rsh"
+#include "atari/download.h"
+#include "atari/osspec.h"
+
+extern struct gui_window * input_window;
+extern GRECT desk_area;
+
+static void gui_download_window_destroy( struct gui_download_window * gdw );
+static void on_abort_click(struct gui_download_window *dw);
+static void on_cbrdy_click(struct gui_download_window *dw);
+static void on_close(struct gui_download_window * dw);
+static void on_redraw(struct gui_download_window *dw, GRECT *clip);
+
+static void toolbar_redraw_cb(GUIWIN *win, uint16_t msg, GRECT *clip)
+{
+ struct gui_download_window *data;
+
+ if (msg != WM_REDRAW) {
+ data = gemtk_wm_get_user_data(win);
+
+ assert(data);
+
+ on_redraw(data, clip);
+ }
+}
+
+static short on_aes_event(GUIWIN *win, EVMULT_OUT *ev_out, short msg[8])
+{
+ short retval = 0;
+ struct gui_download_window *data;
+
+ GRECT clip;
+
+ data = gemtk_wm_get_user_data(win);
+
+ if ((ev_out->emo_events & MU_MESAG) != 0) {
+ // handle message
+ //printf("download win msg: %d\n", msg[0]);
+ switch (msg[0]) {
+
+ case WM_REDRAW:
+ clip.g_x = msg[4];
+ clip.g_y = msg[5];
+ clip.g_w = msg[6];
+ clip.g_h = msg[7];
+ on_redraw(data, &clip);
+ break;
+
+ case WM_CLOSED:
+ // TODO: this needs to iterate through all gui windows and
+ // check if the rootwin is this window...
+ on_close(data);
+ break;
+
+ case WM_TOOLBAR:
+ switch(msg[4]){
+
+ case DOWNLOAD_BT_ABORT:
+ on_abort_click(data);
+ break;
+
+ case DOWNLOAD_CB_CLOSE_RDY:
+ on_cbrdy_click(data);
+ break;
+
+ default: break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ if ((ev_out->emo_events & MU_KEYBD) != 0) {
+
+
+ }
+ if ((ev_out->emo_events & MU_BUTTON) != 0) {
+
+ }
+
+ return(retval);
+}
+
+static void on_redraw(struct gui_download_window *dw, GRECT *clip)
+{
+ OBJECT *tree = dw->tree;
+ GRECT work, visible;
+ uint32_t p = 0;
+
+ gemtk_wm_get_grect(dw->guiwin, GEMTK_WM_AREA_TOOLBAR, &work);
+ tree->ob_x = work.g_x;
+ tree->ob_y = work.g_y;
+
+ if(!rc_intersect(clip, &work)){
+ return;
+ }
+
+ /*
+ Update the AES Object to reflect current state of download:
+ */
+ ((TEDINFO *)get_obspec(tree, DOWNLOAD_FILENAME))->te_ptext = dw->lbl_file;
+ ((TEDINFO *)get_obspec(tree, DOWNLOAD_LBL_BYTES))->te_ptext = dw->lbl_done;
+ ((TEDINFO *)get_obspec(tree, DOWNLOAD_LBL_PERCENT))->te_ptext = dw->lbl_percent;
+ ((TEDINFO *)get_obspec(tree, DOWNLOAD_LBL_SPEED))->te_ptext = dw->lbl_speed;
+
+ if (dw->size_total > 0 ) {
+ p = ((double)dw->size_downloaded / (double)dw->size_total * 100);
+ }
+ tree[DOWNLOAD_PROGRESS_DONE].ob_width = MAX( MIN( p*(DOWNLOAD_BAR_MAX/100),
+ DOWNLOAD_BAR_MAX ), 1);
+ if (dw->close_on_finish) {
+ tree[DOWNLOAD_CB_CLOSE_RDY].ob_state |= (OS_SELECTED | OS_CROSSED);
+ } else {
+ tree[DOWNLOAD_CB_CLOSE_RDY].ob_state &= ~(OS_SELECTED | OS_CROSSED);
+ }
+ tree[DOWNLOAD_BT_ABORT].ob_state &= ~OS_SELECTED;
+
+ /*Walk the AES rectangle list and redraw the visible areas of the window: */
+ wind_get_grect(dw->aes_handle, WF_FIRSTXYWH, &visible);
+ while (visible.g_x && visible.g_y) {
+ if (rc_intersect(&work, &visible)) {
+ objc_draw_grect(tree, 0, 8, &visible);
+ }
+ wind_get_grect(dw->aes_handle, WF_NEXTXYWH, &visible);
+ }
+}
+
+static void on_abort_click(struct gui_download_window *dw)
+{
+ if( dw->status == NSATARI_DOWNLOAD_COMPLETE
+ || dw->status == NSATARI_DOWNLOAD_ERROR ) {
+ gemtk_wm_send_msg(dw->guiwin, WM_CLOSED, 0,0,0,0);
+ }
+ else if( dw->status != NSATARI_DOWNLOAD_CANCELED ){
+ dw->abort = true;
+ }
+}
+
+static void on_cbrdy_click(struct gui_download_window *dw)
+{
+ dw->close_on_finish = !dw->close_on_finish;
+ if (dw->close_on_finish && dw->status == NSATARI_DOWNLOAD_COMPLETE) {
+ gemtk_wm_send_msg(dw->guiwin, WM_CLOSED, 0,0,0,0);
+ }
+ gemtk_wm_exec_redraw(dw->guiwin, NULL);
+ evnt_timer(250);
+}
+
+static void on_close(struct gui_download_window * dw)
+{
+ gui_download_window_destroy(dw);
+}
+
+static void gui_download_window_destroy( struct gui_download_window * gdw)
+{
+ LOG("gdw %p", gdw);
+
+ if (gdw->status == NSATARI_DOWNLOAD_WORKING) {
+ download_context_abort(gdw->ctx);
+ }
+
+ download_context_destroy(gdw->ctx);
+
+ if (gdw->destination) {
+ free( gdw->destination );
+ }
+ if (gdw->fd != NULL) {
+ fclose(gdw->fd);
+ gdw->fd = NULL;
+ }
+ if (gdw->fbuf != NULL) {
+ free( gdw->fbuf );
+ }
+ gemtk_wm_remove(gdw->guiwin);
+ wind_close(gdw->aes_handle);
+ wind_delete(gdw->aes_handle);
+ free(gdw);
+}
+
+static char * select_filepath( const char * path, const char * filename )
+{
+ char tmp[PATH_MAX];
+ char res_path[PATH_MAX];
+ char res_file[PATH_MAX];
+ char * ret = NULL;
+
+ strncpy(res_path, path, PATH_MAX);
+ strncpy(res_file, filename, PATH_MAX);
+ res_file[PATH_MAX-1] = 0;
+ res_path[PATH_MAX-1] = 0;
+
+ if(select_file(res_path, res_file, (char*)"*",
+ (char*)messages_get("SaveAsNS"), NULL)) {
+ snprintf(tmp, PATH_MAX, "%s%s", res_path, res_file);
+ ret = malloc(strlen(tmp)+1);
+ strcpy(ret, tmp);
+ }
+
+ printf("download file: %s\n", ret);
+ return(ret);
+}
+
+static struct gui_download_window *
+gui_download_window_create(download_context *ctx, struct gui_window *parent)
+{
+ const char *filename;
+ char *destination;
+ char gdos_path[PATH_MAX];
+ struct gui_download_window * gdw;
+ int dlgres = 0;
+ OBJECT * tree = gemtk_obj_get_tree(DOWNLOAD);
+ char alert[200];
+
+
+ LOG("Creating download window for gui window: %p", parent);
+
+ /* TODO: Implement real form and use messages file strings! */
+
+ if (tree == NULL){
+ die("Couldn't find AES Object tree for download window!");
+ return(NULL);
+ }
+
+ filename = download_context_get_filename((const download_context*)ctx);
+ snprintf(alert, 200, "[2][Accept download?|%.*s][Yes|Save as...|No]",
+ 40,filename);
+ dlgres = form_alert(2, alert);
+ if( dlgres == 3){
+ return( NULL );
+ }
+ else if( dlgres == 2 ){
+ gemdos_realpath(nsoption_charp(downloads_path), gdos_path);
+ char * tmp = select_filepath( gdos_path, filename );
+ if( tmp == NULL )
+ return( NULL );
+ destination = tmp;
+ } else {
+ int dstsize=0;
+ gemdos_realpath(nsoption_charp(downloads_path), gdos_path);
+ dstsize = strlen(gdos_path) + strlen(filename) + 2;
+ destination = malloc( dstsize );
+ snprintf(destination, dstsize, "%s/%s", gdos_path, filename);
+ }
+
+ gdw = calloc(1, sizeof(struct gui_download_window));
+ if( gdw == NULL ){
+ atari_warn_user(NULL, "Out of memory!");
+ free( destination );
+ return( NULL );
+ }
+
+ gdw->ctx = ctx;
+ gdw->abort = false;
+ gdw->start = clock() / CLOCKS_PER_SEC;
+ gdw->lastrdw = 0;
+ gdw->status = NSATARI_DOWNLOAD_WORKING;
+ gdw->parent = parent;
+ gdw->fbufsize = MAX(BUFSIZ, 48000);
+ gdw->size_downloaded = 0;
+ gdw->size_total = download_context_get_total_length(ctx);
+ gdw->destination = destination;
+ gdw->tree = tree;
+
+ gdw->fd = fopen(gdw->destination, "wb");
+ if( gdw->fd == NULL ){
+ char spare[200];
+ snprintf(spare, 200, "Couldn't open %s for writing!", gdw->destination);
+ gemtk_msg_box_show(GEMTK_MSG_BOX_ALERT, spare);
+ gui_download_window_destroy(gdw);
+ return( NULL );
+ }
+
+ gdw->fbuf = malloc( gdw->fbufsize+1 );
+ if( gdw->fbuf != NULL ){
+ setvbuf( gdw->fd, gdw->fbuf, _IOFBF, gdw->fbufsize );
+ }
+
+ gdw->aes_handle = wind_create_grect(CLOSER | NAME | MOVER, &desk_area);
+ wind_set_str(gdw->aes_handle, WF_NAME, "Download");
+ unsigned long gwflags = GEMTK_WM_FLAG_DEFAULTS;
+ gdw->guiwin = gemtk_wm_add(gdw->aes_handle, gwflags, on_aes_event);
+ if( gdw->guiwin == NULL || gdw->fd == NULL ){
+ die("could not create guiwin");
+ gui_download_window_destroy(gdw);
+ return( NULL );
+ }
+ gemtk_wm_set_user_data(gdw->guiwin, gdw);
+ gemtk_wm_set_toolbar(gdw->guiwin, tree, 0, 0);
+ gemtk_wm_set_toolbar_redraw_func(gdw->guiwin, toolbar_redraw_cb);
+
+ strncpy((char*)&gdw->lbl_file, filename, MAX_SLEN_LBL_FILE-1);
+ LOG("created download: %s (total size: %d)", gdw->destination, gdw->size_total);
+
+ GRECT work, curr;
+ work.g_x = 0;
+ work.g_y = 0;
+ work.g_w = tree->ob_width;
+ work.g_h = tree->ob_height;
+
+ wind_calc_grect(WC_BORDER, CLOSER | MOVER | NAME, &work, &curr);
+
+ curr.g_x = (desk_area.g_w / 2) - (curr.g_w / 2);
+ curr.g_y = (desk_area.g_h / 2) - (curr.g_h / 2);
+
+ wind_open_grect(gdw->aes_handle, &curr);
+ gdw->lastrdw = clock() / (CLOCKS_PER_SEC >> 3);
+
+ return(gdw);
+}
+
+
+static nserror gui_download_window_data(struct gui_download_window *dw,
+ const char *data, unsigned int size)
+{
+ uint32_t clck = clock();
+ uint32_t tnow = clck / (CLOCKS_PER_SEC>>3);
+ uint32_t sdiff = (clck / (CLOCKS_PER_SEC)) - dw->start;
+
+ LOG("dw %p",dw);
+
+ if (dw->abort == true){
+ dw->status = NSATARI_DOWNLOAD_CANCELED;
+ dw->abort = false;
+ download_context_abort(dw->ctx);
+ gemtk_wm_exec_redraw(dw->guiwin, NULL);
+ return(NSERROR_OK);
+ }
+
+ /* save data */
+ fwrite( data , size, sizeof(unsigned char),dw->fd );
+ dw->size_downloaded += size;
+
+ /* Update GUI */
+ if ((tnow - dw->lastrdw) > 1) {
+ float speed;
+
+ dw->lastrdw = tnow;
+ speed = dw->size_downloaded / sdiff;
+
+ if( dw->size_total > 0 ){
+ uint32_t p = 0;
+ p = ((double)dw->size_downloaded / (double)dw->size_total * 100);
+ snprintf( (char*)&dw->lbl_percent, MAX_SLEN_LBL_PERCENT,
+ "%"PRIu32"%s", p, "%"
+ );
+ } else {
+ snprintf( (char*)&dw->lbl_percent, MAX_SLEN_LBL_PERCENT,
+ "%s", "?%"
+ );
+ }
+ snprintf( (char*)&dw->lbl_speed, MAX_SLEN_LBL_SPEED, "%s/s",
+ human_friendly_bytesize(speed)
+ );
+ snprintf( (char*)&dw->lbl_done, MAX_SLEN_LBL_DONE, "%s / %s",
+ human_friendly_bytesize(dw->size_downloaded),
+ (dw->size_total>0) ? human_friendly_bytesize(dw->size_total) : "?"
+ );
+
+ gemtk_wm_exec_redraw(dw->guiwin, NULL);
+ }
+ return NSERROR_OK;
+}
+
+static void gui_download_window_error(struct gui_download_window *dw,
+ const char *error_msg)
+{
+ LOG("%s", error_msg);
+
+ strncpy((char*)&dw->lbl_file, error_msg, MAX_SLEN_LBL_FILE-1);
+ dw->status = NSATARI_DOWNLOAD_ERROR;
+ gemtk_wm_exec_redraw(dw->guiwin, NULL);
+ atari_window_set_status(input_window, messages_get("Done") );
+ // TODO: change abort to close
+}
+
+static void gui_download_window_done(struct gui_download_window *dw)
+{
+ LOG("dw %p", dw);
+
+// TODO: change abort to close
+ dw->status = NSATARI_DOWNLOAD_COMPLETE;
+
+ if( dw->fd != NULL ) {
+ fclose( dw->fd );
+ dw->fd = NULL;
+ }
+
+ if (dw->close_on_finish) {
+ gemtk_wm_send_msg(dw->guiwin, WM_CLOSED, 0, 0, 0, 0);
+ } else {
+ snprintf( (char*)&dw->lbl_percent, MAX_SLEN_LBL_PERCENT,
+ "%u%s", 100, "%"
+ );
+ snprintf( (char*)&dw->lbl_done, MAX_SLEN_LBL_DONE, "%s / %s",
+ human_friendly_bytesize(dw->size_downloaded),
+ (dw->size_total>0) ? human_friendly_bytesize(dw->size_total) : human_friendly_bytesize(dw->size_downloaded)
+ );
+ gemtk_wm_exec_redraw(dw->guiwin, NULL);
+ }
+ atari_window_set_status(input_window, messages_get("Done") );
+}
+
+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 *atari_download_table = &download_table;
diff --git a/frontends/atari/download.h b/frontends/atari/download.h
new file mode 100644
index 000000000..a5be3257e
--- /dev/null
+++ b/frontends/atari/download.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.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 NS_ATARI_DOWNLOAD_H
+#define NS_ATARI_DOWNLOAD_H
+
+extern struct gui_download_table *atari_download_table;
+
+#define MAX_SLEN_LBL_DONE 64
+#define MAX_SLEN_LBL_PERCENT 5
+#define MAX_SLEN_LBL_SPEED 13
+#define MAX_SLEN_LBL_FILE 256
+#define MAX_SLEN_BT_ABORT 5
+
+#define DOWNLOAD_BAR_MAX 300
+
+typedef enum {
+ NSATARI_DOWNLOAD_NONE,
+ NSATARI_DOWNLOAD_WORKING,
+ NSATARI_DOWNLOAD_ERROR,
+ NSATARI_DOWNLOAD_COMPLETE,
+ NSATARI_DOWNLOAD_CANCELED
+} nsatari_download_status;
+
+struct gui_download_window {
+ struct download_context *ctx;
+ struct gui_window * parent;
+ GUIWIN *guiwin;
+ short aes_handle;
+ OBJECT *tree;
+ nsatari_download_status status;
+ char *destination;
+ FILE * fd;
+ char lbl_done[MAX_SLEN_LBL_DONE];
+ char lbl_percent[MAX_SLEN_LBL_PERCENT];
+ char lbl_speed[MAX_SLEN_LBL_SPEED];
+ char lbl_file[MAX_SLEN_LBL_FILE];
+ uint32_t start;
+ uint32_t lastrdw;
+ uint32_t size_total;
+ uint32_t size_downloaded;
+ char * fbuf;
+ size_t fbufsize;
+ bool abort;
+ bool close_on_finish;
+};
+
+#endif
diff --git a/frontends/atari/encoding.c b/frontends/atari/encoding.c
new file mode 100644
index 000000000..9a16cbd4e
--- /dev/null
+++ b/frontends/atari/encoding.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2012 Ole Loots <ole@monochrom.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 "utils/errors.h"
+#include "desktop/gui_utf8.h"
+
+#include "atari/encoding.h"
+
+
+/* TODO: this need a rework..., encoding to atari st doesn|t always work.
+( gui_add_to_clipboard...) */
+nserror utf8_to_local_encoding(const char *string,
+ size_t len,
+ char **result)
+{
+ nserror r;
+ r = utf8_to_enc(string, "ATARIST", len, result);
+ if (r != NSERROR_OK) {
+ r = utf8_to_enc(string, "UTF-8", len, result);
+ assert( r == NSERROR_OK );
+ }
+ return r;
+}
+
+
+nserror utf8_from_local_encoding(const char *string, size_t len, char **result)
+{
+ return utf8_from_enc(string, "ATARIST", len, result, NULL);
+}
+
+
+/* borrowed from highwire project: */
+static const uint16_t Atari_to_Unicode[] = {
+ /* .0 .1 .2 .3 .4 .5 .6 .7 .8 .9 .A .B .C .D .E .F */
+ /* 7F */ 0x0394,
+ /* 8. */ 0x00C7,0x00FC,0x00E9,0x00E2,0x00E4,0x00E0,0x00E5,0x00E7,0x00EA,0x00EB,0x00E8,0x00EF,0x00EE,0x00EC,0x00C4,0x00C5,
+ /* 9. */ 0x00C9,0x00E6,0x00C6,0x00F4,0x00F6,0x00F2,0x00FB,0x00F9,0x00FF,0x00D6,0x00DC,0x00A2,0x00A3,0x00A5,0x00DF,0x0192,
+ /* A. */ 0x00E1,0x00ED,0x00F3,0x00FA,0x00F1,0x00D1,0x00AA,0x00BA,0x00BF,0x2310,0x00AC,0x00BD,0x00BC,0x00A1,0x00AB,0x00BB,
+ /* B. */ 0x00C3,0x00F5,0x00D8,0x00F8,0x0153,0x0152,0x00C0,0x00C3,0x00D5,0x00A8,0x00B4,0x2020,0x00B6,0x00A9,0x00AE,0x2122,
+ /* C. */ 0x0133,0x0132,0x05D0,0x05D1,0x05D2,0x05D3,0x05D4,0x05D5,0x05D6,0x05D7,0x05D8,0x05D9,0x05DB,0x05DC,0x05DE,0x05E0,
+ /* D. */ 0x05E1,0x05E2,0x05E4,0x05E6,0x05E7,0x05E8,0x05E9,0x05EA,0x05DF,0x05DA,0x05DD,0x05E3,0x05E5,0x00A7,0x2038,0x221E,
+ /* E. */ 0x03B1,0x03B2,0x0393,0x03C0,0x03A3,0x03C3,0x00B5,0x03C4,0x03A6,0x0398,0x03A9,0x03B4,0x222E,0x03C6,0x2208,0x2229,
+ /* F. */ 0x2261,0x00B1,0x2265,0x2264,0x2320,0x2321,0x00F7,0x2248,0x00B0,0x2022,0x00B7,0x221A,0x207F,0x00B2,0x00B3,0x00AF
+};
+#define BEG_Atari_to_Unicode 0x7F
+
+int atari_to_ucs4(unsigned char atari)
+{
+ uint32_t ucs4 = 0xfffd;
+ if ( atari >= BEG_Atari_to_Unicode && atari <= 0xFE ) {
+ ucs4 = (int)Atari_to_Unicode[(short)atari - BEG_Atari_to_Unicode];
+ } else {
+ ucs4 = (int)atari;
+ }
+ return( ucs4 );
+}
+
+
+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 *atari_utf8_table = &utf8_table;
diff --git a/frontends/atari/encoding.h b/frontends/atari/encoding.h
new file mode 100644
index 000000000..784aa8273
--- /dev/null
+++ b/frontends/atari/encoding.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2012 Ole Loots <ole@monochrom.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 NS_ATARI_ENCODING_H
+#define NS_ATARI_ENCODING_H
+
+#include <inttypes.h>
+#include <assert.h>
+#include <stdbool.h>
+
+#include "utils/utf8.h"
+
+struct gui_utf8_table *atari_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);
+
+int atari_to_ucs4( unsigned char atarichar);
+
+#endif
diff --git a/frontends/atari/extract.php b/frontends/atari/extract.php
new file mode 100755
index 000000000..865b70ed7
--- /dev/null
+++ b/frontends/atari/extract.php
@@ -0,0 +1,10 @@
+#!/usr/bin/php
+<?
+$lines = file("deskmenu.c");
+
+foreach($lines as $line){
+ if(stripos($line, "static void __CDECL menu_") === 0){
+ echo $line;
+ }
+}
+?>
diff --git a/frontends/atari/file.c b/frontends/atari/file.c
new file mode 100644
index 000000000..499edd627
--- /dev/null
+++ b/frontends/atari/file.c
@@ -0,0 +1,294 @@
+/*
+ * Copyright 2014 Ole Loots <ole@monochrom.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 <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "utils/utils.h"
+#include "utils/corestrings.h"
+#include "utils/url.h"
+#include "utils/nsurl.h"
+#include "utils/file.h"
+#include "utils/string.h"
+
+/**
+ * \file
+ * Atari file handling callbacks.
+ *
+ * Most of this code was taken from windows/gui.c
+ */
+
+/**
+ * Generate a GEMDOS path from one or more component elemnts.
+ *
+ * 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 atari_mkpath(char **str, size_t *size, size_t nelm, va_list ap)
+{
+ return vsnstrjoin(str, size, '\\', nelm, ap);
+}
+
+/**
+ * Get the basename of a file using GEMDOS path handling.
+ *
+ * This gets the last element of a path and returns it.
+ *
+ * @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 atari_basename(const char *path, char **str, size_t *size)
+{
+ const char *leafname;
+ char *fname;
+
+ if (path == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ leafname = strrchr(path, '\\');
+ if (!leafname) {
+ leafname = path;
+ } else {
+ leafname += 1;
+ }
+
+ fname = strdup(leafname);
+ if (fname == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ *str = fname;
+ if (size != NULL) {
+ *size = strlen(fname);
+ }
+ return NSERROR_OK;
+}
+
+/**
+ * Create a path from a nsurl using GEMDOS 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 atari_nsurl_to_path(struct nsurl *url, char **path_out)
+{
+ lwc_string *urlpath;
+ char *path;
+ bool match;
+ lwc_string *scheme;
+ nserror res;
+
+ 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), &path);
+ lwc_string_unref(urlpath);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ /* if there is a drive: prefix treat path as DOS filename */
+ if ((path[2] == ':') || (path[2] == '|')) {
+
+ /* move the string down to remove leading / note the
+ * strlen is *not* copying too much data as we are
+ * moving the null too!
+ */
+ memmove(path, path + 1, strlen(path));
+ }
+ /* if the path does not have a drive letter we return the
+ * complete path.
+ */
+ /** @todo Need to check returning the unaltered path in this
+ * case is correct
+ */
+
+ *path_out = path;
+
+ return NSERROR_OK;
+}
+
+/**
+ * Create a nsurl from a path using GEMDOS file handling.
+ *
+ * Perform the necessary operations on a path to generate a nsurl.
+ *
+ * @param[in] path The path to convert.
+ * @param[out] url_out pointer to recive the nsurl, The returned url
+ * should be unreferenced by the caller.
+ * @return NSERROR_OK and the url is placed in \a url or error code on
+ * faliure.
+ */
+static nserror atari_path_to_nsurl(const char *path, struct nsurl **url_out)
+{
+ nserror ret;
+ int urllen;
+ char *urlstr;
+ char *escpath; /* escaped version of the path */
+ char *escpaths;
+
+ if ((path == NULL) || (url_out == NULL) || (*path == 0)) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ /* escape the path so it can be placed in a url */
+ ret = url_escape(path, 0, false, "/", &escpath);
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+ /* remove unecessary / as file: paths are already absolute */
+ escpaths = escpath;
+ while (*escpaths == '/') {
+ escpaths++;
+ }
+
+ /* build url as a string for nsurl constructor */
+ urllen = strlen(escpaths) + FILE_SCHEME_PREFIX_LEN + 1;
+ urlstr = malloc(urllen);
+ if (urlstr == NULL) {
+ free(escpath);
+ return NSERROR_NOMEM;
+ }
+
+ snprintf(urlstr, urllen, "%s%s", FILE_SCHEME_PREFIX, escpaths);
+ free(escpath);
+
+ ret = nsurl_create(urlstr, url_out);
+ free(urlstr);
+
+ return ret;
+}
+
+/**
+ * Ensure that all directory elements needed to store a filename exist.
+ *
+ * @param fname The filename to ensure the path to exists.
+ * @return NSERROR_OK on success or error code on failure.
+ */
+static nserror atari_mkdir_all(const char *fname)
+{
+ char *dname;
+ char *sep;
+ struct stat sb;
+
+ dname = strdup(fname);
+
+ sep = strrchr(dname, '/');
+ if (sep == NULL) {
+ /* no directory separator path is just filename so its ok */
+ free(dname);
+ return NSERROR_OK;
+ }
+
+ *sep = 0; /* null terminate directory path */
+
+ if (stat(dname, &sb) == 0) {
+ free(dname);
+ if (S_ISDIR(sb.st_mode)) {
+ /* path to file exists and is a directory */
+ return NSERROR_OK;
+ }
+ return NSERROR_NOT_DIRECTORY;
+ }
+ *sep = '/'; /* restore separator */
+
+ sep = dname;
+ while (*sep == '/') {
+ sep++;
+ }
+ while ((sep = strchr(sep, '/')) != NULL) {
+ *sep = 0;
+ if (stat(dname, &sb) != 0) {
+ if (nsmkdir(dname, S_IRWXU) != 0) {
+ /* could not create path element */
+ free(dname);
+ return NSERROR_NOT_FOUND;
+ }
+ } else {
+ if (! S_ISDIR(sb.st_mode)) {
+ /* path element not a directory */
+ free(dname);
+ return NSERROR_NOT_DIRECTORY;
+ }
+ }
+ *sep = '/'; /* restore separator */
+ /* skip directory separators */
+ while (*sep == '/') {
+ sep++;
+ }
+ }
+
+ free(dname);
+ return NSERROR_OK;
+}
+
+
+/* atari file handling table */
+static struct gui_file_table file_table = {
+ .mkpath = atari_mkpath,
+ .basename = atari_basename,
+ .nsurl_to_path = atari_nsurl_to_path,
+ .path_to_nsurl = atari_path_to_nsurl,
+ .mkdir_all = atari_mkdir_all,
+};
+
+struct gui_file_table *atari_file_table = &file_table;
+
+
diff --git a/frontends/atari/file.h b/frontends/atari/file.h
new file mode 100644
index 000000000..b368567c7
--- /dev/null
+++ b/frontends/atari/file.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2014 Ole Loots <ole@monochrom.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 FILE_C_INCLUDED
+#define FILE_C_INCLUDED
+
+#include "utils/file.h"
+
+struct gui_file_table *atari_file_table;
+
+
+#endif /* FILE_C_INCLUDED */
diff --git a/frontends/atari/filetype.c b/frontends/atari/filetype.c
new file mode 100644
index 000000000..1cce6fc18
--- /dev/null
+++ b/frontends/atari/filetype.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.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 <sys/types.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "utils/messages.h"
+#include "utils/utils.h"
+#include "utils/log.h"
+#include "content/fetch.h"
+
+#include "atari/filetype.h"
+
+/**
+ * filetype -- determine the MIME type of a local file
+ */
+const char *fetch_filetype(const char *unix_path)
+{
+ int l;
+ char * res = (char*)"text/html";
+ l = strlen(unix_path);
+
+ LOG("unix path: %s", unix_path);
+
+ /* This line is added for devlopment versions running from the root dir: */
+ if( strchr( unix_path, (int)'.' ) ){
+ if (2 < l && strcasecmp(unix_path + l - 3, "f79") == 0)
+ res = (char*)"text/css";
+ else if (2 < l && strcasecmp(unix_path + l - 3, "css") == 0)
+ res = (char*)"text/css";
+ else if (2 < l && strcasecmp(unix_path + l - 3, "jpg") == 0)
+ res = (char*)"image/jpeg";
+ else if (3 < l && strcasecmp(unix_path + l - 4, "jpeg") == 0)
+ res = (char*)"image/jpeg";
+ else if (2 < l && strcasecmp(unix_path + l - 3, "gif") == 0)
+ res = (char*)"image/gif";
+ else if (2 < l && strcasecmp(unix_path + l - 3, "png") == 0)
+ res = (char*)"image/png";
+ else if (2 < l && strcasecmp(unix_path + l - 3, "jng") == 0)
+ res = (char*)"image/jng";
+ else if (2 < l && strcasecmp(unix_path + l - 3, "svg") == 0)
+ res = (char*)"image/svg";
+ else if (2 < l && strcasecmp(unix_path + l - 3, "txt") == 0)
+ res = (char*)"text/plain";
+ } else {
+ FILE * fp;
+ char buffer[16];
+ fp = fopen( unix_path, "r" );
+ if( fp ){
+ int n=0;
+ int c;
+ do {
+ c = fgetc (fp);
+ if( c != EOF )
+ buffer[n] = (char)c;
+ else
+ buffer[n] = 0;
+ n++;
+ } while (c != EOF && n<15);
+ fclose( fp );
+ if( n > 0 ){
+ if( n > 5 && strncasecmp("GIF89", buffer, 5) == 0 )
+ res = (char*)"image/gif";
+ else if( n > 4 && strncasecmp("PNG", &buffer[1], 3) ==0 )
+ res = (char*)"image/png";
+ else if( n > 10 && strncasecmp("JFIF", &buffer[5], 4) == 0 )
+ res = (char*)"image/jpeg";
+ }
+ }
+ }
+
+ LOG("mime type: %s", res);
+ return( res );
+}
diff --git a/frontends/atari/filetype.h b/frontends/atari/filetype.h
new file mode 100644
index 000000000..97ba75b80
--- /dev/null
+++ b/frontends/atari/filetype.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.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 NS_ATARI_FILETYPE_H_
+#define NS_ATARI_FILETYPE_H_
+
+const char *fetch_filetype(const char *unix_path);
+
+#endif
diff --git a/frontends/atari/findfile.c b/frontends/atari/findfile.c
new file mode 100644
index 000000000..45ca6d916
--- /dev/null
+++ b/frontends/atari/findfile.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.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 <unistd.h>
+
+#include "utils/log.h"
+#include "utils/corestrings.h"
+
+#include "atari/gemtk/gemtk.h"
+#include "atari/findfile.h"
+#include "atari/gui.h"
+#include "atari/osspec.h"
+
+char * local_file_to_url( const char * filename )
+{
+ #define BACKSLASH 0x5C
+ char * url;
+
+ LOG("in: %s", filename);
+
+ if( strlen(filename) <= 2){
+ return( NULL );
+ }
+
+ char * fname_local = malloc( strlen(filename)+1 );
+ char * start = (char*)fname_local;
+ strcpy( start, filename );
+
+ /* convert backslashes: */
+ for( unsigned int i=0; i<strlen(start); i++ ){
+ if( start[i] == BACKSLASH ){
+ start[i] = '/';
+ }
+ }
+
+ // TODO: make file path absolute if it isn't yet.
+ url = malloc( strlen(start) + FILE_SCHEME_PREFIX_LEN + 1);
+ strcpy(url, FILE_SCHEME_PREFIX );
+ strcat(url, start );
+
+ free(fname_local);
+
+ LOG("out: %s", url);
+
+ return( url );
+ #undef BACKSLASH
+}
+
+
+/**
+ * Locate a shared resource file by searching known places in order.
+ * Search order is: ./, NETSURF_GEM_RESPATH, ./$HOME/.netsurf/, $NETSURFRES/
+ * (where NETSURFRES is an environment variable)
+ *
+ * \param buf buffer to write to. must be at least PATH_MAX chars
+ * \param filename file to look for
+ * \param def default to return if file not found
+ * \return buf
+ *
+ */
+#ifndef NETSURF_GEM_RESPATH
+ #define NETSURF_GEM_RESPATH "./res/"
+#endif
+
+char * atari_find_resource(char *buf, const char *filename, const char *def)
+{
+ char *cdir = NULL;
+ char t[PATH_MAX];
+ LOG("%s (def: %s)", filename, def);
+ strcpy(t, NETSURF_GEM_RESPATH);
+ strcat(t, filename);
+ LOG("checking %s", (char *)&t);
+ if (gemdos_realpath(t, buf) != NULL) {
+ if (access(buf, R_OK) == 0) {
+ return buf;
+ }
+ }
+ strcpy(t, "./");
+ strcat(t, filename);
+ LOG("checking %s", (char *)&t);
+ if (gemdos_realpath(t, buf) != NULL) {
+ if (access(buf, R_OK) == 0) {
+ return buf;
+ }
+ }
+
+ cdir = getenv("HOME");
+ if (cdir != NULL) {
+ strcpy(t, cdir);
+ strcat(t, "/.netsurf/");
+ strcat(t, filename);
+ LOG("checking %s", (char *)&t);
+ if (gemdos_realpath(t, buf) != NULL) {
+ if (access(buf, R_OK) == 0)
+ return buf;
+ }
+ }
+
+ cdir = getenv("NETSURFRES");
+ if (cdir != NULL) {
+ if (gemdos_realpath(cdir, buf) != NULL) {
+ strcat(buf, "/");
+ strcat(buf, filename);
+ LOG("checking %s", (char *)&t);
+ if (access(buf, R_OK) == 0)
+ return buf;
+ }
+ }
+ if (def[0] == '~') {
+ snprintf(t, PATH_MAX, "%s%s", getenv("HOME"), def + 1);
+ LOG("checking %s", (char *)&t);
+ if (gemdos_realpath(t, buf) == NULL) {
+ strcpy(buf, t);
+ }
+ } else {
+ LOG("checking %s", (char *)def);
+ if (gemdos_realpath(def, buf) == NULL) {
+ strcpy(buf, def);
+ }
+ }
+
+ return buf;
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/frontends/atari/findfile.h b/frontends/atari/findfile.h
new file mode 100644
index 000000000..9cda2a0be
--- /dev/null
+++ b/frontends/atari/findfile.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2008 Daniel Silverstone <dsilvers@netsurf-browser.org>
+ * Copyright 2011 Ole Loots <ole@monochrom.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 NS_ATARI_FINDFILE_H
+#define NS_ATARI_FINDFILE_H
+
+extern char *atari_find_resource(char *buf, const char *filename, const char *def);
+char *local_file_to_url(const char *filename);
+
+#endif /* NETSURF_ATARI_FINDFILE_H */
diff --git a/frontends/atari/font.c b/frontends/atari/font.c
new file mode 100644
index 000000000..cb0c574ea
--- /dev/null
+++ b/frontends/atari/font.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.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 <inttypes.h>
+#include <assert.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include "utils/utf8.h"
+#include "utils/log.h"
+#include "utils/nsoption.h"
+#include "desktop/gui_layout.h"
+#include "desktop/mouse.h"
+#include "desktop/plotters.h"
+
+#include "atari/gui.h"
+#include "atari/plot/fontplot.h"
+#include "atari/plot/plot.h"
+#include "atari/findfile.h"
+#include "atari/font.h"
+
+extern FONT_PLOTTER fplotter;
+
+
+/**
+ * Find the position in a string where an x coordinate falls.
+ *
+ * \param[in] fstyle style for this text
+ * \param[in] string UTF-8 string to measure
+ * \param[in] length length of string, in bytes
+ * \param[in] x coordinate to search for
+ * \param[out] char_offset updated to offset in string of actual_x, [0..length]
+ * \param[out] actual_x updated to x coordinate of character closest to x
+ * \return NSERROR_OK and char_offset and actual_x updated or appropriate error code on faliure
+ */
+static nserror
+atari_font_position(const plot_font_style_t *fstyle,
+ const char *string,
+ size_t length,
+ int x,
+ size_t *char_offset,
+ int *actual_x)
+{
+ float scale = plot_get_scale();
+
+ if (scale != 1.0) {
+ plot_font_style_t newstyle = *fstyle;
+ newstyle.size = (int)((float)fstyle->size*scale);
+ fplotter->pixel_pos(fplotter, &newstyle, string, length, x,
+ char_offset, actual_x);
+ } else {
+ fplotter->pixel_pos(fplotter, fstyle, string, length, x,
+ char_offset, actual_x);
+ }
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * Find where to split a string to make it fit a width.
+ *
+ * \param[in] fstyle style for this text
+ * \param[in] string UTF-8 string to measure
+ * \param[in] length length of string, in bytes
+ * \param[in] x width available
+ * \param[out] char_offset updated to offset in string of actual_x, [1..length]
+ * \param[out] actual_x updated to x coordinate of character closest to x
+ * \return NSERROR_OK or appropriate error code on faliure
+ *
+ * On exit, char_offset indicates first character after split point.
+ *
+ * \note char_offset of 0 must 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
+atari_font_split(const plot_font_style_t *fstyle,
+ const char *string,
+ size_t length,
+ int x,
+ size_t *char_offset,
+ int *actual_x)
+{
+ float scale = plot_get_scale();
+
+ if (scale != 1.0) {
+ plot_font_style_t newstyle = *fstyle;
+ newstyle.size = (int)((float)fstyle->size*scale);
+ fplotter->str_split(fplotter, &newstyle, string, length, x,
+ char_offset, actual_x);
+ } else {
+ fplotter->str_split(fplotter, fstyle, string, length, x,
+ char_offset, actual_x);
+ }
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * Measure the width of a string.
+ *
+ * \param[in] fstyle plot style for this text
+ * \param[in] string UTF-8 string to measure
+ * \param[in] length length of string, in bytes
+ * \param[out] width updated to width of string[0..length)
+ * \return NSERROR_OK and width updated or appropriate error code on faliure
+ */
+static nserror
+atari_font_width(const plot_font_style_t *fstyle,
+ const char *str,
+ size_t length,
+ int * width)
+{
+ float scale = plot_get_scale();
+
+ if (scale != 1.0) {
+ plot_font_style_t newstyle = *fstyle;
+ newstyle.size = (int)((float)fstyle->size*scale);
+ fplotter->str_width(fplotter, &newstyle, str, length, width);
+ } else {
+ fplotter->str_width(fplotter, fstyle, str, length, width);
+ }
+
+ return NSERROR_OK;
+}
+
+
+static struct gui_layout_table layout_table = {
+ .width = atari_font_width,
+ .position = atari_font_position,
+ .split = atari_font_split,
+};
+
+struct gui_layout_table *atari_layout_table = &layout_table;
diff --git a/frontends/atari/font.h b/frontends/atari/font.h
new file mode 100644
index 000000000..a01d000c0
--- /dev/null
+++ b/frontends/atari/font.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.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 NS_ATARI_FONT_H
+#define NS_ATARI_FONT_H
+
+struct gui_layout_table *atari_layout_table;
+
+#endif /* NETSURF_FB_FONT_H */
+
diff --git a/frontends/atari/gemtk/aestabs.c b/frontends/atari/gemtk/aestabs.c
new file mode 100644
index 000000000..519676514
--- /dev/null
+++ b/frontends/atari/gemtk/aestabs.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2013 Ole Loots <ole@monochrom.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 <assert.h>
+#include <gem.h>
+#include <cflib.h>
+#include "aestabs.h"
+
+#ifndef NDEBUG
+# define DEBUG_PRINT(x) printf x
+#else
+# define DEBUG_PRINT(x)
+#endif
+
+
+AES_TABLIST * tablist_declare(OBJECT *tree, aes_tablist_user_func user_func)
+{
+ AES_TABLIST * newlist = malloc(sizeof(AES_TABLIST));
+
+ newlist->first = NULL;
+ newlist->tree = tree;
+ newlist->user_func = user_func;
+ DEBUG_PRINT(("aes_tablist_declare: %p\n", newlist));
+ return(newlist);
+}
+
+
+AES_TAB * tablist_add(AES_TABLIST * tablist, short obj_tab, OBJECT * page_tree,
+ short obj_page)
+{
+ AES_TAB * newtab = malloc(sizeof(AES_TAB));
+
+ assert(newtab);
+ assert(tablist);
+
+ newtab->next = NULL;
+ newtab->prev = NULL;
+ newtab->obj_tab = obj_tab;
+ newtab->obj_page = obj_page;
+ newtab->page_tree = page_tree;
+
+ if(newtab->page_tree == NULL){
+ newtab->page_tree = tablist->tree;
+ }
+
+ if (tablist->first == NULL) {
+ tablist->first = newtab;
+ set_state(tablist->tree, newtab->obj_tab, OS_SELECTED, 0);
+ } else {
+ AES_TAB *tmp = tablist->first;
+ while( tmp->next != NULL ) {
+ tmp = tmp->next;
+ }
+ tmp->next = newtab;
+ newtab->prev = tmp;
+ newtab->next = NULL;
+ set_state(tablist->tree, newtab->obj_tab, OS_SELECTED, 0);
+ }
+
+ // TODO: Set the visible flag on that register?
+
+ DEBUG_PRINT(("tablist_add: Tab=%p\n", newtab));
+
+ return(newtab);
+}
+
+
+short tablist_activate(AES_TABLIST * tablist, short tab, short options)
+{
+ AES_TAB *tmp, *activated=NULL, *deactivated=NULL;
+ struct aes_tab_s *active;
+ short activated_pg = -1;
+ short is_tab = 0;
+
+ assert(tablist);
+ assert(tablist->first);
+
+ active = tablist_get_active(tablist);
+
+ if (active != NULL) {
+ if ((options & AES_TABLIST_OPTION_FORCE_EVENTS) == 0) {
+ if(active->obj_tab == tab)
+ return(0);
+ }
+ }
+
+ tmp = tablist->first;
+ while (tmp != NULL) {
+ if(tmp->obj_tab == tab) {
+ is_tab = 1;
+ }
+ tmp = tmp->next;
+ }
+
+ if(is_tab == 0) {
+ return(0);
+ }
+
+ tmp = tablist->first;
+ while ( tmp != NULL ) {
+ if(tab != tmp->obj_tab) {
+ if (get_state(tablist->tree, tmp->obj_tab, OS_SELECTED) != 0) {
+ deactivated = tmp;
+ set_state(tablist->tree, tmp->obj_tab, OS_SELECTED, 0);
+ }
+ // the tab registers can share the same page, consider that:
+ if (tablist->tree == tmp->page_tree
+ && activated_pg != tmp->obj_page) {
+
+ set_flag(tablist->tree, tmp->obj_page, OF_HIDETREE, 1);
+ }
+ } else {
+ activated = tmp;
+ // this tab must the selected / visible
+ set_state(tablist->tree, tmp->obj_tab, OS_SELECTED, 1);
+ if(tablist->tree == tmp->page_tree)
+ set_flag(tablist->tree, tmp->obj_page, OF_HIDETREE, 0);
+ activated_pg = tmp->obj_page;
+ }
+ tmp = tmp->next;
+ }
+
+ if(tablist->user_func != NULL) {
+ AES_TABLIST_FUNC_ARGS args;
+ if(deactivated){
+ args.event = AES_TABLIST_TAB_DEACTIVATED;
+ args.tab = deactivated;
+ tablist->user_func(tablist, &args);
+ }
+ if(activated){
+ args.event = AES_TABLIST_TAB_ACTIVATED;
+ args.tab = activated;
+ tablist->user_func(tablist, &args);
+ }
+ }
+ return(1);
+}
+
+struct aes_tab_s *tablist_get_active(AES_TABLIST * tablist)
+{
+ AES_TAB *tmp = tablist->first;
+ while( tmp != NULL ) {
+ if(get_state(tablist->tree, tmp->obj_tab, OS_SELECTED) != 0) {
+ // that's the one
+ return(tmp);
+ }
+ tmp = tmp->next;
+ }
+ return(NULL);
+}
+
+AES_TAB * tablist_find(AES_TABLIST * tablist, OBJECT * page, short tab)
+{
+ AES_TAB *tmp = tablist->first;
+ while( tmp != NULL ) {
+ if((tmp->page_tree == page) && (tab == tmp->obj_tab)) {
+ return(tmp);
+ }
+ tmp = tmp->next;
+ }
+ return(NULL);
+}
+
+void tablist_delete(AES_TABLIST *tablist)
+{
+ AES_TAB *tmp = tablist->first, *cur;
+ while ( tmp != NULL ) {
+ cur = tmp;
+ tmp = tmp->next;
+ DEBUG_PRINT(("tablist_delete, Freeing tab: %p\n", cur));
+ free(cur);
+ }
+ DEBUG_PRINT(("tablist_delete, Freeing list: %p\n", tablist));
+ free(tablist);
+}
diff --git a/frontends/atari/gemtk/aestabs.h b/frontends/atari/gemtk/aestabs.h
new file mode 100644
index 000000000..c72054acc
--- /dev/null
+++ b/frontends/atari/gemtk/aestabs.h
@@ -0,0 +1,56 @@
+#ifndef AESTABS_H_INCLUDED
+#define AESTABS_H_INCLUDED
+
+struct aes_tab_s;
+struct aes_tablist_s;
+typedef struct aes_tab_s AES_TAB;
+typedef struct aes_tablist_s AES_TABLIST;
+
+#define AES_TABLIST_TAB_ACTIVATED 0x01
+#define AES_TABLIST_TAB_DEACTIVATED 0x02
+
+#define AES_TABLIST_OPTION_FORCE_EVENTS 0x01 // do not eat events which do
+ // not changed the internal state
+ // this is required for tabs which
+ // require "activate" events
+ // for tabs which are already
+ // selected.
+
+
+struct aes_tablist_user_args_s
+{
+ short event;
+ AES_TAB *tab;
+};
+
+typedef struct aes_tablist_user_args_s AES_TABLIST_FUNC_ARGS;
+
+typedef void (*aes_tablist_user_func)(AES_TABLIST * list,
+ AES_TABLIST_FUNC_ARGS * args);
+
+struct aes_tab_s {
+ short obj_tab;
+ short obj_page;
+ OBJECT * page_tree;
+ AES_TAB * next, *prev;
+};
+
+struct aes_tablist_s {
+ OBJECT *tree;
+ AES_TAB * first;
+ aes_tablist_user_func user_func;
+};
+
+
+
+AES_TABLIST * tablist_declare(OBJECT *tree, aes_tablist_user_func user_func);
+void tablist_delete(AES_TABLIST * tablist);
+AES_TAB * tablist_add(AES_TABLIST * tablist, short tab, OBJECT *page_tree,
+ short page);
+short tablist_activate(AES_TABLIST * tablist, short tab, short option);
+struct aes_tab_s *tablist_get_active(AES_TABLIST * tablist);
+AES_TAB * tablist_find(AES_TABLIST * tablist, OBJECT *page, short tab);
+
+#define AES_TAB_IS_ACTIVE(l, x) (tablist_get_active(l) == x)
+
+#endif // AESTABS_H_INCLUDED
diff --git a/frontends/atari/gemtk/dragdrop.c b/frontends/atari/gemtk/dragdrop.c
new file mode 100755
index 000000000..a4b7b82a3
--- /dev/null
+++ b/frontends/atari/gemtk/dragdrop.c
@@ -0,0 +1,515 @@
+/*
+* Routine pour Drag and drop sous MultiTos
+* source: D&D Atari, demo OEP (Alexander Lorenz)
+*
+* Struktur OEP (oep.apid): AES-ID der Applikation
+*
+* (Tab = 4)
+*/
+
+#ifdef __PUREC__
+#include <tos.h>
+#else
+#include <osbind.h>
+#include <mintbind.h>
+#include <signal.h>
+#endif
+
+#include <string.h>
+#include <stdio.h>
+
+#include "gemtk.h"
+#include "cflib.h"
+
+#ifndef EACCDN
+#define EACCDN (-36)
+#endif
+
+#ifndef FA_HIDDEN
+#define FA_HIDDEN 0x02
+#endif
+
+static char pipename[] = "U:\\PIPE\\DRAGDROP.AA";
+static long pipesig;
+
+/*
+* Routinen fr den Sender
+*/
+
+/*
+* Erzeugt Pipe fr D&D
+*
+* Eingabeparameter:
+* pipe - Pointer auf 2 Byte Buffer fr Pipeextension
+*
+* Ausgabeparameters:
+* keine
+*
+* Returnwert:
+* >0: Filehandle der Pipe
+* -1: Fehler beim Erzeugen der Pipe
+*/
+
+short gemtk_dd_create(short *pipe)
+{
+ long fd = -1;
+
+ pipename[17] = 'A';
+ pipename[18] = 'A' - 1;
+
+ do /* ouvre un pipe inoccup‚ */
+ {
+ pipename[18]++;
+ if (pipename[18] > 'Z')
+ {
+ pipename[17]++;
+ if (pipename[17] > 'Z')
+ break;
+ else
+ pipename[18] = 'A';
+ }
+
+ /* FA_HIDDEN fr Pipe notwendig! */
+
+ fd = Fcreate(pipename, FA_HIDDEN);
+
+ } while (fd == (long) EACCDN);
+
+ if (fd < 0L)
+ return(-1);
+
+ *pipe = (pipename[17] << 8) | pipename[18];
+
+
+ /* Signalhandler konfigurieren */
+
+ gemtk_dd_getsig(&pipesig);
+
+
+ return((short) fd);
+}
+
+
+
+/*
+* Sendet AP_DRAGDROP an Empf„ngerapplikation
+*
+* Eingabeparameter:
+* apid - AES-ID der Emf„ngerapp.
+* fd - Filehandle der D&D-Pipe
+* winid - Handle des Zielfensters (0 fr Desktopfenster)
+* mx/my - Maus X und Y Koord.
+* (-1/-1 fr einen fake Drag&Drop)
+* kstate - Sondertastenstatus
+* pipename - Extension der D&D-Pipe
+*
+* Ausgabeparameter:
+* keine
+*
+* Returnwert:
+* >0: kein Fehler
+* -1: Empf„ngerapp. gibt DD_NAK zurck
+* -2: Empf„ngerapp. antwortet nicht (Timeout)
+* -3: Fehler bei appl_write()
+*/
+
+short gemtk_dd_message(short apid, short fd, short winid, short mx, short my, short kstate, short pipeid)
+{
+ char c;
+ short i, msg[8];
+ long fd_mask;
+
+
+ /* AES-Message define and post */
+
+ msg[0] = AP_DRAGDROP;
+ msg[1] = _AESapid;
+ msg[2] = 0;
+ msg[3] = winid;
+ msg[4] = mx;
+ msg[5] = my;
+ msg[6] = kstate;
+ msg[7] = pipeid;
+
+ i = appl_write(apid, 16, msg);
+
+ if (i == 0)
+ {
+ gemtk_dd_close(fd);
+ return(-3);
+ }
+
+
+ /* receiver reaction */
+
+ fd_mask = (1L << fd);
+ i = Fselect(DD_TIMEOUT, &fd_mask, 0L, 0L);
+ if (!i || !fd_mask)
+ {
+ /* Timeout eingetreten */
+
+ gemtk_dd_close(fd);
+ return(-2);
+ }
+
+
+ /* le recepteur refuse (lecture du pipe) */
+
+ if (Fread(fd, 1L, &c) != 1L)
+ {
+ gemtk_dd_close(fd);
+ return(-1);
+ }
+
+ if (c != DD_OK)
+ {
+ gemtk_dd_close(fd);
+ return(-1);
+ }
+
+ return(1);
+}
+
+
+
+/*
+* Liest die 8 "bevorzugten" Extensionen der Empf„ngerapplikation
+*
+* Eingabeparameter:
+* fd - Filehandle der D&D-Pipe
+*
+* Ausgabeparameters:
+* exts - 32 Bytebuffer fr die 8 bevorzugten Extensionen
+* der Zielapp.
+*
+* Returnwert:
+* >0: kein Fehler
+* -1: Fehler beim Lesen aus der Pipe
+*/
+
+short gemtk_dd_rexts(short fd, char *exts)
+{
+ if (Fread(fd, DD_EXTSIZE, exts) != DD_EXTSIZE)
+ {
+ gemtk_dd_close(fd);
+ return(-1);
+ }
+
+ return(1);
+}
+
+
+
+/*
+* Testet, ob der Empf„nger einen Datentyp akzeptiert
+*
+* Eingabeparameter:
+* fd - Filehandle (von gemtk_dd_create())
+* ext - Zeiger auf Datentyp (4 Bytes zB. "ARGS")
+* text - Zeiger auf Datenbeschreibung (optional, zB. "DESKTOP args")
+* name - Zeiger auf Datendateiname (optional, zB. "SAMPLE.TXT")
+* size - Anzahl Bytes der zu sendenden Daten
+*
+* Ausgabeparameter:
+* keine
+*
+* Returnwert:
+* DD_OK - Empf„nger akzeptiert Datentyp
+* DD_NAK - Empf„nger brach Drag&Drop ab
+* DD_EXT - Empf„nger lehnt Datentyp ab
+* DD_LEN - Empf„nger kann Datenmenge nicht verarbeiten
+* DD_TRASH - Drop erfolgte auf Mlleimer
+* DD_PRINTER - Drop erfolgte auf Drucker
+* DD_CLIPBOARD - Drop erfolgte auf Clipboard
+*/
+
+short gemtk_dd_stry(short fd, char *ext, char *text, char *name, long size)
+{
+ char c;
+ short hdrlen, i;
+
+ /* 4 Bytes fr "ext", 4 Bytes fr "size",
+ 2 Bytes fr Stringendnullen */
+
+ hdrlen = (short) (4 + 4 + strlen(text)+1 + strlen(name)+1);
+
+
+ /* Header senden */
+
+ if (Fwrite(fd, 2L, &hdrlen) != 2L)
+ return(DD_NAK);
+
+ i = (short) Fwrite(fd, 4L, ext);
+ i += (short) Fwrite(fd, 4L, &size);
+ i += (short) Fwrite(fd, strlen(text)+1, text);
+ i += (short) Fwrite(fd, strlen(name)+1, name);
+
+ if (i != hdrlen)
+ return(DD_NAK);
+
+
+ /* auf die Antwort warten */
+
+ if (Fread(fd, 1L, &c) != 1L)
+ return(DD_NAK);
+
+ return(c);
+}
+
+
+
+/* Routinen fr Sender und Empf„nger */
+
+/*
+* Pipe schliežen (Drag&Drop beenden/abbrechen)
+*/
+
+void gemtk_dd_close(short fd)
+{
+ /* Signalhandler restaurieren */
+
+ gemtk_dd_setsig(pipesig);
+
+
+ Fclose(fd);
+}
+
+
+/*
+* Signalhandler fr D&D konfigurieren
+*
+* Eingabeparameter:
+* oldsig - Zeiger auf 4 Byte Puffer fr alten Handlerwert
+*
+* Ausgabeparameter:
+* keine
+*
+* Returnwerte:
+* keine
+*/
+
+void gemtk_dd_getsig(long *oldsig)
+{
+ *oldsig = (long) Psignal(SIGPIPE, (void *) SIG_IGN);
+}
+
+
+/*
+* Signalhandler nach D&D restaurieren
+*
+* Eingabeparameter:
+* oldsig - Alter Handlerwert (von gemtk_dd_getsig)
+*
+* Ausgabeparameter:
+* keine
+*
+* Returnwerte:
+* keine
+*/
+
+void gemtk_dd_setsig(long oldsig)
+{
+ if (oldsig != -32L)
+ Psignal(SIGPIPE, (void *) oldsig);
+}
+
+
+
+/* Routinen fr Empf„nger */
+
+/*
+* Drag&Drop Pipe ”ffnen
+*
+* Eingabeparameter:
+* ddnam - Extension der Pipe (letztes short von AP_DRAGDROP)
+* ddmsg - DD_OK oder DD_NAK
+*
+* Ausgabeparameter:
+* keine
+*
+* Returnwerte:
+* >0 - Filehandle der Drag&Drop pipe
+* -1 - Drag&Drop abgebrochen
+*/
+
+short gemtk_dd_open(short ddnam, char ddmsg)
+{
+ long fd;
+
+ pipename[17] = (ddnam & 0xff00) >> 8;
+ pipename[18] = ddnam & 0x00ff;
+
+ fd = Fopen(pipename, 2);
+
+ if (fd < 0L)
+ return(-1);
+
+
+ /* Signalhandler konfigurieren */
+
+ gemtk_dd_getsig(&pipesig);
+
+
+ if (Fwrite((short) fd, 1L, &ddmsg) != 1L)
+ {
+ gemtk_dd_close((short) fd);
+ return(-1);
+ }
+
+ return((short) fd);
+}
+
+
+
+/*
+* Schreibt die 8 "bevorzugten" Extensionen der Applikation
+*
+* Eingabeparameter:
+* fd - Filehandle der D&D-Pipe
+* exts - Liste aus acht 4 Byte Extensionen die verstanden
+* werden. Diese Liste sollte nach bevorzugten Datentypen
+* sortiert sein. Sollten weniger als DD_NUMEXTS
+* Extensionen untersttzt werden, muž die Liste mit
+* Nullen (0) aufgefllt werden!
+*
+* Ausgabeparameter:
+* keine
+*
+* Returnwert:
+* >0: kein Fehler
+* -1: Fehler beim Schreiben in die Pipe
+*/
+
+short gemtk_dd_sexts(short fd, char *exts)
+{
+ if (Fwrite(fd, DD_EXTSIZE, exts) != DD_EXTSIZE)
+ {
+ gemtk_dd_close(fd);
+ return(-1);
+ }
+
+ return(1);
+}
+
+
+
+/*
+* N„chsten Header vom Sender holen
+*
+* Eingabeparameter:
+* fd - Filehandle der Pipe (von gemtk_dd_open())
+*
+* Ausgabeparameters:
+* name - Zeiger auf Buffer fr Datenbeschreibung (min. DD_NAMEMAX!)
+* file - Zeiger auf Buffer fr Datendateiname (min. DD_NAMEMAX!)
+* whichext- Zeiger auf Buffer fr Extension (4 Bytes)
+* size - Zeiger auf Buffer fr Datengr”že (4 Bytes)
+*
+* Returnwert:
+* >0: kein Fehler
+* -1: Sender brach Drag&Drop ab
+*
+* On lit dans le pipe qui normalement est constitu‚ de:
+* 1 short: taille du header
+* 4 CHAR: type de donn‚e (extension)
+* 1 long: taille des donn‚es
+* STRING: description des donn‚es
+* STRING: nom du fichiers
+* soit au minimun 11 octets (cas ou les string sont r‚duites … \0)
+* les string sont limit‚ a 128 octets
+*/
+
+short gemtk_dd_rtry(short fd, char *name, char *file, char *whichext, long *size)
+{
+ char buf[DD_NAMEMAX * 2];
+ short hdrlen, i, len;
+
+ if (Fread(fd, 2L, &hdrlen) != 2L)
+ return(-1);
+
+
+ if (hdrlen < 9) /* il reste au minimum 11 - 2 = 9 octets a lire */
+ {
+ /* sollte eigentlich nie passieren */
+
+ return(-1); /* erreur taille incorrecte */
+ }
+
+ if (Fread(fd, 4L, whichext) != 4L) /* lecture de l'extension */
+ return(-1);
+
+ if (Fread(fd, 4L, size) != 4L) /* lecture de la longueurs des donn‚es */
+ return(-1);
+
+ hdrlen -= 8; /* on a lu 8 octets */
+
+ if (hdrlen > DD_NAMEMAX*2)
+ i = DD_NAMEMAX*2;
+ else
+ i = hdrlen;
+
+ len = i;
+
+ if (Fread(fd, (long) i, buf) != (long) i)
+ return(-1);
+
+ hdrlen -= i;
+
+ strncpy(name, buf, DD_NAMEMAX);
+
+ i = (short) strlen(name) + 1;
+
+ if (len - i > 0)
+ strncpy(file, buf + i, DD_NAMEMAX);
+ else
+ file[0] = '\0';
+
+
+ /* weitere Bytes im Header in den Mll */
+
+ while (hdrlen > DD_NAMEMAX*2)
+ {
+ if (Fread(fd, DD_NAMEMAX*2, buf) != DD_NAMEMAX*2)
+ return(-1);
+
+ hdrlen -= DD_NAMEMAX*2;
+ }
+
+ if (hdrlen > 0)
+ {
+ if (Fread(fd, (long) hdrlen, buf) != (long) hdrlen)
+ return(-1);
+ }
+
+ return(1);
+}
+
+
+
+/*
+* Sendet der Senderapplikation eine 1 Byte Antwort
+*
+* Eingabeparameter:
+* fd - Filehandle der Pipe (von gemtk_dd_open())
+* ack - Byte das gesendet werden soll (zB. DD_OK)
+*
+* Ausgabeparameter:
+* keine
+*
+* Returnwert:
+* >0: kein Fehler
+* -1: Fehler (die Pipe wird automatisch geschlossen!)
+*/
+
+short gemtk_dd_reply(short fd, char ack)
+{
+ if (Fwrite(fd, 1L, &ack) != 1L)
+ {
+ gemtk_dd_close(fd);
+ return(-1);
+ }
+
+ return(1);
+}
+
+
diff --git a/frontends/atari/gemtk/dragdrop.h b/frontends/atari/gemtk/dragdrop.h
new file mode 100755
index 000000000..38466137b
--- /dev/null
+++ b/frontends/atari/gemtk/dragdrop.h
@@ -0,0 +1,4 @@
+#ifndef DD_H_INCLUDED
+#define DD_H_INCLUDED
+
+#endif
diff --git a/frontends/atari/gemtk/gemtk.h b/frontends/atari/gemtk/gemtk.h
new file mode 100644
index 000000000..e5915e6eb
--- /dev/null
+++ b/frontends/atari/gemtk/gemtk.h
@@ -0,0 +1,298 @@
+#ifndef GEMTK_H_INCLUDED
+#define GEMTK_H_INCLUDED
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include <mint/osbind.h>
+#include <mint/cookie.h>
+
+#include <gem.h>
+#include <cflib.h>
+
+
+/* -------------------------------------------------------------------------- */
+/* SYSTEM UTILS */
+/* -------------------------------------------------------------------------- */
+
+/* System type detection added by [GS] */
+/* detect the system type, AES + kernel */
+#define SYS_TOS 0x0001
+#define SYS_MAGIC 0x0002
+#define SYS_MINT 0x0004
+#define SYS_GENEVA 0x0010
+#define SYS_NAES 0x0020
+#define SYS_XAAES 0x0040
+#define sys_type() (_systype_v ? _systype_v : _systype())
+#define sys_MAGIC() ((sys_type() & SYS_MAGIC) != 0)
+#define sys_NAES() ((sys_type() & SYS_NAES) != 0)
+#define sys_XAAES() ((sys_type() & SYS_XAAES) != 0)
+
+#define TOS4VER 0x03300 /* this is assumed to be the last single tasking OS */
+
+extern unsigned short _systype_v;
+unsigned short _systype (void);
+
+/* GEMTK Utils API: */
+
+#define GEMTK_DBG_GRECT(s,g) \
+ printf("%s", s); \
+ printf("\tx0: %d, \n", (g)->g_x); \
+ printf("\ty0: %d, \n", (g)->g_y); \
+ printf("\tx1: %d, \n", (g)->g_x+(g)->g_w); \
+ printf("\ty1: %d, \n", (g)->g_y+(g)->g_h); \
+ printf("\tw: %d, \n", (g)->g_w); \
+ printf("\th: %d \n", (g)->g_h); \
+
+/*
+* Chech for GRECT intersection without modifiend the src rectangles
+* return true when the GRECT's intersect, fals otherwise.
+*/
+bool gemtk_rc_intersect_ro(GRECT *a, GRECT *b);
+
+/*
+* Convert keycode returned by evnt_multi to ascii value
+*/
+int gemtk_keybd2ascii( int keybd, int shift);
+
+/** set VDI clip area by passing an GRECT */
+void gemtk_clip_grect(VdiHdl vh, GRECT *rect);
+
+void gemtk_wind_get_str(short aes_handle, short mode, char *str, int len);
+
+/* send application message */
+void gemtk_send_msg(short msg_type, short data2, short data3, short data4,
+ short data5, short data6, short data7);
+
+
+#ifndef POINT_WITHIN
+# define POINT_WITHIN(_x,_y, r) ((_x >= r.g_x) && (_x <= r.g_x + r.g_w ) \
+ && (_y >= r.g_y) && (_y <= r.g_y + r.g_h))
+#endif
+
+#ifndef RC_WITHIN
+# define RC_WITHIN(a,b) \
+ (((a)->g_x >= (b)->g_x) \
+ && (((a)->g_x + (a)->g_w) <= ((b)->g_x + (b)->g_w))) \
+ && (((a)->g_y >= (b)->g_y) \
+ && (((a)->g_y + (a)->g_h) <= ((b)->g_y + (b)->g_h)))
+#endif
+
+#ifndef MAX
+# define MAX(_a,_b) ((_a>_b) ? _a : _b)
+#endif
+
+#ifndef MIN
+# define MIN(_a,_b) ((_a<_b) ? _a : _b)
+#endif
+
+#ifndef SET_BIT
+# define SET_BIT(field,bit,val) field = (val)?((field)|(bit)):((field) & ~(bit))
+#endif
+
+/* -------------------------------------------------------------------------- */
+/* MultiTOS Drag & Drop */
+/* -------------------------------------------------------------------------- */
+short gemtk_dd_create(short *pipe);
+short gemtk_dd_message(short apid, short fd, short winid, short mx, short my, short kstate, short pipename);
+short gemtk_dd_rexts(short fd, char *exts);
+short gemtk_dd_stry(short fd, char *ext, char *text, char *name, long size);
+void gemtk_dd_close(short fd);
+void gemtk_dd_getsig(long *oldsig);
+void gemtk_dd_setsig(long oldsig);
+short gemtk_dd_open(short ddnam, char ddmsg);
+short gemtk_dd_sexts(short fd, char *exts);
+short gemtk_dd_rtry(short fd, char *name, char *file, char *whichext, long *size);
+short gemtk_dd_reply(short fd, char ack);
+
+/* -------------------------------------------------------------------------- */
+/* AV/VA Protocol Module */
+/* -------------------------------------------------------------------------- */
+int gemtk_av_init(const char *appname);
+void gemtk_av_exit(void);
+bool gemtk_av_send (short message, const char * data1, const char * data2);
+bool gemtk_av_dispatch (short msg[8]);
+
+/* -------------------------------------------------------------------------- */
+/* Message Box module */
+/* -------------------------------------------------------------------------- */
+#define GEMTK_MSG_BOX_ALERT 1
+#define GEMTK_MSG_BOX_CONFIRM 2
+
+short gemtk_msg_box_show(short type, const char * msg);
+
+/* -------------------------------------------------------------------------- */
+/* GUIWIN Module */
+/* -------------------------------------------------------------------------- */
+#define GEMTK_WM_FLAG_PREPROC_WM 0x01 // let guiwin API handle some events
+#define GEMTK_WM_FLAG_RECV_PREPROC_WM 0x02 // get notified even when pre-processed
+#define GEMTK_WM_FLAG_HAS_VTOOLBAR 0x04 // the attached toolbar is vertical
+#define GEMTK_WM_FLAG_CUSTOM_TOOLBAR 0x08 // no internal toolbar handling
+ // (Except considering it's size)
+#define GEMTK_WM_FLAG_CUSTOM_SCROLLING 0x20 // no internal scroller handling
+
+#define GEMTK_WM_FLAG_DEFAULTS \
+ (GEMTK_WM_FLAG_PREPROC_WM | GEMTK_WM_FLAG_RECV_PREPROC_WM)
+
+#define GEMTK_WM_STATUS_ICONIFIED 0x01
+#define GEMTK_WM_STATUS_SHADED 0x02
+
+#define GEMTK_WM_VSLIDER 0x01
+#define GEMTK_WM_HSLIDER 0x02
+#define GEMTK_WM_VH_SLIDER 0x03
+
+/*
+ Message sent to the client application when an AES object is
+ clicked in an window which contains an form.
+
+ Message Parameters:
+ msg[4] = Clicked Object.
+ msg[5] = Number of clicks.
+ msg[6] = Modifier keys.
+*/
+#define GEMTK_WM_WM_FORM_CLICK 1001
+#define GEMTK_WM_WM_FORM_KEY 1002
+
+struct gemtk_window_s;
+
+/** list struct for managing AES windows */
+typedef struct gemtk_window_s GUIWIN;
+
+/** GUIWIN event handler */
+typedef short (*gemtk_wm_event_handler_f)(GUIWIN *gw,
+ EVMULT_OUT *ev_out, short msg[8]);
+
+typedef void (*gemtk_wm_redraw_f)(GUIWIN *win, uint16_t msg, GRECT *clip);
+
+struct gemtk_wm_scroll_info_s {
+
+ /** Definition of a content unit (horizontal) measured in pixel */
+ int x_unit_px;
+
+ /** Definition of content unit (vertical) measured in pixel */
+ int y_unit_px;
+
+ /** Current scroll position (in content units) */
+ int x_pos;
+
+ /** Current scroll position (in content units) */
+ int y_pos;
+
+ /** Size of content (horizontal) measured in content units */
+ int x_units;
+
+ /** Size of content (vertical) measured in content units */
+ int y_units;
+};
+
+/** Well known areas inside the window */
+enum guwin_area_e {
+ GEMTK_WM_AREA_WORK = 0,
+ GEMTK_WM_AREA_TOOLBAR,
+ GEMTK_WM_AREA_CONTENT
+};
+
+/* -------------------------------------------------------------------------- */
+/* GUIWIN functions (document in guiwin.c) */
+/* -------------------------------------------------------------------------- */
+
+short
+gemtk_wm_init(void);
+
+void gemtk_wm_exit(void);
+
+GUIWIN * gemtk_wm_add(short handle, uint32_t flags,
+ gemtk_wm_event_handler_f handler);
+
+GUIWIN * gemtk_wm_find(short handle);
+
+void gemtk_wm_dump_window_info(GUIWIN *win);
+
+short gemtk_wm_remove(GUIWIN *win);
+
+GUIWIN * gemtk_wm_validate_ptr(GUIWIN *win);
+
+GUIWIN *gemtk_wm_link(GUIWIN *win);
+
+GUIWIN *gemtk_wm_unlink(GUIWIN *win);
+
+short gemtk_wm_dispatch_event(EVMULT_IN *ev_in, EVMULT_OUT *ev_out, short msg[8]);
+
+void gemtk_wm_get_grect(GUIWIN *win, enum guwin_area_e mode, GRECT *dest);
+
+short gemtk_wm_get_toolbar_edit_obj(GUIWIN *win);
+
+short gemtk_wm_get_handle(GUIWIN *win);
+
+uint32_t gemtk_wm_get_state(GUIWIN *win);
+
+void gemtk_wm_set_toolbar(GUIWIN *win, OBJECT *toolbar, short idx,
+ uint32_t flags);
+
+void gemtk_wm_set_event_handler(GUIWIN *win,gemtk_wm_event_handler_f cb);
+
+void gemtk_wm_set_user_data(GUIWIN *win, void *data);
+
+void * gemtk_wm_get_user_data(GUIWIN *win);
+
+struct gemtk_wm_scroll_info_s * gemtk_wm_get_scroll_info(GUIWIN *win);
+
+void gemtk_wm_set_scroll_grid(GUIWIN * win, short x, short y);
+
+void gemtk_wm_set_content_units(GUIWIN * win, short x, short y);
+
+void gemtk_wm_set_form(GUIWIN *win, OBJECT *tree, short index);
+
+void gemtk_wm_set_toolbar_size(GUIWIN *win, uint16_t s);
+
+void gemtk_wm_set_toolbar_edit_obj(GUIWIN *win, uint16_t obj, short kreturn);
+
+void gemtk_wm_set_toolbar_redraw_func(GUIWIN *win, gemtk_wm_redraw_f func);
+
+bool gemtk_wm_update_slider(GUIWIN *win, short mode);
+
+void gemtk_wm_scroll(GUIWIN *gw, short orientation, int units, bool refresh);
+
+void gemtk_wm_send_msg(GUIWIN *win, short msgtype, short a, short b, short c,
+ short d);
+
+short gemtk_wm_exec_msg(GUIWIN *win, short msg_type, short a, short b, short c,
+ short d);
+
+void gemtk_wm_exec_redraw(GUIWIN *win, GRECT *area);
+
+VdiHdl gemtk_wm_get_vdi_handle(GUIWIN *win);
+
+short getm_wm_get_toolbar_edit_obj(GUIWIN *win);
+
+bool gemtk_wm_has_intersection(GUIWIN *win, GRECT *work);
+
+void gemtk_wm_toolbar_redraw(GUIWIN *win, uint16_t msg, GRECT *clip);
+
+void gemtk_wm_form_redraw(GUIWIN *gw, GRECT *clip);
+
+void gemtk_wm_clear(GUIWIN *win);
+
+/* -------------------------------------------------------------------------- */
+/* AES SCROLLER MODULE */
+/* -------------------------------------------------------------------------- */
+
+/* -------------------------------------------------------------------------- */
+/* AES TABS MODULE */
+/* -------------------------------------------------------------------------- */
+
+/* -------------------------------------------------------------------------- */
+/* AES OBJECT TREE TOOLS */
+/* -------------------------------------------------------------------------- */
+char gemtk_obj_set_str_safe(OBJECT * tree, short idx, const char *txt);
+char *gemtk_obj_get_text(OBJECT * tree, short idx);
+GRECT * gemtk_obj_screen_rect(OBJECT * tree, short obj);
+bool gemtk_obj_is_inside(OBJECT * tree, short obj, GRECT *area);
+OBJECT *gemtk_obj_get_tree(int idx);
+void gemtk_obj_mouse_sprite(OBJECT *tree, int index);
+OBJECT *gemtk_obj_tree_copy(OBJECT *tree);
+OBJECT * gemtk_obj_create_popup_tree(const char **items, int nitems,
+ char * selected, bool horizontal,
+ int max_width, int max_height);
+void gemtk_obj_destroy_popup_tree(OBJECT * popup);
+#endif // GEMTK_H_INCLUDED
diff --git a/frontends/atari/gemtk/guiwin.c b/frontends/atari/gemtk/guiwin.c
new file mode 100644
index 000000000..ea0f8f917
--- /dev/null
+++ b/frontends/atari/gemtk/guiwin.c
@@ -0,0 +1,1430 @@
+/*
+ * Copyright 2012 Ole Loots <ole@monochrom.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 <stdint.h>
+#include <stdbool.h>
+#include <assert.h>
+
+#include <gem.h>
+#include <gemx.h>
+#include <cflib.h>
+
+#include "gemtk.h"
+#include "vaproto.h"
+
+//#define DEBUG_PRINT(x) printf x
+#define DEBUG_PRINT(x)
+
+struct gemtk_window_s {
+
+ /** The AES handle of the window */
+ short handle;
+
+ /** the generic event handler function for events passed to the client */
+ gemtk_wm_event_handler_f handler_func;
+
+ /** The toolbar redraw function, if any */
+ gemtk_wm_redraw_f toolbar_redraw_func;
+
+ /** window configuration */
+ uint32_t flags;
+
+ /** window state */
+ uint32_t state;
+
+ /** AES Tree used as toolbar */
+ OBJECT *toolbar;
+
+ /** Current edit object selected in the toolbar, if any. */
+ short toolbar_edit_obj;
+
+ /** Current selected object in the toolbar, if any. */
+ short toolbar_focus_obj;
+
+ /** Describes the start of the toolbar tree (usually 0) */
+ short toolbar_idx;
+
+ /** depending on the flag GEMTK_WM_FLAG_HAS_VTOOLBAR this defines the toolbar
+ height or the toolbar width (GEMTK_WM_FLAG_HAS_VTOOLBAR means width).
+ */
+ short toolbar_size;
+
+ /** AES Object tree to be used for windowed dialogs. */
+ OBJECT *form;
+
+ /** Current form edit object, if any. */
+ short form_edit_obj;
+
+ /** Current form focus object, if any */
+ short form_focus_obj;
+
+ /** Describes the start of the form tree */
+ short form_idx;
+
+ /** Scroll state */
+ struct gemtk_wm_scroll_info_s scroll_info;
+
+ /** Arbitary data set by the user */
+ void *user_data;
+
+ /** linked list items */
+ struct gemtk_window_s *next, *prev;
+};
+
+static GUIWIN * winlist;
+static VdiHdl v_vdi_h = -1;
+static short work_out[57];
+
+static void move_rect(GUIWIN * win, GRECT *rect, int dx, int dy)
+{
+ INT16 xy[ 8];
+ long dum = 0L;
+ GRECT g;
+
+ VdiHdl vh = gemtk_wm_get_vdi_handle(win);
+
+ while(!wind_update(BEG_UPDATE));
+ graf_mouse(M_OFF, 0L);
+
+ /* get intersection with screen area */
+ wind_get_grect(0, WF_CURRXYWH, &g);
+ if(!rc_intersect(&g, rect)){
+ goto error;
+ }
+ xy[0] = rect->g_x;
+ xy[1] = rect->g_y;
+ xy[2] = xy[0] + rect->g_w-1;
+ xy[3] = xy[1] + rect->g_h-1;
+ xy[4] = xy[0] + dx;
+ xy[5] = xy[1] + dy;
+ xy[6] = xy[2] + dx;
+ xy[7] = xy[3] + dy;
+ vro_cpyfm(vh, S_ONLY, xy, (MFDB *)&dum, (MFDB *)&dum);
+
+error:
+ graf_mouse(M_ON, 0L);
+ wind_update(END_UPDATE);
+}
+
+/**
+* Handles common events.
+* returns 0 when the event was not handled, 1 otherwise.
+*/
+static short preproc_wm(GUIWIN * gw, EVMULT_OUT *ev_out, short msg[8])
+{
+ GRECT g, g_ro, g2;
+ short retval = 1;
+ int val = 1;
+ struct gemtk_wm_scroll_info_s *slid;
+
+ switch(msg[0]) {
+
+ case WM_HSLID:
+ gemtk_wm_get_grect(gw, GEMTK_WM_AREA_CONTENT, &g);
+ wind_set(gw->handle, WF_HSLIDE, msg[4], 0, 0, 0);
+ slid = gemtk_wm_get_scroll_info(gw);
+ val = (float)(slid->x_units-(g.g_w/slid->x_unit_px))/1000*(float)msg[4];
+ if(val != slid->x_pos) {
+ if (val < slid->x_pos) {
+ val = -(MAX(0, slid->x_pos-val));
+ } else {
+ val = val-slid->x_pos;
+ }
+ gemtk_wm_scroll(gw, GEMTK_WM_HSLIDER, val, false);
+ }
+ break;
+
+ case WM_VSLID:
+ gemtk_wm_get_grect(gw, GEMTK_WM_AREA_CONTENT, &g);
+ wind_set(gw->handle, WF_VSLIDE, msg[4], 0, 0, 0);
+ slid = gemtk_wm_get_scroll_info(gw);
+ val = (float)(slid->y_units-(g.g_h/slid->y_unit_px))/1000*(float)msg[4];
+ if(val != slid->y_pos) {
+ if (val < slid->y_pos) {
+ val = -(slid->y_pos - val);
+ } else {
+ val = val -slid->y_pos;
+ }
+ gemtk_wm_scroll(gw, GEMTK_WM_VSLIDER, val, false);
+ }
+ break;
+
+ case WM_ARROWED:
+ if((gw->flags & GEMTK_WM_FLAG_CUSTOM_SCROLLING) == 0) {
+
+ slid = gemtk_wm_get_scroll_info(gw);
+ gemtk_wm_get_grect(gw, GEMTK_WM_AREA_CONTENT, &g);
+ g_ro = g;
+
+ switch(msg[4]) {
+
+ case WA_UPPAGE:
+ /* scroll page up */
+ gemtk_wm_scroll(gw, GEMTK_WM_VSLIDER, -(g.g_h/slid->y_unit_px),
+ true);
+ break;
+
+ case WA_UPLINE:
+ /* scroll line up */
+ gemtk_wm_scroll(gw, GEMTK_WM_VSLIDER, -1, true);
+ break;
+
+ case WA_DNPAGE:
+ /* scroll page down */
+ gemtk_wm_scroll(gw, GEMTK_WM_VSLIDER, g.g_h/slid->y_unit_px,
+ true);
+ break;
+
+ case WA_DNLINE:
+ /* scroll line down */
+ gemtk_wm_scroll(gw, GEMTK_WM_VSLIDER, +1, true);
+ break;
+
+ case WA_LFPAGE:
+ /* scroll page left */
+ gemtk_wm_scroll(gw, GEMTK_WM_HSLIDER, -(g.g_w/slid->x_unit_px),
+ true);
+ break;
+
+ case WA_LFLINE:
+ /* scroll line left */
+ gemtk_wm_scroll(gw, GEMTK_WM_HSLIDER, -1,
+ true);
+ break;
+
+ case WA_RTPAGE:
+ /* scroll page right */
+ gemtk_wm_scroll(gw, GEMTK_WM_HSLIDER, (g.g_w/slid->x_unit_px),
+ true);
+ break;
+
+ case WA_RTLINE:
+ /* scroll line right */
+ gemtk_wm_scroll(gw, GEMTK_WM_HSLIDER, 1,
+ true);
+ break;
+
+ default:
+ break;
+ }
+ }
+ break;
+
+ case WM_TOPPED:
+ wind_set(gw->handle, WF_TOP, 1, 0, 0, 0);
+ break;
+
+ case WM_MOVED:
+ wind_get_grect(gw->handle, WF_CURRXYWH, &g);
+ wind_set(gw->handle, WF_CURRXYWH, msg[4], msg[5], g.g_w, g.g_h);
+
+ if (gw->form) {
+
+ gemtk_wm_get_grect(gw, GEMTK_WM_AREA_CONTENT, &g);
+ slid = gemtk_wm_get_scroll_info(gw);
+
+ gw->form[gw->form_idx].ob_x = g.g_x -
+ (slid->x_pos * slid->x_unit_px);
+
+ gw->form[gw->form_idx].ob_y = g.g_y -
+ (slid->y_pos * slid->y_unit_px);
+ }
+
+ break;
+
+ case WM_SIZED:
+ case WM_REPOSED:
+ wind_get_grect(gw->handle, WF_FULLXYWH, &g2);
+ wind_get_grect(gw->handle, WF_CURRXYWH, &g);
+ g.g_w = MIN(msg[6], g2.g_w);
+ g.g_h = MIN(msg[7], g2.g_h);
+ if(g2.g_w != g.g_w || g2.g_h != g.g_h) {
+ wind_set(gw->handle, WF_CURRXYWH, g.g_x, g.g_y, g.g_w, g.g_h);
+ if((gw->flags & GEMTK_WM_FLAG_CUSTOM_SCROLLING) == 0) {
+ if(gemtk_wm_update_slider(gw, GEMTK_WM_VH_SLIDER)) {
+ gemtk_wm_exec_redraw(gw, NULL);
+ }
+ }
+ }
+
+
+ break;
+
+ case WM_FULLED:
+ wind_get_grect(DESKTOP_HANDLE, WF_WORKXYWH, &g);
+ wind_get_grect(gw->handle, WF_CURRXYWH, &g2);
+ if(g.g_w == g2.g_w && g.g_h == g2.g_h) {
+ wind_get_grect(gw->handle, WF_PREVXYWH, &g);
+ }
+ wind_set_grect(gw->handle, WF_CURRXYWH, &g);
+ if((gw->flags & GEMTK_WM_FLAG_CUSTOM_SCROLLING) == 0) {
+ if(gemtk_wm_update_slider(gw, GEMTK_WM_VH_SLIDER)) {
+ gemtk_wm_exec_redraw(gw, NULL);
+ }
+ }
+ break;
+
+ case WM_ICONIFY:
+ wind_set(gw->handle, WF_ICONIFY, msg[4], msg[5], msg[6], msg[7]);
+ gw->state |= GEMTK_WM_STATUS_ICONIFIED;
+ break;
+
+ case WM_UNICONIFY:
+ wind_set(gw->handle, WF_UNICONIFY, msg[4], msg[5], msg[6], msg[7]);
+ gw->state &= ~(GEMTK_WM_STATUS_ICONIFIED);
+ break;
+
+ case WM_SHADED:
+ gw->state |= GEMTK_WM_STATUS_SHADED;
+ break;
+
+ case WM_UNSHADED:
+ gw->state &= ~(GEMTK_WM_STATUS_SHADED);
+ break;
+
+ case WM_REDRAW:
+ if ((gw->flags & GEMTK_WM_FLAG_CUSTOM_TOOLBAR) == 0
+ && (gw->toolbar != NULL)) {
+ g.g_x = msg[4];
+ g.g_y = msg[5];
+ g.g_w = msg[6];
+ g.g_h = msg[7];
+ if((gw->state & GEMTK_WM_STATUS_ICONIFIED) == 0){
+ gemtk_wm_toolbar_redraw(gw, WM_REDRAW, &g);
+ }
+ }
+ if (gw->form != NULL) {
+ g.g_x = msg[4];
+ g.g_y = msg[5];
+ g.g_w = msg[6];
+ g.g_h = msg[7];
+ gemtk_wm_form_redraw(gw, &g);
+ }
+ break;
+
+ default:
+ retval = 0;
+ break;
+
+ }
+
+ return(retval);
+}
+
+/**
+* Preprocess mouse events
+*/
+static short preproc_mu_button(GUIWIN * gw, EVMULT_OUT *ev_out, short msg[8])
+{
+ short retval = 0, obj_idx = 0;
+
+ DEBUG_PRINT(("preproc_mu_button\n"));
+
+ // toolbar handling:
+ if ((gw->flags & GEMTK_WM_FLAG_CUSTOM_TOOLBAR) == 0
+ && gw->toolbar != NULL) {
+
+ GRECT tb_area;
+
+ gemtk_wm_get_grect(gw, GEMTK_WM_AREA_TOOLBAR, &tb_area);
+
+ if (POINT_WITHIN(ev_out->emo_mouse.p_x,
+ ev_out->emo_mouse.p_y, tb_area)) {
+
+ gw->toolbar[gw->toolbar_idx].ob_x = tb_area.g_x;
+ gw->toolbar[gw->toolbar_idx].ob_y = tb_area.g_y;
+ obj_idx = objc_find(gw->toolbar,
+ gw->toolbar_idx, 8,
+ ev_out->emo_mouse.p_x,
+ ev_out->emo_mouse.p_y);
+
+ gw->toolbar_focus_obj = obj_idx;
+
+ DEBUG_PRINT(("Toolbar index: %d\n", obj_idx));
+ if (obj_idx > -1
+ && (gw->toolbar[obj_idx].ob_state & OS_DISABLED)== 0
+ && ((gw->flags & GEMTK_WM_FLAG_CUSTOM_TOOLBAR) == 0)) {
+
+ uint16_t type = (gw->toolbar[obj_idx].ob_type & 0xFF);
+ uint16_t nextobj;
+
+ DEBUG_PRINT(("toolbar item type: %d, toolbar_edit_obj: %d\n",
+ type, gw->toolbar_edit_obj));
+ // Report mouse click to the tree:
+ retval = form_wbutton(gw->toolbar, gw->toolbar_focus_obj,
+ ev_out->emo_mclicks, &nextobj,
+ gw->handle);
+ if (nextobj == obj_idx
+ && (type == G_FTEXT || type == G_FBOXTEXT)) {
+ gw->toolbar_edit_obj = obj_idx;
+ }
+ else {
+ gw->toolbar_edit_obj = -1;
+ }
+ }
+
+ // send WM_TOOLBAR message
+ short oldevents = ev_out->emo_events;
+ short msg_out[8] = {WM_TOOLBAR, gl_apid,
+ 0, gw->handle,
+ obj_idx, ev_out->emo_mclicks,
+ ev_out->emo_kmeta, ev_out->emo_mbutton
+ };
+ ev_out->emo_events = MU_MESAG;
+ // notify the window about toolbar click:
+ gw->handler_func(gw, ev_out, msg_out);
+ ev_out->emo_events = oldevents;
+ retval = 1;
+ } else {
+ if (gw->toolbar_edit_obj != -1) {
+ gw->toolbar_edit_obj = -1;
+ }
+ }
+ }
+
+ if (gw->form != NULL) {
+
+ GRECT content_area;
+ struct gemtk_wm_scroll_info_s *slid;
+
+ DEBUG_PRINT(("preproc_mu_button: handling form click.\n"));
+
+ gemtk_wm_get_grect(gw, GEMTK_WM_AREA_CONTENT, &content_area);
+
+ if (POINT_WITHIN(ev_out->emo_mouse.p_x,
+ ev_out->emo_mouse.p_y, content_area)) {
+
+ slid = gemtk_wm_get_scroll_info(gw);
+
+ // adjust form position (considering window and scroll position):
+ gw->form[gw->form_idx].ob_x = content_area.g_x -
+ (slid->x_pos * slid->x_unit_px);
+ gw->form[gw->form_idx].ob_y = content_area.g_y -
+ (slid->y_pos * slid->y_unit_px);
+
+ obj_idx = objc_find(gw->form, gw->form_idx, 8,
+ ev_out->emo_mouse.p_x, ev_out->emo_mouse.p_y);
+ gw->form_focus_obj = obj_idx;
+ DEBUG_PRINT(("Window Form click, obj: %d\n", gw->form_focus_obj));
+ if (obj_idx > -1
+ && (gw->form[obj_idx].ob_state & OS_DISABLED)== 0) {
+
+ uint16_t type = (gw->form[obj_idx].ob_type & 0xFF);
+ uint16_t nextobj;
+
+ DEBUG_PRINT(("type: %d\n", type));
+
+ retval = form_wbutton(gw->form, gw->form_focus_obj,
+ ev_out->emo_mclicks, &nextobj,
+ gw->handle);
+
+ if (nextobj == obj_idx
+ && (type == G_FTEXT || type == G_FBOXTEXT)) {
+ gw->form_edit_obj = obj_idx;
+ }
+ else {
+ gw->form_edit_obj = -1;
+ }
+
+ short oldevents = ev_out->emo_events;
+ short msg_out[8] = { GEMTK_WM_WM_FORM_CLICK, gl_apid,
+ 0, gw->handle,
+ gw->form_focus_obj, ev_out->emo_mclicks,
+ ev_out->emo_kmeta, 0
+ };
+ ev_out->emo_events = MU_MESAG;
+ // notify the window about form click:
+ gw->handler_func(gw, ev_out, msg_out);
+ ev_out->emo_events = oldevents;
+ retval = 1;
+ evnt_timer(150);
+ }
+ }
+ else {
+ gw->form_edit_obj = -1;
+
+ }
+ }
+
+ return(retval);
+}
+
+/**
+* Preprocess keyboard events (for forms/toolbars)
+*/
+static short preproc_mu_keybd(GUIWIN * gw, EVMULT_OUT *ev_out, short msg[8])
+{
+ short retval = 0;
+
+ if ((gw->toolbar != NULL) && (gw->toolbar_edit_obj > -1)) {
+
+ short next_edit_obj = gw->toolbar_edit_obj;
+ short next_char = -1;
+ short edit_idx;
+ short r;
+
+ DEBUG_PRINT(("%s, gw: %p, toolbar_edit_obj: %d\n", __FUNCTION__, gw,
+ gw->toolbar_edit_obj));
+
+ r = form_wkeybd(gw->toolbar, gw->toolbar_edit_obj, next_edit_obj,
+ ev_out->emo_kreturn,
+ &next_edit_obj, &next_char, gw->handle);
+
+ if (next_edit_obj != gw->toolbar_edit_obj) {
+ gemtk_wm_set_toolbar_edit_obj(gw, next_edit_obj,
+ ev_out->emo_kreturn);
+ } else {
+ if (next_char > 13) {
+ r = objc_wedit(gw->toolbar, gw->toolbar_edit_obj,
+ ev_out->emo_kreturn, &edit_idx,
+ EDCHAR, gw->handle);
+ }
+ }
+ //retval = 1;
+ /*gemtk_wm_send_msg(gw, GEMTK_WM_WM_FORM_KEY, gw->toolbar_edit_obj,
+ ev_out->emo_kreturn, 0, 0);*/
+ }
+
+ if((gw->form != NULL) && (gw->form_edit_obj > -1) ) {
+
+ short next_edit_obj = gw->form_edit_obj;
+ short next_char = -1;
+ short edit_idx;
+ short r;
+
+ r = form_wkeybd(gw->form, gw->form_edit_obj, next_edit_obj,
+ ev_out->emo_kreturn,
+ &next_edit_obj, &next_char, gw->handle);
+
+ if (next_edit_obj != gw->form_edit_obj) {
+
+ if(gw->form_edit_obj != -1) {
+ objc_wedit(gw->form, gw->form_edit_obj,
+ ev_out->emo_kreturn, &edit_idx,
+ EDEND, gw->handle);
+ }
+
+ gw->form_edit_obj = next_edit_obj;
+
+ objc_wedit(gw->form, gw->form_edit_obj,
+ ev_out->emo_kreturn, &edit_idx,
+ EDINIT, gw->handle);
+ } else {
+ if(next_char > 13)
+ r = objc_wedit(gw->form, gw->form_edit_obj,
+ ev_out->emo_kreturn, &edit_idx,
+ EDCHAR, gw->handle);
+ }
+ }
+ return(retval);
+}
+
+/**
+* Default toolbar redraw function
+*/
+static void std_toolbar_redraw(GUIWIN *gw, uint16_t msg, GRECT *clip)
+{
+ GRECT g, tb_area;
+
+ gemtk_wm_get_grect(gw, GEMTK_WM_AREA_TOOLBAR, &tb_area);
+
+ assert(gw->toolbar);
+ assert(gw->toolbar_idx >= 0);
+
+ // Update object position:
+ gw->toolbar[gw->toolbar_idx].ob_x = tb_area.g_x;
+ gw->toolbar[gw->toolbar_idx].ob_y = tb_area.g_y;
+ gw->toolbar[gw->toolbar_idx].ob_width = tb_area.g_w;
+ gw->toolbar[gw->toolbar_idx].ob_height = tb_area.g_h;
+
+ wind_get_grect(gw->handle, WF_FIRSTXYWH, &g);
+ while (g.g_h > 0 || g.g_w > 0) {
+ if(rc_intersect(clip, &g)) {
+ objc_draw(gw->toolbar, gw->toolbar_idx, 8, g.g_x, g.g_y,
+ g.g_w, g.g_h);
+
+ }
+ wind_get_grect(gw->handle, WF_NEXTXYWH, &g);
+ }
+}
+
+/**
+* Event Dispatcher function. The guiwin API doesn't own an event loop,
+* so you have to inform it for every event that you want it to handle.
+*/
+short gemtk_wm_dispatch_event(EVMULT_IN *ev_in, EVMULT_OUT *ev_out, short msg[8])
+{
+ GUIWIN *dest;
+ short retval = 0;
+ bool handler_called = false;
+
+ if( (ev_out->emo_events & MU_MESAG) != 0 ) {
+ DEBUG_PRINT(("gemtk_wm_handle_event_multi_fast: %d (%x)\n", msg[0],
+ msg[0]));
+ switch (msg[0]) {
+ case WM_REDRAW:
+ case WM_CLOSED:
+ case WM_TOPPED:
+ case WM_ARROWED:
+ case WM_HSLID:
+ case WM_VSLID:
+ case WM_FULLED:
+ case WM_SIZED:
+ case WM_REPOSED:
+ case WM_MOVED:
+ case WM_NEWTOP:
+ case WM_UNTOPPED:
+ case WM_ONTOP:
+ case WM_BOTTOM:
+ case WM_ICONIFY:
+ case WM_UNICONIFY:
+ case WM_ALLICONIFY:
+ case WM_TOOLBAR:
+ case AP_DRAGDROP:
+ case AP_TERM:
+ case AP_TFAIL:
+ dest = gemtk_wm_find(msg[3]);
+ if (dest) {
+ DEBUG_PRINT(("Found WM_ dest: %p (%d), flags: %d, cb: %p\n",
+ dest, dest->handle, dest->flags,
+ dest->handler_func));
+ if (dest->flags&GEMTK_WM_FLAG_PREPROC_WM) {
+ retval = preproc_wm(dest, ev_out, msg);
+ if(((retval == 0)||(dest->flags&GEMTK_WM_FLAG_RECV_PREPROC_WM))) {
+ retval = dest->handler_func(dest, ev_out, msg);
+ handler_called = true;
+ }
+ } else {
+ if (dest->handler_func) {
+ retval = dest->handler_func(dest, ev_out, msg);
+ handler_called = true;
+ }
+ }
+
+ }
+ break;
+// TODO: check code with Thing! Desktop
+/*
+ We receive VA_PROTOSTATUS but AV_START doesn't seem to cause
+ an TeraDesk response. Check if something happens with Thing!
+ Desktop.
+
+ case VA_PROTOSTATUS:
+ case VA_VIEWED:
+ case AV_STARTED:
+ gemtk_av_dispatch(msg);
+ break;
+*/
+ }
+ } else {
+
+ short h_aes;
+ h_aes = wind_find(ev_out->emo_mouse.p_x, ev_out->emo_mouse.p_y);
+ if(h_aes > 0 && (ev_out->emo_events != MU_TIMER)) {
+
+ dest = gemtk_wm_find(h_aes);
+
+ if (dest == NULL || dest->handler_func == NULL)
+ return(0);
+
+ DEBUG_PRINT(("Found Event receiver GUIWIN: %p (%d), flags: %d, cb: %p\n",
+ dest, dest->handle, dest->flags, dest->handler_func));
+
+ if ((ev_out->emo_events & MU_BUTTON) != 0) {
+ DEBUG_PRINT(("gemtk_wm_handle_event_multi_fast: MU_BUTTON -> "
+ "%d / %d\n", ev_out->emo_mouse.p_x,
+ ev_out->emo_mouse.p_y));
+ retval = preproc_mu_button(dest, ev_out, msg);
+ if(retval != 0) {
+ handler_called = true;
+ }
+ }
+
+ if ((ev_out->emo_events & MU_KEYBD)) {
+ DEBUG_PRINT(("gemtk_wm_handle_event_multi_fast: MU_KEYBD -> %x\n",
+ ev_out->emo_kreturn));
+ retval = preproc_mu_keybd(dest, ev_out, msg);
+ if(retval != 0) {
+ handler_called = true;
+ }
+ }
+
+ if (handler_called==false) {
+ retval = dest->handler_func(dest, ev_out, msg);
+ }
+ }
+ }
+
+ return(retval);
+}
+
+/**
+* Initialises the guiwin API
+*/
+short gemtk_wm_init(void)
+{
+ if(v_vdi_h == -1) {
+ short dummy;
+ short work_in[12] = {Getrez()+2,1,1,1,1,1,1,1,1,1,2,1};
+ v_vdi_h=graf_handle(&dummy, &dummy, &dummy, &dummy);
+ v_opnvwk(work_in, &v_vdi_h, work_out);
+ }
+ return(0);
+}
+
+void gemtk_wm_exit(void)
+{
+ v_clsvwk(v_vdi_h);
+}
+
+/**
+* Adds and AES handle to the guiwin list and creates and GUIWIN management
+* structure.
+*
+* \param handle The AES handle
+* \param flags Creation flags, configures how the AES window is handled
+* \param cb event handler function for that window
+*/
+GUIWIN * gemtk_wm_add(short handle, uint32_t flags, gemtk_wm_event_handler_f cb)
+{
+
+ GUIWIN *win = calloc(1, sizeof(GUIWIN));
+
+ assert(win!=NULL);
+ DEBUG_PRINT(("gemtk_wm_add: %d, %p, cb: %p\n", handle, win, cb));
+
+ win->handle = handle;
+ win->handler_func = cb;
+ win->flags = flags;
+ gemtk_wm_link(win);
+
+ DEBUG_PRINT(("Added guiwin: %p, tb: %p\n", win, win->toolbar));
+ return(win);
+}
+
+/**
+* Returns an GUIWIN* for AES handle, when that AES window is managed by gemtk_wm
+*/
+GUIWIN *gemtk_wm_find(short handle)
+{
+ GUIWIN *g;
+ DEBUG_PRINT(("guiwin search handle: %d\n", handle));
+ for (g = winlist; g != NULL; g=g->next) {
+ if(g->handle == handle) {
+ DEBUG_PRINT(("guiwin found handle: %p\n", g));
+ return(g);
+ }
+ }
+ return(NULL);
+}
+
+void gemtk_wm_dump_window_info(GUIWIN *win)
+{
+
+
+
+ char title[255];
+ GRECT work_area;
+ GRECT curr_area;
+ GRECT gemtk_work_area;
+ GRECT gemtk_toolbar_area;
+ GRECT gemtk_free_area;
+ short handle;
+ struct gemtk_wm_scroll_info_s *slid;
+
+ handle = gemtk_wm_get_handle(win);
+
+ assert(handle);
+
+ gemtk_wind_get_str(handle, WF_NAME, title, 255);
+ wind_get_grect(handle, WF_WORKXYWH, &work_area);
+ wind_get_grect(handle, WF_CURRXYWH, &curr_area);
+ gemtk_wm_get_grect(win, GEMTK_WM_AREA_CONTENT, &gemtk_free_area);
+ gemtk_wm_get_grect(win, GEMTK_WM_AREA_WORK, &gemtk_work_area);
+ gemtk_wm_get_grect(win, GEMTK_WM_AREA_TOOLBAR, &gemtk_toolbar_area);
+ slid = gemtk_wm_get_scroll_info(win);
+
+ printf ("GEMTK Window: %p (AES handle: %d)\n", win, win->handle);
+ printf ("Title: %s\n", title);
+ GEMTK_DBG_GRECT ("WF_WORKXYWH: \n", &work_area)
+ GEMTK_DBG_GRECT ("WF_CURRXYWH: \n", &curr_area)
+ GEMTK_DBG_GRECT ("GEMTK_WM_AREA_CONTENT:\n", &gemtk_free_area)
+ GEMTK_DBG_GRECT ("GEMTK_WM_AREA_WORK:\n", &gemtk_work_area)
+ GEMTK_DBG_GRECT ("GEMTK_WM_AREA_TOOLBAR:\n", &gemtk_toolbar_area)
+ printf ("Slider X pos: %d\n", slid->x_pos);
+ printf ("Slider Y pos: %d\n", slid->y_pos);
+ printf ("Slider X units: %d\n", slid->x_unit_px);
+ printf ("Slider Y units: %d\n", slid->y_unit_px);
+
+
+#undef DBG_GRECT
+};
+
+/**
+* Check's if the pointer is managed by the guiwin API.
+*/
+GUIWIN *gemtk_wm_validate_ptr(GUIWIN *win)
+{
+ GUIWIN *g;
+ for( g = winlist; g != NULL; g=g->next ) {
+ DEBUG_PRINT(("guiwin gemtk_wm_validate_ptr check: %p\n", g));
+ if(g == win) {
+ DEBUG_PRINT(("gemtk_wm_validate_ptr valid: %p\n", g));
+ return(g);
+ }
+ }
+ return(NULL);
+}
+
+/**
+* Add the GUIWIN to the list of handled windows.
+*/
+GUIWIN *gemtk_wm_link(GUIWIN *win)
+{
+ /* Make sure the window is not linked: */
+ GUIWIN *win_val = gemtk_wm_validate_ptr(win);
+ if(win_val){
+ DEBUG_PRINT(("GUIWIN %p is already linked!\n", win));
+ return(NULL);
+ }
+
+ if (winlist == NULL) {
+ winlist = win;
+ win->next = NULL;
+ win->prev = NULL;
+ } else {
+ GUIWIN *tmp = winlist;
+ while( tmp->next != NULL ) {
+ tmp = tmp->next;
+ }
+ tmp->next = win;
+ win->prev = tmp;
+ win->next = NULL;
+ }
+ return(win);
+}
+
+/**
+* Remove the GUIWIN from the list of handled windows.
+*/
+GUIWIN *gemtk_wm_unlink(GUIWIN *win)
+{
+ GUIWIN * win_val;
+
+ /* Make sure the window is linked: */
+ win_val = gemtk_wm_validate_ptr(win);
+ if (win_val == NULL){
+ DEBUG_PRINT(("GUIWIN %p is not linked!\n", win));
+ return(NULL);
+ }
+
+
+ /* unlink the window: */
+ if(win->prev != NULL ) {
+ win->prev->next = win->next;
+ } else {
+ winlist = win->next;
+ }
+ if (win->next != NULL) {
+ win->next->prev = win->prev;
+ }
+ return(win);
+}
+
+/**
+* Remove an GUIWIN from the list of managed windows and free the GUIWIN.
+* Call this when the AES window is closed or deleted.
+*/
+short gemtk_wm_remove(GUIWIN *win)
+{
+ gemtk_wm_unlink(win);
+ DEBUG_PRINT(("guiwin free: %p\n", win));
+ free(win);
+ return(0);
+}
+
+/** Calculate & get a well known area within the GUIWIN.
+* \param win The GUIWIN ptr.
+* \param mode Specifies the area to retrieve.
+* \param dest The calculated rectangle.
+*/
+void gemtk_wm_get_grect(GUIWIN *win, enum guwin_area_e mode, GRECT *dest)
+{
+
+ assert(win != NULL);
+
+ wind_get_grect(win->handle, WF_WORKXYWH, dest);
+
+ if (mode == GEMTK_WM_AREA_CONTENT) {
+ GRECT tb_area;
+ gemtk_wm_get_grect(win, GEMTK_WM_AREA_TOOLBAR, &tb_area);
+ if (win->flags & GEMTK_WM_FLAG_HAS_VTOOLBAR) {
+ dest->g_x += tb_area.g_w;
+ dest->g_w -= tb_area.g_w;
+ }
+ else {
+ dest->g_y += tb_area.g_h;
+ dest->g_h -= tb_area.g_h;
+ }
+ } else if (mode == GEMTK_WM_AREA_TOOLBAR) {
+ if (win->toolbar) {
+ if (win->flags & GEMTK_WM_FLAG_HAS_VTOOLBAR) {
+ dest->g_w = win->toolbar_size;
+ } else {
+ dest->g_h = win->toolbar_size;
+ }
+ }
+ else {
+ dest->g_w = 0;
+ dest->g_h = 0;
+ }
+ }
+}
+
+
+/**
+* Scroll the content area (GEMTK_WM_AREA_CONTENT) in the specified dimension
+* (GEMTK_WM_VSLIDER, GEMTK_WM_HSLIDER)
+* \param win The GUIWIN
+* \param orientation GEMTK_WM_VSLIDER or GEMTK_WM_HSLIDER
+* \param units the amout to scroll (pass negative values to scroll up)
+* \param refresh Sliders will be updated when this flag is set
+*/
+void gemtk_wm_scroll(GUIWIN *win, short orientation, int units, bool refresh)
+{
+ struct gemtk_wm_scroll_info_s *slid = gemtk_wm_get_scroll_info(win);
+ int oldpos = 0, newpos = 0, vis_units=0, pix = 0;
+ int abs_pix = 0;
+ GRECT *redraw=NULL, g, g_ro;
+
+ gemtk_wm_get_grect(win, GEMTK_WM_AREA_CONTENT, &g);
+ g_ro = g;
+
+ if (orientation == GEMTK_WM_VSLIDER) {
+ pix = units*slid->y_unit_px;
+ abs_pix = abs(pix);
+ oldpos = slid->y_pos;
+ vis_units = g.g_h/slid->y_unit_px;
+ newpos = slid->y_pos = MIN(slid->y_units-vis_units,
+ MAX(0, slid->y_pos+units));
+ if(newpos < 0) {
+ newpos = slid->y_pos = 0;
+ }
+ if(oldpos == newpos)
+ return;
+
+ if (units>=vis_units || gemtk_wm_has_intersection(win, &g_ro)) {
+ // send complete redraw
+ redraw = &g_ro;
+ } else {
+ // only adjust ypos when scrolling down:
+ if(pix < 0 ) {
+ // blit screen area:
+ g.g_h -= abs_pix;
+ move_rect(win, &g, 0, abs_pix);
+ g.g_y = g_ro.g_y;
+ g.g_h = abs_pix;
+ redraw = &g;
+ } else {
+ // blit screen area:
+ g.g_y += abs_pix;
+ g.g_h -= abs_pix;
+ move_rect(win, &g, 0, -abs_pix);
+ g.g_y = g_ro.g_y + g_ro.g_h - abs_pix;
+ g.g_h = abs_pix;
+ redraw = &g;
+ }
+ }
+ } else {
+ pix = units*slid->x_unit_px;
+ abs_pix = abs(pix);
+ oldpos = slid->x_pos;
+ vis_units = g.g_w/slid->x_unit_px;
+ newpos = slid->x_pos = MIN(slid->x_units-vis_units,
+ MAX(0, slid->x_pos+units));
+
+ if(newpos < 0) {
+ newpos = slid->x_pos = 0;
+ }
+
+ if(oldpos == newpos)
+ return;
+ if (units>=vis_units || gemtk_wm_has_intersection(win, &g_ro)) {
+ // send complete redraw
+ redraw = &g_ro;
+ } else {
+ // only adjust ypos when scrolling down:
+ if(pix < 0 ) {
+ // blit screen area:
+ g.g_w -= abs_pix;
+ move_rect(win, &g, abs_pix, 0);
+ g.g_x = g_ro.g_x;
+ g.g_w = abs_pix;
+ redraw = &g;
+ } else {
+ // blit screen area:
+ g.g_x += abs_pix;
+ g.g_w -= abs_pix;
+ move_rect(win, &g, -abs_pix, 0);
+ g.g_x = g_ro.g_x + g_ro.g_w - abs_pix;
+ g.g_w = abs_pix;
+ redraw = &g;
+ }
+ }
+ }
+
+ if (refresh) {
+ gemtk_wm_update_slider(win, orientation);
+ }
+
+ if ((redraw != NULL) && (redraw->g_h > 0)) {
+ gemtk_wm_exec_redraw(win, redraw);
+ }
+}
+
+/**
+* Refresh the sliders of the window.
+* \param win the GUIWIN
+* \param mode bitmask, valid bits: GEMTK_WM_VSLIDER, GEMTK_WM_HSLIDER
+*/
+bool gemtk_wm_update_slider(GUIWIN *win, short mode)
+{
+ GRECT viewport;
+ struct gemtk_wm_scroll_info_s * slid;
+ unsigned long size, pos;
+ int old_x, old_y;
+
+ short handle = gemtk_wm_get_handle(win);
+ gemtk_wm_get_grect(win, GEMTK_WM_AREA_CONTENT, &viewport);
+ slid = gemtk_wm_get_scroll_info(win);
+
+ old_x = slid->x_pos;
+ old_y = slid->y_pos;
+
+ // TODO: check if the window has sliders of that direction...?
+
+ if((mode & GEMTK_WM_VSLIDER) && (slid->y_unit_px > 0)) {
+ if ( slid->y_units < (long)viewport.g_h/slid->y_unit_px) {
+ size = 1000L;
+ } else
+ size = MAX( 50L, (unsigned long)viewport.g_h*1000L/
+ (unsigned long)(slid->y_unit_px*slid->y_units));
+ wind_set(handle, WF_VSLSIZE, (int)size, 0, 0, 0);
+
+ if (slid->y_units > (long)viewport.g_h/slid->y_unit_px) {
+ pos = (unsigned long)slid->y_pos *1000L/
+ (unsigned long)(slid->y_units-viewport.g_h/slid->y_unit_px);
+ wind_set(handle, WF_VSLIDE, (int)pos, 0, 0, 0);
+ } else if (slid->y_pos) {
+ slid->y_pos = 0;
+ wind_set(handle, WF_VSLIDE, 0, 0, 0, 0);
+ }
+ }
+ if((mode & GEMTK_WM_HSLIDER) && (slid->x_unit_px > 0)) {
+ if ( slid->x_units < (long)viewport.g_w/slid->x_unit_px)
+ size = 1000L;
+ else
+ size = MAX( 50L, (unsigned long)viewport.g_w*1000L/
+ (unsigned long)(slid->x_unit_px*slid->x_units));
+ wind_set(handle, WF_HSLSIZE, (int)size, 0, 0, 0);
+
+ if( slid->x_units > (long)viewport.g_w/slid->x_unit_px) {
+ pos = (unsigned long)slid->x_pos*1000L/
+ (unsigned long)(slid->x_units-viewport.g_w/slid->x_unit_px);
+ wind_set(handle, WF_HSLIDE, (int)pos, 0, 0, 0);
+ } else if (slid->x_pos) {
+ slid->x_pos = 0;
+ wind_set(handle, WF_HSLIDE, 0, 0, 0, 0);
+ }
+ }
+
+ if(old_x != slid->x_pos || old_y != slid->y_pos) {
+ return(true);
+ }
+ return(false);
+}
+
+/**
+* Return the AES handle for the GUIWIN.
+*/
+short gemtk_wm_get_handle(GUIWIN *win)
+{
+ return(win->handle);
+}
+
+/**
+* Return the VDI handle for an GUIWIN.
+*/
+VdiHdl gemtk_wm_get_vdi_handle(GUIWIN *win)
+{
+ return(v_vdi_h);
+}
+
+/**
+* Returns the state bitmask of the window
+*/
+uint32_t gemtk_wm_get_state(GUIWIN *win)
+{
+ return(win->state);
+}
+
+/**
+* Set and new event handler function.
+*/
+void gemtk_wm_set_event_handler(GUIWIN *win,gemtk_wm_event_handler_f cb)
+{
+ win->handler_func = cb;
+}
+
+/**
+* Configure the window so that it shows an toolbar or at least reserves
+* an area to draw an toolbar.
+* \param win The GUIWIN
+* \param toolbar the AES form
+* \param idx index within the toolbar tree (0 in most cases...)
+* \param flags optional configuration flags
+*/
+//TODO: document flags
+void gemtk_wm_set_toolbar(GUIWIN *win, OBJECT *toolbar, short idx, uint32_t flags)
+{
+ win->toolbar = toolbar;
+ win->toolbar_idx = idx;
+ win->toolbar_edit_obj = -1;
+ if (flags & GEMTK_WM_FLAG_HAS_VTOOLBAR) {
+ win->flags |= GEMTK_WM_FLAG_HAS_VTOOLBAR;
+ win->toolbar_size = win->toolbar[idx].ob_width;
+ }
+ else {
+ win->toolbar_size = win->toolbar[idx].ob_height;
+ }
+ gemtk_wm_set_toolbar_redraw_func(win, std_toolbar_redraw);
+}
+
+/** Update width/height of the toolbar region
+* \param win the GUIWIN
+* \param s the width or height, depending on the flag GEMTK_WM_FLAG_HAS_VTOOLBAR
+*/
+void gemtk_wm_set_toolbar_size(GUIWIN *win, uint16_t s)
+{
+ win->toolbar_size = s;
+}
+
+short gemtk_wm_get_toolbar_edit_obj(GUIWIN *win)
+{
+ return(win->toolbar_edit_obj);
+}
+
+/** Set the current active edit object */
+void gemtk_wm_set_toolbar_edit_obj(GUIWIN *win, uint16_t obj, short kreturn)
+{
+ short edit_idx;
+
+ DEBUG_PRINT(("%s, win: %p, obj: %d, kret: %d\n", __FUNCTION__,
+ win, obj, kreturn));
+
+ if (obj != win->toolbar_edit_obj) {
+
+ DEBUG_PRINT(("%s, current edit obj: %d\n", __FUNCTION__,
+ win->toolbar_edit_obj));
+
+ if(win->toolbar_edit_obj != -1) {
+ objc_wedit(win->toolbar, win->toolbar_edit_obj, kreturn, &edit_idx,
+ EDEND, win->handle);
+ }
+
+ win->toolbar_edit_obj = obj;
+
+ objc_wedit(win->toolbar, win->toolbar_edit_obj, kreturn, &edit_idx,
+ EDINIT, win->handle);
+ } else {
+ DEBUG_PRINT(("%s, nothing to do!\n", __FUNCTION__));
+ }
+}
+
+/** Set an custom toolbar redraw function which is called instead of
+* default drawing routine.
+* \param win the GUIWIN
+* \param func the custom redraw function
+*/
+void gemtk_wm_set_toolbar_redraw_func(GUIWIN *win, gemtk_wm_redraw_f func)
+{
+ win->toolbar_redraw_func = func;
+}
+
+/**
+* Attach an arbitary pointer to the GUIWIN
+*/
+void gemtk_wm_set_user_data(GUIWIN *win, void *data)
+{
+ win->user_data = data;
+}
+
+/**
+* Retrieve the user_data pointer attached to the GUIWIN.
+*/
+void *gemtk_wm_get_user_data(GUIWIN *win)
+{
+ return(win->user_data);
+}
+
+/** Get the scroll management structure for a GUIWIN
+*/
+struct gemtk_wm_scroll_info_s *gemtk_wm_get_scroll_info(GUIWIN *win) {
+ return(&win->scroll_info);
+}
+
+/**
+* Get the amount of content dimensions within the window
+* which is calculated by using the scroll_info attached to the GUIWIN.
+*/
+void gemtk_wm_set_scroll_grid(GUIWIN * win, short x, short y)
+{
+ struct gemtk_wm_scroll_info_s *slid = gemtk_wm_get_scroll_info(win);
+
+ assert(slid != NULL);
+
+ slid->y_unit_px = x;
+ slid->x_unit_px = y;
+}
+
+
+/** Set the size of the content measured in content units
+* \param win the GUIWIN
+* \param x horizontal size
+* \param y vertical size
+*/
+void gemtk_wm_set_content_units(GUIWIN * win, short x, short y)
+{
+ struct gemtk_wm_scroll_info_s *slid = gemtk_wm_get_scroll_info(win);
+
+ assert(slid != NULL);
+
+ slid->x_units = x;
+ slid->y_units = y;
+}
+
+/** Send an Message to a GUIWIN using AES message pipe
+* \param win the GUIWIN which shall receive the message
+* \param msg_type the WM_ message definition
+* \param a the 4th parameter to appl_write
+* \param b the 5th parameter to appl_write
+* \param c the 6th parameter to appl_write
+* \param d the 7th parameter to appl_write
+*/
+void gemtk_wm_send_msg(GUIWIN *win, short msg_type, short a, short b, short c,
+ short d)
+{
+ short msg[8];
+
+ msg[0] = msg_type;
+ msg[1] = gl_apid;
+ msg[2] = 0;
+ msg[3] = (win != NULL) ? win->handle : 0;
+ msg[4] = a;
+ msg[5] = b;
+ msg[6] = c;
+ msg[7] = d;
+
+ appl_write(gl_apid, 16, &msg);
+}
+
+/** Directly execute an Message to a GUIWIN using the internal dispatcher function.
+* This only works for managed windows which have the,
+ GEMTK_WM_FLAG_PREPROC_WM flag set.
+ This call does not send any AES messages.
+* \param win the GUIWIN which shall receive the message
+* \param msg_type the WM_ message definition
+* \param a the 4th parameter to appl_write
+* \param b the 5th parameter to appl_write
+* \param c the 6th parameter to appl_write
+* \param d the 7th parameter to appl_write
+*/
+short gemtk_wm_exec_msg(GUIWIN *win, short msg_type, short a, short b, short c,
+ short d)
+{
+ short msg[8], retval;
+
+ EVMULT_OUT event_out;
+
+ msg[0] = msg_type;
+ msg[1] = gl_apid;
+ msg[2] = 0;
+ msg[3] = win->handle;
+ msg[4] = a;
+ msg[5] = b;
+ msg[6] = c;
+ msg[7] = d;
+
+ event_out.emo_events = MU_MESAG;
+ retval = preproc_wm(win, &event_out, msg);
+ if (retval == 0 || (win->flags & GEMTK_WM_FLAG_PREPROC_WM) != 0){
+ retval = win->handler_func(win, &event_out, msg);
+ }
+
+ return(retval);
+}
+
+void gemtk_wm_exec_redraw(GUIWIN *win, GRECT *area)
+{
+ GRECT work;
+
+ if (area == NULL) {
+ gemtk_wm_get_grect(win, GEMTK_WM_AREA_WORK, &work);
+ if (work.g_w < 1 || work.g_h < 1) {
+ if (win->toolbar != NULL) {
+ gemtk_wm_get_grect(win, GEMTK_WM_AREA_TOOLBAR, &work);
+ if (work.g_w < 1 || work.g_h < 1) {
+ return;
+ }
+ }
+ }
+ area = &work;
+ }
+
+ gemtk_wm_exec_msg(win, WM_REDRAW, area->g_x, area->g_y, area->g_w,
+ area->g_h);
+}
+
+/** Attach an AES FORM to the GUIWIN, similar feature like the toolbar
+*/
+void gemtk_wm_set_form(GUIWIN *win, OBJECT *tree, short index)
+{
+ DEBUG_PRINT(("Setting form %p (%d) for window %p\n", tree, index, win));
+ win->form = tree;
+ win->form_edit_obj = -1;
+ win->form_focus_obj = -1;
+ win->form_idx = index;
+}
+
+/** Checks if a GUIWIN is overlapped by other windows.
+*/
+bool gemtk_wm_has_intersection(GUIWIN *win, GRECT *work)
+{
+ GRECT area, mywork;
+ bool retval = true;
+
+ if (work == NULL) {
+ gemtk_wm_get_grect(win, GEMTK_WM_AREA_CONTENT, &mywork);
+ work = &mywork;
+ }
+
+ wind_get_grect(win->handle, WF_FIRSTXYWH, &area);
+ while (area.g_w) {
+ //GRECT * ptr = &area;
+ if (RC_WITHIN(work, &area)) {
+ retval = false;
+ }
+ wind_get_grect(win->handle, WF_NEXTXYWH, &area);
+ }
+
+ return(retval);
+}
+
+/** Execute an toolbar redraw
+* \param msg specifies the AES message which initiated the redraw, or 0 when
+* the function was called without AES message context.
+*/
+void gemtk_wm_toolbar_redraw(GUIWIN *gw, uint16_t msg, GRECT *clip)
+{
+ GRECT tb_area, tb_area_ro;
+
+ gemtk_wm_get_grect(gw, GEMTK_WM_AREA_TOOLBAR, &tb_area_ro);
+
+ if(clip == NULL) {
+ clip = &tb_area_ro;
+ }
+
+ tb_area = tb_area_ro;
+
+ if (rc_intersect(clip, &tb_area)) {
+ gw->toolbar_redraw_func(gw, msg, &tb_area);
+ }
+}
+
+/** Execute FORM redraw
+*/
+void gemtk_wm_form_redraw(GUIWIN *gw, GRECT *clip)
+{
+ GRECT area, area_ro, g;
+ struct gemtk_wm_scroll_info_s *slid;
+ //int new_x, new_y, old_x, old_y;
+
+ DEBUG_PRINT(("gemtk_wm_form_redraw\n"));
+
+ // calculate form coordinates, include scrolling:
+ gemtk_wm_get_grect(gw, GEMTK_WM_AREA_CONTENT, &area_ro);
+ slid = gemtk_wm_get_scroll_info(gw);
+
+ // Update form position:
+ gw->form[gw->form_idx].ob_x = area_ro.g_x - (slid->x_pos * slid->x_unit_px);
+ gw->form[gw->form_idx].ob_y = area_ro.g_y - (slid->y_pos * slid->y_unit_px);
+
+ if(clip == NULL) {
+ clip = &area_ro;
+ }
+
+ area = area_ro;
+
+ /* Walk the AES rectangle list and redraw the visible areas of the window:*/
+ if(rc_intersect(clip, &area)) {
+
+ wind_get_grect(gw->handle, WF_FIRSTXYWH, &g);
+ while (g.g_h > 0 || g.g_w > 0) {
+ if(rc_intersect(&area, &g)) {
+ objc_draw(gw->form, gw->form_idx, 8, g.g_x, g.g_y,
+ g.g_w, g.g_h);
+
+ }
+ wind_get_grect(gw->handle, WF_NEXTXYWH, &g);
+ }
+ }
+}
+
+
+/** Fill the content area with white color
+*/
+void gemtk_wm_clear(GUIWIN *win)
+{
+ GRECT area, g;
+ short pxy[4];
+ VdiHdl vh;
+
+ vh = gemtk_wm_get_vdi_handle(win);
+
+ if(win->state & GEMTK_WM_STATUS_ICONIFIED) {
+ // also clear the toolbar area when iconified:
+ gemtk_wm_get_grect(win, GEMTK_WM_AREA_WORK, &area);
+ } else {
+ gemtk_wm_get_grect(win, GEMTK_WM_AREA_CONTENT, &area);
+ }
+
+ vsf_interior(vh, FIS_SOLID);
+ vsf_color(vh, 0);
+ vswr_mode(vh, MD_REPLACE);
+ wind_get_grect(win->handle, WF_FIRSTXYWH, &g);
+ while (g.g_h > 0 || g.g_w > 0) {
+ if(rc_intersect(&area, &g)) {
+ pxy[0] = g.g_x;
+ pxy[1] = g.g_y;
+ pxy[2] = g.g_x+g.g_w-1;
+ pxy[3] = g.g_y+g.g_h-1;
+ v_bar(vh, pxy);
+ }
+ wind_get_grect(win->handle, WF_NEXTXYWH, &g);
+ }
+}
diff --git a/frontends/atari/gemtk/guiwin.h b/frontends/atari/gemtk/guiwin.h
new file mode 100644
index 000000000..6daf16ca9
--- /dev/null
+++ b/frontends/atari/gemtk/guiwin.h
@@ -0,0 +1,4 @@
+#ifndef OPKG_GUI_GUIWIN_H
+#define OPKG_GUI_GUIWIN_
+
+#endif /* OPKG_GUIWIN_H */
diff --git a/frontends/atari/gemtk/msgbox.c b/frontends/atari/gemtk/msgbox.c
new file mode 100644
index 000000000..89ca75a46
--- /dev/null
+++ b/frontends/atari/gemtk/msgbox.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2013 Ole Loots <ole@monochrom.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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <gem.h>
+#include "gemtk.h"
+
+#ifndef min
+# define min(x,y) ((x<y) ? x : y )
+#endif
+
+/***
+ * Display an message box
+ *
+ * \param type Valid values: GEMTK_MSG_BOX_CONFIRM, GEMTK_MSG_BOX_ALERT
+ * \param msg The message / query to display
+ * \return 0 on "No"
+ *
+ */
+short gemtk_msg_box_show(short type, const char * msg)
+{
+ #define GEMTK_MSG_BOX_STR_SIZE 256
+ short retval=0, i=0, z=0, l=0;
+ char c;
+ int len_msg = strlen(msg);
+
+ // TODO: localize strings
+ const char *str_yes = "Yes";
+ const char *str_no = "No";
+ const char *str_ok = "OK";
+ char msg_box_str[GEMTK_MSG_BOX_STR_SIZE];
+ char *dst = msg_box_str;
+
+ memset(msg_box_str, 0, GEMTK_MSG_BOX_STR_SIZE);
+
+ strncat(msg_box_str, "[1]", GEMTK_MSG_BOX_STR_SIZE);
+ strncat(msg_box_str, "[", GEMTK_MSG_BOX_STR_SIZE);
+
+ dst = msg_box_str + strlen(msg_box_str);
+
+ for (i=0; i<min(len_msg,40*5); i++) {
+
+ c = msg[i];
+
+ if(c==0)
+ break;
+
+ if (z==40) {
+ if(l==4){
+ break;
+ }
+ z = 0;
+ l++;
+ *dst = (char)'|';
+ dst++;
+ }
+
+ if ((c=='\r' || c=='\n') && *dst != '|') {
+ if(l==4){
+ break;
+ }
+ z = 0;
+ l++;
+ *dst = '|';
+ dst++;
+ }
+ else {
+ z++;
+ *dst = c;
+ dst++;
+ }
+ }
+ strncat(msg_box_str, "][", GEMTK_MSG_BOX_STR_SIZE);
+
+ if(type == GEMTK_MSG_BOX_CONFIRM){
+ strncat(msg_box_str, str_yes, GEMTK_MSG_BOX_STR_SIZE);
+ strncat(msg_box_str, "|", GEMTK_MSG_BOX_STR_SIZE);
+ strncat(msg_box_str, str_no, GEMTK_MSG_BOX_STR_SIZE);
+ } else {
+ strncat(msg_box_str, str_ok, GEMTK_MSG_BOX_STR_SIZE);
+ }
+ strncat(msg_box_str, "]", GEMTK_MSG_BOX_STR_SIZE);
+
+ retval = form_alert(type, msg_box_str);
+ if(type == GEMTK_MSG_BOX_CONFIRM){
+ if(retval != 1){
+ retval = 0;
+ }
+ }
+ return(retval);
+
+ #undef GEMTK_MSG_BOX_STR_SIZE
+}
diff --git a/frontends/atari/gemtk/msgbox.h b/frontends/atari/gemtk/msgbox.h
new file mode 100644
index 000000000..7a46900ef
--- /dev/null
+++ b/frontends/atari/gemtk/msgbox.h
@@ -0,0 +1,5 @@
+#ifndef GUIMSG_H_INCLUDED
+#define GUIMSG_H_INCLUDED
+
+
+#endif // GUIMSG_H_INCLUDED
diff --git a/frontends/atari/gemtk/objc.c b/frontends/atari/gemtk/objc.c
new file mode 100644
index 000000000..855413e0b
--- /dev/null
+++ b/frontends/atari/gemtk/objc.c
@@ -0,0 +1,522 @@
+/*
+ * Copyright 2013 Ole Loots <ole@monochrom.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/>.
+ *
+ * Module Description:
+ *
+ * AES Object tree tools.
+ *
+ */
+
+#include <assert.h>
+#include "gemtk.h"
+
+char *gemtk_obj_get_text(OBJECT * tree, short idx)
+{
+ static char p[]="";
+
+ switch (tree[idx].ob_type & 0x00FF) {
+ case G_BUTTON:
+ case G_STRING:
+ case G_TITLE:
+ return( tree[idx].ob_spec.free_string);
+ case G_TEXT:
+ case G_BOXTEXT:
+ case G_FTEXT:
+ case G_FBOXTEXT:
+ return (tree[idx].ob_spec.tedinfo->te_ptext);
+ case G_ICON:
+ case G_CICON:
+ return (tree[idx].ob_spec.iconblk->ib_ptext);
+ break;
+
+ default:
+ break;
+ }
+ return (p);
+}
+
+static void set_text(OBJECT *obj, short idx, char * text, int len)
+{
+ char spare[255];
+
+ if( len > 254 )
+ len = 254;
+ if( text != NULL ) {
+ strncpy(spare, text, 254);
+ } else {
+ strcpy(spare, "");
+ }
+
+ set_string(obj, idx, spare);
+}
+
+char gemtk_obj_set_str_safe(OBJECT * tree, short idx, const char *txt)
+{
+ char spare[204];
+ short type = 0;
+ short maxlen = 0;
+
+
+ type = (tree[idx].ob_type & 0xFF);
+ if (type == G_FTEXT || type == G_FBOXTEXT) {
+ TEDINFO *ted = ((TEDINFO *)get_obspec(tree, idx));
+ maxlen = ted->te_tmplen+1;
+ if (maxlen > 200) {
+ maxlen = 200;
+ } else if (maxlen < 0) {
+ maxlen = 0;
+ }
+ } else {
+ assert((type == G_FTEXT) || (type == G_FBOXTEXT));
+ }
+
+ snprintf(spare, maxlen, "%s", txt);
+ set_string(tree, idx, spare);
+
+ return(0);
+}
+
+OBJECT *gemtk_obj_get_tree(int idx)
+{
+
+ OBJECT *tree;
+
+ rsrc_gaddr(R_TREE, idx, &tree);
+
+ return tree;
+}
+
+bool gemtk_obj_is_inside(OBJECT * tree, short obj, GRECT *area)
+{
+ GRECT obj_screen;
+ bool ret = false;
+
+ objc_offset(tree, obj, &obj_screen.g_x, &obj_screen.g_y);
+ obj_screen.g_w = tree[obj].ob_width;
+ obj_screen.g_h = tree[obj].ob_height;
+
+ ret = RC_WITHIN(&obj_screen, area);
+
+ return(ret);
+}
+
+GRECT * gemtk_obj_screen_rect(OBJECT * tree, short obj)
+{
+ static GRECT obj_screen;
+
+ get_objframe(tree, obj, &obj_screen);
+
+ return(&obj_screen);
+}
+
+
+void gemtk_obj_mouse_sprite(OBJECT *tree, int index)
+{
+ MFORM mform;
+ int dum;
+
+ if ((tree[index].ob_type & 0xFF) != G_ICON)
+ return;
+
+ dum = tree[index].ob_spec.iconblk->ib_char;
+ mform . mf_nplanes = 1;
+ mform . mf_fg = (dum>>8)&0x0F;
+ mform . mf_bg = dum>>12;
+ mform . mf_xhot = 0; /* to prevent the mform to "jump" on the */
+ mform . mf_yhot = 0; /* screen (zebulon rules!) */
+
+ for( dum = 0; dum<16; dum ++) {
+ mform . mf_mask[dum] = tree[index].ob_spec.iconblk->ib_pmask[dum];
+ mform . mf_data[dum] = tree[index].ob_spec.iconblk->ib_pdata[dum];
+ }
+ graf_mouse(USER_DEF, &mform);
+}
+
+
+/*
+ * gemtk_obj_tree_copy
+ *
+ * Copy a complete object-tree including all substructures (optional).
+ *
+ * CAUTION: The object-tree *must* have the LASTOB-flag (0x20) set in
+ * it's physically last member.
+ *
+ * BUG: Up to now tree_copy won't copy the color-icon-structure,
+ * because I'm too lazy ;) Maybe I'll do that one day. If you need it
+ * urgently, contact me and force me to work... Btw, this doesn't mean
+ * that G_CICONs won't be copied at all, but the copied tree will
+ * share the CICONBLKs with the original.
+ *
+ * Input:
+ * tree: Pointer to tree which should be copied
+ * what: Specifies what substructures should be copied, too (see the
+ * C_xxx-definitions in tree-copy.h for details)
+ *
+ * Output:
+ * NULL: Tree couldn't be copied (due to lack of memory)
+ * otherwise: Pointer to copied tree, use free to dealloc it's memory
+ */
+OBJECT *gemtk_obj_tree_copy(OBJECT *tree)
+{
+ int16_t i, objects;
+ size_t to_malloc, size;
+ OBJECT *new_tree;
+ char *area;
+
+ /* Calculate the number of bytes we need for the new tree */
+ to_malloc = (size_t) 0;
+ for (i = 0;;) {
+
+ /* Size of the OBJECT-structure itself */
+ to_malloc += sizeof(OBJECT);
+
+ switch (tree[i].ob_type & 0xff) {
+ case G_TEXT:
+ case G_BOXTEXT:
+ case G_FTEXT:
+ case G_FBOXTEXT:
+ /* Size of a TEDINFO-structure */
+ to_malloc += sizeof(TEDINFO);
+
+ /* Sizes of the strings in the TEDINFO-structure */
+ to_malloc += (size_t)tree[i].ob_spec.tedinfo->te_txtlen;
+ to_malloc += (size_t)tree[i].ob_spec.tedinfo->te_txtlen;
+ to_malloc += (size_t)tree[i].ob_spec.tedinfo->te_tmplen;
+ break;
+
+ case G_IMAGE:
+
+ /* Size of the BITBLK-structure */
+ to_malloc += sizeof(BITBLK);
+
+ /* Size of the image-data in the BITBLK-structure */
+ to_malloc += (size_t)((int32_t)tree[i].ob_spec.bitblk->bi_wb *
+ (int32_t)tree[i].ob_spec.bitblk->bi_hl);
+
+ break;
+
+ case G_USERDEF:
+ /* Size of the USERBLK-structure */
+ to_malloc += sizeof(USERBLK);
+ break;
+
+ case G_BUTTON:
+ case G_STRING:
+ case G_TITLE:
+ /* Size of the string (with one null character at the end) */
+ to_malloc += strlen(tree[i].ob_spec.free_string) + 1L;
+ break;
+
+ case G_ICON:
+ /* Size of the ICONBLK-structure */
+ to_malloc += sizeof(BITBLK);
+
+ /* Sizes of icon-data, icon-mask and icon-text */
+ to_malloc += (size_t)((int32_t)tree[i].ob_spec.iconblk->ib_wicon *
+ (int32_t)tree[i].ob_spec.iconblk->ib_hicon /
+ 4L + 1L +
+ (int32_t)strlen(tree[i].ob_spec.iconblk->ib_ptext));
+
+ break;
+ }
+
+ /* If the size is odd, make it even */
+ if ((long)to_malloc & 1)
+ to_malloc++;
+
+ /* Exit if we've reached the last object in the tree */
+ if (tree[i].ob_flags & OF_LASTOB)
+ break;
+
+ i++;
+ }
+
+ objects = i + 1;
+
+ /* If there's not enough memory left for the new tree, return NULL */
+ if ((new_tree = (OBJECT *)calloc(1, to_malloc)) == NULL) {
+ return(NULL);
+ }
+
+ /*
+ * area contains a pointer to the area where we copy the structures to
+ */
+ area = (char *)((int32_t)new_tree+(int32_t)objects*(int32_t)sizeof(OBJECT));
+
+ for (i = 0; i < objects; i++) {
+
+ /* Copy the contents of the OBJECT-structure */
+ new_tree[i] = tree[i];
+
+ /* This was added to assure true copies of the object type */
+ new_tree[i].ob_type = tree[i].ob_type;
+
+ switch (tree[i].ob_type & 0xff) {
+ case G_TEXT:
+ case G_BOXTEXT:
+ case G_FTEXT:
+ case G_FBOXTEXT:
+
+ /* Copy the contents of the TEDINFO-structure */
+ *(TEDINFO *)area = *tree[i].ob_spec.tedinfo;
+ new_tree[i].ob_spec.tedinfo = (TEDINFO *)area;
+ area += sizeof(TEDINFO);
+
+ /* Copy the strings in the TEDINFO-structure */
+ strncpy(area, tree[i].ob_spec.tedinfo->te_ptext,
+ tree[i].ob_spec.tedinfo->te_txtlen);
+ new_tree[i].ob_spec.tedinfo->te_ptext = area;
+ area += tree[i].ob_spec.tedinfo->te_txtlen;
+ strncpy(area, tree[i].ob_spec.tedinfo->te_ptmplt,
+ tree[i].ob_spec.tedinfo->te_tmplen);
+ new_tree[i].ob_spec.tedinfo->te_ptmplt = area;
+ area += tree[i].ob_spec.tedinfo->te_tmplen;
+ strncpy(area, tree[i].ob_spec.tedinfo->te_pvalid,
+ tree[i].ob_spec.tedinfo->te_txtlen);
+ new_tree[i].ob_spec.tedinfo->te_pvalid = area;
+ area += tree[i].ob_spec.tedinfo->te_txtlen;
+
+ break;
+
+ case G_IMAGE:
+
+ /* Copy the contents of the BITBLK-structure */
+ *(BITBLK *)area = *tree[i].ob_spec.bitblk;
+ new_tree[i].ob_spec.bitblk = (BITBLK *)area;
+ area += sizeof(BITBLK);
+
+ /* Copy the image-data */
+ size = (size_t)((int32_t)tree[i].ob_spec.bitblk->bi_wb *
+ (int32_t)tree[i].ob_spec.bitblk->bi_hl);
+ memcpy(area, tree[i].ob_spec.bitblk->bi_pdata, size);
+ new_tree[i].ob_spec.bitblk->bi_pdata = (int16_t *)area;
+ area += size;
+
+ break;
+
+ case G_USERDEF:
+
+ /* Copy the contents of the USERBLK-structure */
+ *(USERBLK *)area = *tree[i].ob_spec.userblk;
+ new_tree[i].ob_spec.userblk = (USERBLK *)area;
+ area += sizeof(USERBLK);
+
+ break;
+
+ case G_BUTTON:
+ case G_STRING:
+ case G_TITLE:
+
+ /* Copy the string */
+ size = strlen(tree[i].ob_spec.free_string) + 1L;
+ strcpy(area, tree[i].ob_spec.free_string);
+ new_tree[i].ob_spec.free_string = area;
+ area += size;
+
+ break;
+
+ case G_ICON:
+
+ /* Copy the contents of the ICONBLK-structure */
+ *(ICONBLK *)area = *tree[i].ob_spec.iconblk;
+ new_tree[i].ob_spec.iconblk = (ICONBLK *)area;
+ area += sizeof(ICONBLK);
+
+ size = (size_t)((int32_t)tree[i].ob_spec.iconblk->ib_wicon *
+ (int32_t)tree[i].ob_spec.iconblk->ib_hicon /
+ 8L);
+ /* Copy the mask-data */
+ memcpy(area, tree[i].ob_spec.iconblk->ib_pmask, size);
+ new_tree[i].ob_spec.iconblk->ib_pmask = (int16_t *)area;
+ area += size;
+
+ /* Copy the icon-data */
+ memcpy(area, tree[i].ob_spec.iconblk->ib_pdata, size);
+ new_tree[i].ob_spec.iconblk->ib_pdata = (int16_t *)area;
+ area += size;
+ size = strlen(tree[i].ob_spec.iconblk->ib_ptext) + 1L;
+
+ /* Copy the icon-string */
+ strcpy(area, tree[i].ob_spec.iconblk->ib_ptext);
+ new_tree[i].ob_spec.iconblk->ib_ptext = area;
+ area += size;
+
+ break;
+ }
+
+ /* Assure that area contains an even address */
+ if ((int32_t)area & 1)
+ area++;
+ }
+
+ return(new_tree);
+}
+
+/***
+ * Create a simple OBJECT tree from a list of strings, to be used with menu_popup
+ * OBJECT ownership is passed to caller.
+ * Call gemtk_obj_destroy_popup_tree once the popup isn't needed anymore.
+ *
+ * \param items A list of string to be used as items
+ * \param nitems The number of items in the list
+ * \param selected The text of the selected item
+ * \param horizontal Set to true to render the tree horizontally
+ * \param max_width -1: autodetect width
+ * \param max_heigth -1: autodetect height (set to postive value when using a vertical scrolling popup)
+ * \return a pointer to the new OBJECT tree
+ */
+OBJECT * gemtk_obj_create_popup_tree(const char **items, int nitems,
+ char * selected, bool horizontal,
+ int max_width, int max_height)
+{
+ OBJECT * popup = NULL;
+ int box_width = 0;
+ int box_height = 0;
+ int char_width = 10;
+ int char_height = 16;
+ int item_height; // height of each item
+
+ assert(items != NULL);
+
+ item_height = char_height;
+
+ /* Allocate room for n items and the root G_BOX: */
+ popup = calloc(nitems+1, sizeof(OBJECT));
+ assert(popup != null);
+
+ for (int i=0; i<nitems; i++) {
+
+ int len = strlen(items[i]);
+
+ if (horizontal && (max_width<1)) {
+ box_width += (len * char_width)+4;
+ }
+ else if (!horizontal){
+ /* Detect max width, used for vertical rendering: */
+ if(len*char_width > box_width){
+ box_width = (len+2) * char_width;
+ }
+ //if (max_height < 1) {
+ box_height += item_height;
+ //}
+ }
+ }
+
+ if (max_width>0){
+ box_width = max_width;
+ }
+
+ if (horizontal) {
+ box_height = item_height;
+ }
+ else if(max_height > 0){
+ // TODO: validate max_height, shrink values larger than screen height
+ //box_height = max_height;
+ }
+
+/*
+ printf("popup height: %d, popup width: %d\n", box_height, box_width);
+*/
+
+ popup[0].ob_next = -1; /**< object's next sibling */
+ popup[0].ob_head = 1; /**< head of object's children */
+ popup[0].ob_tail = nitems; /**< tail of object's children */
+ popup[0].ob_type = G_BOX; /**< type of object */
+ popup[0].ob_flags = OF_FL3DBAK; /**< flags */
+ popup[0].ob_state = OS_NORMAL; /**< state */
+ popup[0].ob_spec.index = (long) 16650496L; /**< object-specific data */
+ popup[0].ob_x = 0; /**< upper left corner of object */
+ popup[0].ob_y = 0; /**< upper left corner of object */
+ popup[0].ob_width = box_width; /**< width of obj */
+ popup[0].ob_height = box_height;
+
+
+
+ /* Add items to popup: */
+ int xpos = 0, ypos = 0;
+
+ for (int i=0; i<nitems; i++) {
+
+ int state = OS_NORMAL;
+ int flags = OF_NONE;
+ int item_width;
+ char * string = calloc(1, strlen(items[i])+3);
+
+ snprintf(string, strlen(items[i])+3, " %s", items[i]);
+
+ if (selected != NULL) {
+ if (strcmp(selected, items[i]) == 0) {
+ state |= OS_CHECKED;
+ }
+ }
+
+ if (i == nitems-1) {
+ flags |= OF_LASTOB;
+ }
+
+ item_width = (horizontal) ? ((int)strlen(items[i])*char_width)+2 : box_width;
+/*
+ printf("addin popup item \"%s\" (w: %d, h: %d, flags: %x) at %d/%d\n", items[i],
+ item_width, item_height, flags,
+ xpos, ypos);
+*/
+
+ popup[i+1].ob_next = ((flags&OF_LASTOB) != 0) ? 0 : i+2; /**< object's next sibling */
+ popup[i+1].ob_head = -1; /**< head of object's children */
+ popup[i+1].ob_tail = -1; /**< tail of object's children */
+ popup[i+1].ob_type = G_STRING; /**< type of object */
+ popup[i+1].ob_flags = flags; /**< flags */
+ popup[i+1].ob_state = state; /**< state */
+ popup[i+1].ob_spec.free_string = string; /**< object-specific data */
+ popup[i+1].ob_x = xpos; /**< upper left corner of object */
+ popup[i+1].ob_y = ypos; /**< upper left corner of object */
+ popup[i+1].ob_width = item_width; /**< width of obj */
+ popup[i+1].ob_height = item_height;
+
+ if (horizontal) {
+ xpos += item_width;
+ }
+ else {
+ ypos += item_height;
+ }
+
+ }
+
+ return(popup);
+}
+
+/***
+ * Free memory of an OBJECT tree created with gemtk_obj_create_popup_tree.
+ *
+ * \param popup The tree to destroy
+ */
+void gemtk_obj_destroy_popup_tree(OBJECT * popup)
+{
+ int i=0;
+
+ while (1) {
+ if (popup[i].ob_type == G_STRING) {
+ free(popup[i+1].ob_spec.free_string);
+ }
+ if((popup[i].ob_flags & OF_LASTOB) != OF_LASTOB){
+ break;
+ }
+ i++;
+ }
+
+ free(popup);
+}
diff --git a/frontends/atari/gemtk/objc.h b/frontends/atari/gemtk/objc.h
new file mode 100644
index 000000000..6fa1072b7
--- /dev/null
+++ b/frontends/atari/gemtk/objc.h
@@ -0,0 +1,7 @@
+#ifndef GEMTK_OBJC_H
+#define GEMTK_OBJC_H
+
+
+
+#endif // GEMTK_OBJC_H
+
diff --git a/frontends/atari/gemtk/redrawslots.c b/frontends/atari/gemtk/redrawslots.c
new file mode 100644
index 000000000..ee5627daf
--- /dev/null
+++ b/frontends/atari/gemtk/redrawslots.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2011 Ole Loots <ole@monochrom.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>
+#define WITH_RECT
+#include "gemtk.h"
+#undef WITH_RECT
+
+void redraw_slots_init(struct s_redrw_slots * slots, short size)
+{
+ // TODO: allocate slots dynamically!
+ slots->size = MIN( MAX_REDRW_SLOTS , size);
+ slots->areas_used = 0;
+}
+
+void redraw_slots_free(struct s_redrw_slots * slots)
+{
+ // TOOD: free areas...
+}
+
+
+static inline bool rect_intersect( struct rect * box1, struct rect * box2 )
+{
+ if (box2->x1 < box1->x0)
+ return false;
+
+ if (box2->y1 < box1->y0)
+ return false;
+
+ if (box2->x0 > box1->x1)
+ return false;
+
+ if (box2->y0 > box1->y1)
+ return false;
+
+ return true;
+}
+
+
+void redraw_slot_schedule_grect(struct s_redrw_slots * slots, GRECT *area,
+ bool force)
+{
+ redraw_slot_schedule(slots, area->g_x, area->g_y,
+ area->g_x + area->g_w, area->g_y + area->g_h, force);
+}
+
+/*
+ schedule redraw coords.
+*/
+void redraw_slot_schedule(struct s_redrw_slots * slots, short x0, short y0,
+ short x1, short y1, bool force)
+{
+ int i = 0;
+ struct rect area;
+
+ area.x0 = x0;
+ area.y0 = y0;
+ area.x1 = x1;
+ area.y1 = y1;
+
+ if (force == false) {
+ for (i=0; i<slots->areas_used; i++) {
+ if (slots->areas[i].x0 <= x0
+ && slots->areas[i].x1 >= x1
+ && slots->areas[i].y0 <= y0
+ && slots->areas[i].y1 >= y1) {
+ /* the area is already queued for redraw */
+ return;
+ } else {
+ if (rect_intersect(&slots->areas[i], &area )) {
+ slots->areas[i].x0 = MIN(slots->areas[i].x0, x0);
+ slots->areas[i].y0 = MIN(slots->areas[i].y0, y0);
+ slots->areas[i].x1 = MAX(slots->areas[i].x1, x1);
+ slots->areas[i].y1 = MAX(slots->areas[i].y1, y1);
+ return;
+ }
+ }
+ }
+ }
+
+ if (slots->areas_used < slots->size) {
+ slots->areas[slots->areas_used].x0 = x0;
+ slots->areas[slots->areas_used].x1 = x1;
+ slots->areas[slots->areas_used].y0 = y0;
+ slots->areas[slots->areas_used].y1 = y1;
+ slots->areas_used++;
+ } else {
+ /*
+ we are out of available slots, merge box with last slot
+ this is dumb... but also a very rare case.
+ */
+ slots->areas[slots->size-1].x0 = MIN(slots->areas[i].x0, x0);
+ slots->areas[slots->size-1].y0 = MIN(slots->areas[i].y0, y0);
+ slots->areas[slots->size-1].x1 = MAX(slots->areas[i].x1, x1);
+ slots->areas[slots->size-1].y1 = MAX(slots->areas[i].y1, y1);
+ }
+done:
+ return;
+}
+
+void redraw_slots_remove_area(struct s_redrw_slots * slots, int i)
+{
+ int x;
+ for(x = i+1; i<slots->areas_used; x++){
+ slots->areas[x-1] = slots->areas[x];
+ }
+ slots->areas_used--;
+}
diff --git a/frontends/atari/gemtk/redrawslots.h b/frontends/atari/gemtk/redrawslots.h
new file mode 100644
index 000000000..9691fb4bc
--- /dev/null
+++ b/frontends/atari/gemtk/redrawslots.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2012 Ole Loots <ole@monochrom.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 ATARI_REDRAW_SLOTS_H
+#define ATARI_REDRAW_SLOTS_H
+
+#include <mt_gem.h>
+
+#endif
diff --git a/frontends/atari/gemtk/utils.c b/frontends/atari/gemtk/utils.c
new file mode 100644
index 000000000..63e6330ec
--- /dev/null
+++ b/frontends/atari/gemtk/utils.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2013 Ole Loots <ole@monochrom.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 <stdint.h>
+#include <stdbool.h>
+#include <mt_gem.h>
+#include "gemtk.h"
+
+/* -------------------------------------------------------------------------- */
+/* GEM Utillity functions: */
+/* -------------------------------------------------------------------------- */
+
+unsigned short _systype_v;
+unsigned short _systype (void)
+{
+ int32_t * cptr = NULL;
+ _systype_v = SYS_TOS;
+
+ cptr = (int32_t *)Setexc(0x0168, -1L);
+ if (cptr == NULL ) {
+ return _systype_v; /* stone old TOS without any cookie support */
+ }
+ while (*cptr) {
+ if (*cptr == C_MgMc || *cptr == C_MgMx ) {
+ _systype_v = (_systype_v & ~0xF) | SYS_MAGIC;
+ } else if (*cptr == C_MiNT ) {
+ _systype_v = (_systype_v & ~0xF) | SYS_MINT;
+ } else if (*cptr == C_Gnva /* Gnva */ ) {
+ _systype_v |= SYS_GENEVA;
+ } else if (*cptr == C_nAES /* nAES */ ) {
+ _systype_v |= SYS_NAES;
+ }
+ cptr += 2;
+ }
+ if (_systype_v & SYS_MINT) { /* check for XaAES */
+ short out = 0, u;
+ if (wind_get (0, (((short)'X') <<8)|'A', &out, &u,&u,&u) && out) {
+ _systype_v |= SYS_XAAES;
+ }
+ }
+ return _systype_v;
+}
+
+bool gemtk_rc_intersect_ro(GRECT *a, GRECT *b)
+{
+ GRECT r1, r2;
+
+ r1 = *a;
+ r2 = *b;
+
+ return((bool)rc_intersect(&r1, &r2));
+}
+
+
+typedef struct {
+ char *unshift;
+ char *shift;
+ char *capslock;
+} KEYTAB;
+
+int gemtk_keybd2ascii( int keybd, int shift)
+{
+
+ KEYTAB *key;
+ key = (KEYTAB *)Keytbl( (char*)-1, (char*)-1, (char*)-1);
+ return (shift)?key->shift[keybd>>8]:key->unshift[keybd>>8];
+}
+
+
+void gemtk_clip_grect(VdiHdl vh, GRECT *rect)
+{
+ PXY pxy[2];
+
+ pxy[0].p_x = rect->g_x;
+ pxy[0].p_y = rect->g_y;
+ pxy[1].p_x = pxy[0].p_x + rect->g_w - 1;
+ pxy[1].p_y = pxy[0].p_y + rect->g_h - 1;
+
+ vs_clip_pxy(vh, pxy);
+}
+
+/** Send an Message to a GUIWIN using AES message pipe
+* \param win the GUIWIN which shall receive the message
+* \param msg_type the WM_ message definition
+* \param a the 4th parameter to appl_write
+* \param b the 5th parameter to appl_write
+* \param c the 6th parameter to appl_write
+* \param d the 7th parameter to appl_write
+*/
+void gemtk_send_msg(short msg_type, short data2, short data3, short data4,
+ short data5, short data6, short data7)
+{
+ short msg[8];
+
+ msg[0] = msg_type;
+ msg[1] = gl_apid;
+ msg[2] = data2;
+ msg[3] = data3;
+ msg[4] = data4;
+ msg[5] = data5;
+ msg[6] = data6;
+ msg[7] = data7;
+
+ appl_write(gl_apid, 16, &msg);
+}
+
+
+void gemtk_wind_get_str(short aes_handle, short mode, char *str, int len)
+{
+
+ // TODO: remove or implement function
+
+ if(len>255) {
+ len = 255;
+ }
+
+ memset(str, 0, len);
+ return;
+ /*
+
+ wind_get(aes_handle, mode, (short)(((unsigned long)tmp_str)>>16),
+ (short)(((unsigned long)tmp_str) & 0xffff), 0, 0);
+
+ strncpy(str, tmp_str, len);
+ */
+}
+
+
diff --git a/frontends/atari/gemtk/utils.h b/frontends/atari/gemtk/utils.h
new file mode 100644
index 000000000..7ebbcf228
--- /dev/null
+++ b/frontends/atari/gemtk/utils.h
@@ -0,0 +1,5 @@
+#ifndef UTILS_H_INCLUDED
+#define UTILS_H_INCLUDED
+
+
+#endif // UTILS_H_INCLUDED
diff --git a/frontends/atari/gemtk/vaproto.c b/frontends/atari/gemtk/vaproto.c
new file mode 100644
index 000000000..45e47225c
--- /dev/null
+++ b/frontends/atari/gemtk/vaproto.c
@@ -0,0 +1,170 @@
+#include <limits.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <gem.h>
+
+#include "vaproto.h"
+#include "gemtk.h"
+
+#ifndef NDEBUG
+# define DEBUG_PRINT(x) printf x
+#else
+# define DEBUG_PRINT(x)
+#endif
+
+
+/* Global memory, at least 1024 bytes large: */
+static char *va_helpbuf;
+
+/* Desktop's AES ID: */
+static short av_shell_id = -1;
+
+/* What AV commands can desktop do? */
+static short av_shell_status = 0;
+
+/* The application name used for AV/VA messages: */
+static const char * av_clientname = "gemtk_av_app";
+
+
+static short get_avserver(void)
+{
+ short ret = -100;
+ const char * av_env = getenv("AVSERVER");
+ if (av_env) {
+ char av_envname[9];
+ strncpy(av_envname,av_env, 8);
+ av_envname[8] = '\0';
+ while (strlen (av_envname) < 8) {
+ strcat(av_envname, " ");
+ }
+ ret = appl_find (av_envname);
+ }
+ return ret;
+}
+
+/**
+ * initialitze the AV client API
+ * \param appname Name of the application passed to menu_register()
+ * \return returns 1 on success, otherwise an negative error code.
+ *
+ */
+int gemtk_av_init(const char *appname)
+{
+ short mode = 0x0003 /* prefer TT ram */
+ | 0x0020; /* global accesible */
+
+ if(av_shell_id != -1) {
+ /* Already initialized */
+ return(1);
+ }
+
+ va_helpbuf = (char*)Mxalloc(1024, mode);
+
+ if(va_helpbuf == NULL){
+ gemtk_msg_box_show(GEMTK_MSG_BOX_ALERT, "Could not allocate AV memory!");
+ return(-1);
+ }
+
+ if(appname != NULL){
+ av_clientname = appname;
+ }
+
+ av_shell_id = get_avserver();
+ DEBUG_PRINT(("AV Server ID: %d", av_shell_id));
+
+ gemtk_av_send(AV_PROTOKOLL, NULL, NULL);
+
+ va_helpbuf[0] = '\0';
+}
+
+void gemtk_av_exit(void)
+{
+ if(av_shell_id == -1) {
+ /* Nothing to do */
+ return;
+ }
+
+ if (av_shell_status & AA_EXIT) {
+ /* AV server knows AV_EXIT */
+ gemtk_av_send(AV_EXIT, NULL, NULL);
+ }
+
+ if(va_helpbuf != NULL){
+ free(va_helpbuf);
+ va_helpbuf = NULL;
+ }
+
+ av_shell_id = -1;
+
+}
+
+bool gemtk_av_send (short message, const char * data1, const char * data2)
+{
+ short msg[8];
+ short to_ap_id = av_shell_id;
+
+ /* - 100 to ap id would be no AV server */
+ if (to_ap_id == -100){
+ return false;
+ }
+
+ msg[0] = message;
+ msg[1] = gl_apid;
+ msg[7] = msg[6] = msg[5] = msg[4] = msg[3] = msg[2] = 0;
+
+ switch (message)
+ {
+ case AV_EXIT:
+ msg[3] = gl_apid;
+ break;
+ case AV_PROTOKOLL:
+ msg[3] = VV_START | VV_ACC_QUOTING;
+ *(char **)(msg+6) = strcpy (va_helpbuf, av_clientname);
+ break;
+ case AV_STARTPROG:
+ DEBUG_PRINT(("AV_STARTPROG: %s (%s)\n", data1, data2));
+ *(char **)(msg+3) = strcpy(va_helpbuf, data1);
+ *(char **)(msg+5) = strcpy(va_helpbuf, data2);
+ break;
+ case AV_VIEW:
+ DEBUG_PRINT(("AV_VIEW: %s (%d)\n", data1, (short)data2));
+ *(char **)(msg+3) = strcpy(va_helpbuf, data1);
+ msg[5] = (short)data2;
+ break;
+ default:
+ return false; /* not supported */
+ }
+
+ return (appl_write (to_ap_id, 16, msg) > 0);
+}
+
+bool gemtk_av_dispatch (short msg[8])
+{
+
+ if(av_shell_id == -1)
+ return(false);
+
+ switch (msg[0]) {
+ case VA_PROTOSTATUS :
+ DEBUG_PRINT(("AV STATUS: %d for %d\n", msg[3], msg[1]));
+ if (msg[1] == av_shell_id) {
+ av_shell_status = msg[3];
+ if(av_shell_status & AA_STARTPROG){
+ printf(" AA_STARTPROG\n");
+ }
+ }
+ break;
+
+ default:
+ DEBUG_PRINT(("Unknown AV message: %d", msg[0]));
+ break;
+ }
+
+ return(true);
+}
+
+
diff --git a/frontends/atari/gemtk/vaproto.h b/frontends/atari/gemtk/vaproto.h
new file mode 100644
index 000000000..84e0ecf0b
--- /dev/null
+++ b/frontends/atari/gemtk/vaproto.h
@@ -0,0 +1,121 @@
+#ifndef VAPROTO_H_INCLUDED
+#define VAPROTO_H_INCLUDED
+
+
+#define VAPRO 1
+
+/* AES-Messages */
+
+typedef enum
+{
+ AV_PROTOKOLL = 0x4700,
+ VA_PROTOSTATUS = 0x4701,
+ AV_GETSTATUS = 0x4703,
+ AV_STATUS = 0x4704,
+ VA_SETSTATUS = 0x4705,
+ AV_SENDKEY = 0x4710,
+ VA_START = 0x4711,
+ AV_ASKFILEFONT = 0x4712,
+ VA_FILEFONT = 0x4713,
+ AV_ASKCONFONT = 0x4714,
+ VA_CONFONT = 0x4715,
+ AV_ASKOBJECT = 0x4716,
+ VA_OBJECT = 0x4717,
+ AV_OPENCONSOLE = 0x4718,
+ VA_CONSOLEOPEN = 0x4719,
+ AV_OPENWIND = 0x4720,
+ VA_WINDOPEN = 0x4721,
+ AV_STARTPROG = 0x4722,
+ VA_PROGSTART = 0x4723,
+ AV_ACCWINDOPEN = 0x4724,
+ VA_DRAGACCWIND = 0x4725,
+ AV_ACCWINDCLOSED = 0x4726,
+
+ AV_COPY_DRAGGED = 0x4728,
+ VA_COPY_COMPLETE = 0x4729,
+ AV_PATH_UPDATE = 0x4730,
+ AV_WHAT_IZIT = 0x4732,
+ VA_THAT_IZIT = 0x4733,
+ AV_DRAG_ON_WINDOW = 0x4734,
+ VA_DRAG_COMPLETE = 0x4735,
+ AV_EXIT = 0x4736,
+ AV_STARTED = 0x4738,
+ VA_FONTCHANGED = 0x4739,
+ AV_XWIND = 0x4740,
+ VA_XOPEN = 0x4741,
+
+/* Neue Messages seit dem 26.06.1995 */
+
+ AV_VIEW = 0x4751,
+ VA_VIEWED = 0x4752,
+ AV_FILEINFO = 0x4753,
+ VA_FILECHANGED = 0x4754,
+ AV_COPYFILE = 0x4755,
+ VA_FILECOPIED = 0x4756,
+ AV_DELFILE = 0x4757,
+ VA_FILEDELETED = 0x4758,
+ AV_SETWINDPOS = 0x4759,
+ VA_PATH_UPDATE = 0x4760,
+ VA_HIGH /* HR please always do this! */
+} AV_VA;
+
+
+/* Objekttypen fÂr VA_THAT_IZIT */
+
+enum
+{
+ VA_OB_UNKNOWN,
+ VA_OB_TRASHCAN,
+ VA_OB_SHREDDER,
+ VA_OB_CLIPBOARD,
+ VA_OB_FILE,
+ VA_OB_FOLDER,
+ VA_OB_DRIVE,
+ VA_OB_WINDOW,
+ VA_OB_NOTEPAD,
+ VA_OB_NOTE
+};
+
+typedef enum
+{
+ VV_SETSTATUS = 0x0001,
+ VV_START = 0x0002,
+ VV_STARTED = 0x0004,
+ VV_FONTCHANGED = 0x0008,
+ VV_ACC_QUOTING = 0x0010,
+ VV_PATH_UPDATE = 0x0020
+} av_va_give;
+
+typedef enum
+{ /* mp[3]: */
+ AA_SENDKEY = 0x0001, /* b0: MAGXDESK, THING */
+ AA_ASKFILEFONT = 0x0002, /* b1: THING */
+ AA_ASKCONFONT = 0x0004, /* b2: THING */
+ AA_ASKOBJECT = 0x0008,
+ AA_OPENWIND = 0x0010, /* b4: MAGXDESK, THING */
+ AA_STARTPROG = 0x0020, /* b5: MAGXDESK, THING */
+ AA_ACCWIND = 0x0040, /* b6: THING */
+ AA_STATUS = 0x0080, /* b7: THING */
+ AA_COPY_DRAGGED= 0x0100, /* b8: THING */
+ AA_DRAG_ON_WINDOW=0x0200, /* b9: MAGXDESK, THING */
+ AA_EXIT = 0x0400, /* b10: MAGXDESK, THING */
+ AA_XWIND = 0x0800, /* b11: MAGXDESK, THING */
+ AA_FONTCHANGED = 0x1000, /* b2: THING */
+ AA_STARTED = 0x2000, /* b13: MAGXDESK, THING */
+ AA_SRV_QUOTING = 0x4000, /* b14: THING */
+ AA_FILE = 0x8000, /* b15: THING */
+ /* mp[4]: THING */
+ AA_COPY = 0x0001,
+ AA_DELETE = 0x0002,
+ AA_VIEW = 0x0004,
+ AA_SETWINDPOS = 0x0008,
+ AA_COPYFILELINK= 0x0010,
+ AA_SENDCLICK = 0x0020
+} av_va_have;
+
+/* Makros zum Testen auf Quoting */
+
+#define VA_ACC_QUOTING(a) ((a) & VV_ACC_QUOTING)
+#define VA_SERVER_QUOTING(a) ((a) & AA_SRV_QUOTING)
+
+#endif // VAPROTO_H_INCLUDED
diff --git a/frontends/atari/gui.c b/frontends/atari/gui.c
new file mode 100644
index 000000000..810c7646f
--- /dev/null
+++ b/frontends/atari/gui.c
@@ -0,0 +1,1217 @@
+/*
+ * Copyright 2010 <ole@monochrom.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
+ *
+ * Provides all the mandatory functions prefixed with gui_ for atari
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/corestrings.h"
+#include "content/urldb.h"
+#include "content/content.h"
+#include "content/backing_store.h"
+#include "content/hlcache.h"
+#include "desktop/treeview.h"
+#include "desktop/browser.h"
+#include "desktop/gui_layout.h"
+#include "desktop/gui_window.h"
+#include "desktop/gui_clipboard.h"
+#include "desktop/gui_fetch.h"
+#include "desktop/gui_misc.h"
+#include "desktop/netsurf.h"
+
+#include "atari/gemtk/gemtk.h"
+#include "atari/gui.h"
+#include "atari/misc.h"
+#include "atari/findfile.h"
+#include "atari/schedule.h"
+#include "atari/rootwin.h"
+#include "atari/statusbar.h"
+#include "atari/toolbar.h"
+#include "atari/hotlist.h"
+#include "atari/cookies.h"
+#include "atari/certview.h"
+#include "atari/history.h"
+#include "atari/login.h"
+#include "atari/encoding.h"
+#include "atari/res/netsurf.rsh"
+#include "atari/plot/plot.h"
+#include "atari/clipboard.h"
+#include "atari/osspec.h"
+#include "atari/search.h"
+#include "atari/deskmenu.h"
+#include "atari/download.h"
+#include "atari/file.h"
+#include "atari/filetype.h"
+#include "atari/bitmap.h"
+#include "atari/font.h"
+#include "cflib.h"
+
+static bool atari_quit = false;
+
+struct gui_window *input_window = NULL;
+struct gui_window *window_list = NULL;
+void *h_gem_rsrc;
+long next_poll;
+bool rendering = false;
+GRECT desk_area;
+
+/* Comandline / Options: */
+int option_window_width;
+int option_window_height;
+int option_window_x;
+int option_window_y;
+
+/* Defaults to option_homepage_url, commandline options overwrites that value */
+const char *option_homepage_url;
+
+/* path to choices file: */
+char options[PATH_MAX];
+
+EVMULT_IN aes_event_in = {
+ .emi_flags = MU_MESAG | MU_TIMER | MU_KEYBD | MU_BUTTON | MU_M1,
+ .emi_bclicks = 258,
+ .emi_bmask = 3,
+ .emi_bstate = 0,
+ .emi_m1leave = MO_ENTER,
+ .emi_m1 = {0,0,0,0},
+ .emi_m2leave = 0,
+ .emi_m2 = {0,0,0,0},
+ .emi_tlow = 0,
+ .emi_thigh = 0
+};
+EVMULT_OUT aes_event_out;
+short aes_msg_out[8];
+
+bool gui_window_get_scroll(struct gui_window *w, int *sx, int *sy);
+static nserror gui_window_set_url(struct gui_window *w, nsurl *url);
+
+/**
+ * Core atari event processing.
+ */
+static void atari_poll(void)
+{
+
+ struct gui_window *tmp;
+ short mx, my, dummy;
+
+ aes_event_in.emi_tlow = schedule_run();
+
+ if(rendering){
+ aes_event_in.emi_tlow = nsoption_int(atari_gui_poll_timeout);
+ }
+
+ if(aes_event_in.emi_tlow < 0) {
+ aes_event_in.emi_tlow = 10000;
+ printf("long poll!\n");
+ }
+
+ if(input_window && input_window->root->redraw_slots.areas_used > 0) {
+ window_process_redraws(input_window->root);
+ }
+
+
+ graf_mkstate(&mx, &my, &dummy, &dummy);
+ aes_event_in.emi_m1.g_x = mx;
+ aes_event_in.emi_m1.g_y = my;
+ evnt_multi_fast(&aes_event_in, aes_msg_out, &aes_event_out);
+ if(gemtk_wm_dispatch_event(&aes_event_in, &aes_event_out, aes_msg_out) == 0) {
+ if( (aes_event_out.emo_events & MU_MESAG) != 0 ) {
+ LOG("WM: %d\n", aes_msg_out[0]);
+ switch(aes_msg_out[0]) {
+
+ case MN_SELECTED:
+ LOG("Menu Item: %d\n", aes_msg_out[4]);
+ deskmenu_dispatch_item(aes_msg_out[3], aes_msg_out[4]);
+ break;
+
+ case AP_TERM:
+ atari_quit = true;
+ break;
+ default:
+ break;
+ }
+ }
+ if((aes_event_out.emo_events & MU_KEYBD) != 0) {
+ uint16_t nkc = gem_to_norm( (short)aes_event_out.emo_kmeta,
+ (short)aes_event_out.emo_kreturn);
+ deskmenu_dispatch_keypress(aes_event_out.emo_kreturn,
+ aes_event_out.emo_kmeta, nkc);
+ }
+ }
+
+ tmp = window_list;
+ while(tmp){
+ if(tmp->root->redraw_slots.areas_used > 0){
+ window_process_redraws(tmp->root);
+ }
+ tmp = tmp->next;
+ }
+
+ /** @todo implement generic treeview redraw function. */
+ /** @todo rename hl to atari_hotlist or create getter for it... */
+
+ atari_treeview_flush_redraws();
+}
+
+/**
+ * Create and open a gui window for a browsing context.
+ *
+ * \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
+ *
+ * If GW_CREATE_CLONE flag is set existing is non-NULL.
+ *
+ * The created gui_window must include a reference to the browser
+ * window passed in the bw param.
+ */
+static struct gui_window *
+gui_window_create(struct browser_window *bw,
+ struct gui_window *existing,
+ gui_window_create_flags flags)
+{
+ struct gui_window *gw=NULL;
+ LOG("gw: %p, BW: %p, existing %p, flags: %d\n", gw, bw, existing, (int)flags);
+
+ gw = calloc(1, sizeof(struct gui_window));
+ if (gw == NULL)
+ return NULL;
+
+ LOG("new window: %p, bw: %p\n", gw, bw);
+ window_create(gw, bw, existing, WIDGET_STATUSBAR|WIDGET_TOOLBAR|WIDGET_RESIZE\
+ |WIDGET_SCROLL);
+ if (gw->root->win) {
+ GRECT pos = {
+ option_window_x, option_window_y,
+ option_window_width, option_window_height
+ };
+ gui_window_set_url(gw, corestring_nsurl_about_blank);
+ gui_window_set_pointer(gw, BROWSER_POINTER_DEFAULT);
+ gui_set_input_gui_window(gw);
+ window_open(gw->root, gw, pos);
+ }
+
+ /* add the window to the window list: */
+ if( window_list == NULL ) {
+ window_list = gw;
+ gw->next = NULL;
+ gw->prev = NULL;
+ } else {
+ struct gui_window * tmp = window_list;
+ while( tmp->next != NULL ) {
+ tmp = tmp->next;
+ }
+ tmp->next = gw;
+ gw->prev = tmp;
+ gw->next = NULL;
+ }
+
+ /* Loose focus: */
+ window_set_focus(gw->root, WIDGET_NONE, NULL );
+
+ /* trigger on-focus event (select all text): */
+ window_set_focus(gw->root, URL_WIDGET, NULL);
+
+ /* delete selection: */
+ toolbar_key_input(gw->root->toolbar, NK_DEL);
+
+ return( gw );
+
+}
+
+/**
+ * Destroy previously created gui window
+ *
+ * \param gw The gui window to destroy.
+ */
+void gui_window_destroy(struct gui_window *gw)
+{
+ if (gw == NULL)
+ return;
+
+ LOG("%s\n", __FUNCTION__);
+
+ if (input_window == gw) {
+ gui_set_input_gui_window(NULL);
+ }
+
+ nsatari_search_session_destroy(gw->search);
+ free(gw->browser);
+ free(gw->status);
+ free(gw->title);
+ free(gw->url);
+
+ /* unlink the window: */
+ if(gw->prev != NULL ) {
+ gw->prev->next = gw->next;
+ } else {
+ window_list = gw->next;
+ }
+ if( gw->next != NULL ) {
+ gw->next->prev = gw->prev;
+ }
+
+ window_unref_gui_window(gw->root, gw);
+
+ free(gw);
+ gw = NULL;
+
+ if(input_window == NULL) {
+ gw = window_list;
+ while( gw != NULL ) {
+ if(gw->root) {
+ gui_set_input_gui_window(gw);
+ break;
+ }
+ gw = gw->next;
+ }
+ }
+}
+
+/**
+ * Find the current dimensions of a browser window's content area.
+ *
+ * \param w 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 *w,
+ int *width,
+ int *height,
+ bool scaled)
+{
+ if (w == NULL)
+ return;
+ GRECT rect;
+ window_get_grect(w->root, BROWSER_AREA_CONTENT, &rect);
+ *width = rect.g_w;
+ *height = rect.g_h;
+}
+
+/**
+ * Set the title of a window.
+ *
+ * \param gw window to update
+ * \param title new window title
+ */
+static void gui_window_set_title(struct gui_window *gw, const char *title)
+{
+ if (gw == NULL)
+ return;
+
+ if (gw->root) {
+
+ int l;
+ char * conv;
+ l = strlen(title)+1;
+ if (utf8_to_local_encoding(title, l-1, &conv) == NSERROR_OK ) {
+ l = MIN((uint32_t)atari_sysinfo.aes_max_win_title_len, strlen(conv));
+ if(gw->title == NULL)
+ gw->title = malloc(l);
+ else
+ gw->title = realloc(gw->title, l);
+
+ strncpy(gw->title, conv, l);
+ free( conv );
+ } else {
+ l = MIN((size_t)atari_sysinfo.aes_max_win_title_len, strlen(title));
+ if(gw->title == NULL)
+ gw->title = malloc(l);
+ else
+ gw->title = realloc(gw->title, l);
+ strncpy(gw->title, title, l);
+ }
+ gw->title[l] = 0;
+ if(input_window == gw)
+ window_set_title(gw->root, gw->title);
+ }
+}
+
+/* exported interface documented in atari/gui.h */
+void atari_window_set_status(struct gui_window *w, const char *text)
+{
+ int l;
+ if (w == NULL || text == NULL)
+ return;
+
+ assert(w->root);
+
+ l = strlen(text)+1;
+ if(w->status == NULL)
+ w->status = malloc(l);
+ else
+ w->status = realloc(w->status, l);
+
+ strncpy(w->status, text, l);
+ w->status[l] = 0;
+
+ if(input_window == w)
+ window_set_stauts(w->root, (char*)text);
+}
+
+static void atari_window_reformat(struct gui_window *gw)
+{
+ int width = 0, height = 0;
+
+ if (gw != NULL) {
+ gui_window_get_dimensions(gw, &width, &height, true);
+ browser_window_reformat(gw->browser->bw, false, width, height);
+ }
+}
+
+static void gui_window_redraw_window(struct gui_window *gw)
+{
+ CMP_BROWSER b;
+ GRECT rect;
+ if (gw == NULL)
+ return;
+ b = gw->browser;
+ window_get_grect(gw->root, BROWSER_AREA_CONTENT, &rect);
+ window_schedule_redraw_grect(gw->root, &rect);
+}
+
+static void gui_window_update_box(struct gui_window *gw, const struct rect *rect)
+{
+ GRECT area;
+ struct gemtk_wm_scroll_info_s *slid;
+
+ if (gw == NULL)
+ return;
+
+ slid = gemtk_wm_get_scroll_info(gw->root->win);
+
+ window_get_grect(gw->root, BROWSER_AREA_CONTENT, &area);
+ area.g_x += rect->x0 - (slid->x_pos * slid->x_unit_px);
+ area.g_y += rect->y0 - (slid->y_pos * slid->y_unit_px);
+ area.g_w = rect->x1 - rect->x0;
+ area.g_h = rect->y1 - rect->y0;
+ //dbg_grect("update box", &area);
+ window_schedule_redraw_grect(gw->root, &area);
+}
+
+bool gui_window_get_scroll(struct gui_window *w, int *sx, int *sy)
+{
+ if (w == NULL)
+ return false;
+
+ window_get_scroll(w->root, sx, sy);
+
+ return( true );
+}
+
+static void gui_window_set_scroll(struct gui_window *w, int sx, int sy)
+{
+ if ( (w == NULL)
+ || (w->browser->bw == NULL)
+ || (!browser_window_has_content(w->browser->bw)))
+ return;
+
+ LOG("scroll (gui_window: %p) %d, %d\n", w, sx, sy);
+ window_scroll_by(w->root, sx, sy);
+ return;
+
+}
+
+/**
+ * Update the extent of the inside of a browser window to that of the
+ * current content.
+ *
+ * It seems this method is called when content size got adjusted, so
+ * that we can adjust scroll info. We also have to call it when tab
+ * change occurs.
+ *
+ * \param gw gui_window to update the extent of
+ */
+static void gui_window_update_extent(struct gui_window *gw)
+{
+
+ if(browser_window_has_content(gw->browser->bw)) {
+ /** @todo store content size. */
+ if(window_get_active_gui_window(gw->root) == gw) {
+ int width, height;
+ GRECT area;
+ browser_window_get_extents(gw->browser->bw, false, &width, &height);
+ window_set_content_size(gw->root, width, height);
+ window_update_back_forward(gw->root);
+ window_get_grect(gw->root, BROWSER_AREA_CONTENT, &area);
+ window_schedule_redraw_grect(gw->root, &area);
+ }
+ }
+}
+
+
+/**
+ * set the pointer shape
+ */
+void gui_window_set_pointer(struct gui_window *gw, gui_pointer_shape shape)
+{
+ if (gw == NULL)
+ return;
+
+ switch (shape) {
+ case GUI_POINTER_POINT: /* link */
+ gw->cursor = &gem_cursors.hand;
+ break;
+
+ case GUI_POINTER_MENU:
+ gw->cursor = &gem_cursors.menu;
+ break;
+
+ case GUI_POINTER_CARET: /* input */
+ gw->cursor = &gem_cursors.ibeam;
+ break;
+
+ case GUI_POINTER_CROSS:
+ gw->cursor = &gem_cursors.cross;
+ break;
+
+ case GUI_POINTER_MOVE:
+ gw->cursor = &gem_cursors.sizeall;
+ break;
+
+ case GUI_POINTER_RIGHT:
+ case GUI_POINTER_LEFT:
+ gw->cursor = &gem_cursors.sizewe;
+ break;
+
+ case GUI_POINTER_UP:
+ case GUI_POINTER_DOWN:
+ gw->cursor = &gem_cursors.sizens;
+ break;
+
+ case GUI_POINTER_RU:
+ case GUI_POINTER_LD:
+ gw->cursor = &gem_cursors.sizenesw;
+ break;
+
+ case GUI_POINTER_RD:
+ case GUI_POINTER_LU:
+ gw->cursor = &gem_cursors.sizenwse;
+ break;
+
+ case GUI_POINTER_WAIT:
+ gw->cursor = &gem_cursors.wait;
+ break;
+
+ case GUI_POINTER_PROGRESS:
+ gw->cursor = &gem_cursors.appstarting;
+ break;
+
+ case GUI_POINTER_NO_DROP:
+ gw->cursor = &gem_cursors.nodrop;
+ break;
+
+ case GUI_POINTER_NOT_ALLOWED:
+ gw->cursor = &gem_cursors.deny;
+ break;
+
+ case GUI_POINTER_HELP:
+ gw->cursor = &gem_cursors.help;
+ break;
+
+ default:
+ gw->cursor = &gem_cursors.arrow;
+ break;
+ }
+
+ if (input_window == gw) {
+ gem_set_cursor(gw->cursor);
+ }
+}
+
+
+static nserror gui_window_set_url(struct gui_window *w, nsurl *url)
+{
+ int l;
+
+ if (w == NULL)
+ return NSERROR_OK;
+
+ l = strlen(nsurl_access(url))+1;
+
+ if (w->url == NULL) {
+ w->url = malloc(l);
+ } else {
+ w->url = realloc(w->url, l);
+ }
+ strncpy(w->url, nsurl_access(url), l);
+ w->url[l] = 0;
+ if(input_window == w->root->active_gui_window) {
+ toolbar_set_url(w->root->toolbar, nsurl_access(url));
+ }
+
+ return NSERROR_OK;
+}
+
+char * gui_window_get_url(struct gui_window *gw)
+{
+ if (gw == NULL) {
+ return(NULL);
+ }
+ return(gw->url);
+}
+
+char * gui_window_get_title(struct gui_window *gw)
+{
+ if (gw == NULL) {
+ return(NULL);
+ }
+ return(gw->title);
+}
+
+static void throbber_advance( void * data )
+{
+
+ struct gui_window * gw = (struct gui_window *)data;
+
+ if (gw->root == NULL)
+ return;
+ if (gw->root->toolbar == NULL)
+ return;
+
+ if (gw->root->toolbar->throbber.running == false)
+ return;
+
+ toolbar_throbber_progress(gw->root->toolbar);
+ atari_schedule(1000, throbber_advance, gw );
+}
+
+static void gui_window_start_throbber(struct gui_window *w)
+{
+ if (w == NULL)
+ return;
+
+ toolbar_set_throbber_state(w->root->toolbar, true);
+ atari_schedule(1000, throbber_advance, w );
+ rendering = true;
+}
+
+static void gui_window_stop_throbber(struct gui_window *w)
+{
+ if (w == NULL)
+ return;
+ if (w->root->toolbar->throbber.running == false)
+ return;
+
+ atari_schedule(-1, throbber_advance, w);
+
+ toolbar_set_throbber_state(w->root->toolbar, false);
+
+ rendering = false;
+}
+
+/**
+ * Place caret in window
+ */
+static void
+gui_window_place_caret(struct gui_window *w, int x, int y, int height,
+ const struct rect *clip)
+{
+ window_place_caret(w->root, 1, x, y, height, NULL);
+ w->root->caret.state |= CARET_STATE_ENABLED;
+ return;
+}
+
+
+/**
+ * clear window caret
+ */
+static void
+gui_window_remove_caret(struct gui_window *w)
+{
+ if (w == NULL)
+ return;
+
+ if ((w->root->caret.state & CARET_STATE_ENABLED) != 0) {
+ //printf("gw hide caret\n");
+ window_place_caret(w->root, 0, -1, -1, -1, NULL);
+ w->root->caret.state &= ~CARET_STATE_ENABLED;
+ }
+ return;
+}
+
+/**
+ * Set a favicon for a gui window.
+ *
+ * \param g window to update.
+ * \param icon handle to object to use as icon.
+ */
+static void
+gui_window_set_icon(struct gui_window *g, hlcache_handle *icon)
+{
+ struct bitmap *bmp_icon;
+
+ bmp_icon = (icon != NULL) ? content_get_bitmap(icon) : NULL;
+ g->icon = bmp_icon;
+ if(input_window == g) {
+ window_set_icon(g->root, bmp_icon);
+ }
+}
+
+static void gui_window_new_content(struct gui_window *w)
+{
+ struct gemtk_wm_scroll_info_s *slid = gemtk_wm_get_scroll_info(w->root->win);
+ slid->x_pos = 0;
+ slid->y_pos = 0;
+ gemtk_wm_update_slider(w->root->win, GEMTK_WM_VH_SLIDER);
+ gui_window_redraw_window(w);
+}
+
+
+/**
+ * Core asks front end for clipboard contents.
+ *
+ * \param buffer UTF-8 text, allocated by front end, ownership yeilded to core
+ * \param length Byte length of UTF-8 text in buffer
+ */
+static void gui_get_clipboard(char **buffer, size_t *length)
+{
+ char *clip;
+
+ *length = 0;
+ *buffer = 0;
+
+ clip = scrap_txt_read();
+
+ if(clip == NULL) {
+ return;
+ } else {
+
+ // clipboard is in atari encoding, convert it to utf8:
+
+ size_t clip_len;
+ char *utf8 = NULL;
+
+ clip_len = strlen(clip);
+ if (clip_len > 0) {
+ nserror ret;
+ ret = utf8_to_local_encoding(clip, clip_len, &utf8);
+ if (ret == NSERROR_OK && utf8 != NULL) {
+ *buffer = utf8;
+ *length = strlen(utf8);
+ } else {
+ assert(ret == NSERROR_OK && utf8 != NULL);
+ }
+ }
+
+ free(clip);
+ }
+}
+
+/**
+ * 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)
+{
+ if (length > 0 && buffer != NULL) {
+
+ // convert utf8 input to atari encoding:
+
+ nserror ret;
+ char *clip = NULL;
+
+ ret = utf8_to_local_encoding(buffer,length, &clip);
+ if (ret == NSERROR_OK) {
+ scrap_txt_write(clip);
+ } else {
+ assert(ret == NSERROR_OK);
+ }
+ free(clip);
+ }
+}
+
+static void gui_401login_open(nsurl *url, const char *realm,
+ nserror (*cb)(bool proceed, void *pw), void *cbpw)
+{
+ bool bres;
+ char * out = NULL;
+ bres = login_form_do( url, (char*)realm, &out);
+ if (bres) {
+ LOG("url: %s, realm: %s, auth: %s\n", nsurl_access(url), realm, out);
+ urldb_set_auth_details(url, realm, out);
+ }
+ if (out != NULL) {
+ free( out );
+ }
+ if (cb != NULL) {
+ cb(bres, cbpw);
+ }
+
+}
+
+static void
+gui_cert_verify(nsurl *url, const struct ssl_cert_info *certs,
+ unsigned long num, nserror (*cb)(bool proceed, void *pw),
+ void *cbpw)
+{
+ struct sslcert_session_data *data;
+ LOG("url %s", nsurl_access(url));
+
+ // TODO: localize string
+ int b = form_alert(1, "[2][SSL Verify failed, continue?][Continue|Abort|Details...]");
+ if(b == 1){
+ // Accept
+ urldb_set_cert_permissions(url, true);
+ cb(true, cbpw);
+ } else if(b == 2) {
+ // Reject
+ urldb_set_cert_permissions(url, false);
+ cb(false, cbpw);
+ } else if(b == 3) {
+ // Inspect
+ sslcert_viewer_create_session_data(num, url, cb, cbpw, certs,
+ &data);
+ atari_sslcert_viewer_open(data);
+ }
+
+}
+
+void gui_set_input_gui_window(struct gui_window *gw)
+{
+ LOG("Setting input window from: %p to %p\n", input_window, gw);
+ input_window = gw;
+}
+
+struct gui_window * gui_get_input_window(void)
+{
+ return(input_window);
+}
+
+static void gui_quit(void)
+{
+ LOG("quitting");
+
+ struct gui_window *gw = window_list;
+ struct gui_window *tmp = window_list;
+
+ /* Destroy all remaining browser windows: */
+ while (gw) {
+ tmp = gw->next;
+ browser_window_destroy(gw->browser->bw);
+ gw = tmp;
+ }
+
+ /* destroy the treeview windows: */
+ atari_global_history_destroy();
+ atari_hotlist_destroy();
+ atari_cookie_manager_destroy();
+
+ /* shutdown netsurf treeview framework: */
+ treeview_fini();
+
+ /* shutdown the toolbar framework: */
+ toolbar_exit();
+
+ /* save persistent informations: */
+ urldb_save_cookies(nsoption_charp(cookie_file));
+ urldb_save(nsoption_charp(url_file));
+
+ deskmenu_destroy();
+ gemtk_wm_exit();
+
+ rsrc_free();
+
+ LOG("Shutting down plotter");
+ plot_finalise();
+ LOG("done");
+}
+
+/**
+ * Process commandline parameters.
+ */
+static bool
+process_cmdline(int argc, char** argv)
+{
+ int opt;
+ bool set_default_dimensions = true;
+
+ LOG("argc %d, argv %p", argc, argv);
+
+ if ((nsoption_int(window_width) != 0) && (nsoption_int(window_height) != 0)) {
+
+ option_window_width = nsoption_int(window_width);
+ option_window_height = nsoption_int(window_height);
+ option_window_x = nsoption_int(window_x);
+ option_window_y = nsoption_int(window_y);
+
+ if (option_window_width <= desk_area.g_w
+ && option_window_height < desk_area.g_h) {
+ set_default_dimensions = false;
+ }
+ }
+
+ if (set_default_dimensions) {
+ if( sys_type() == SYS_TOS ) {
+ /* on single tasking OS, start as fulled window: */
+ option_window_width = desk_area.g_w;
+ option_window_height = desk_area.g_h;
+ option_window_x = desk_area.g_w/2-(option_window_width/2);
+ option_window_y = (desk_area.g_h/2)-(option_window_height/2);
+ } else {
+ option_window_width = 600;
+ option_window_height = 360;
+ option_window_x = 10;
+ option_window_y = 30;
+ }
+ }
+
+ if (nsoption_charp(homepage_url) != NULL)
+ option_homepage_url = nsoption_charp(homepage_url);
+ else
+ option_homepage_url = NETSURF_HOMEPAGE;
+
+ while((opt = getopt(argc, argv, "w:h:")) != -1) {
+ switch (opt) {
+ case 'w':
+ option_window_width = atoi(optarg);
+ break;
+
+ case 'h':
+ option_window_height = atoi(optarg);
+ break;
+
+ default:
+ fprintf(stderr,
+ "Usage: %s [w,h,v] url\n",
+ argv[0]);
+ return false;
+ }
+ }
+
+ if (optind < argc) {
+ option_homepage_url = argv[optind];
+ }
+ return true;
+}
+
+static inline void create_cursor(int flags, short mode, void * form,
+ MFORM_EX * m)
+{
+ m->flags = flags;
+ m->number = mode;
+ if( flags & MFORM_EX_FLAG_USERFORM ) {
+ m->number = mode;
+ m->tree = (OBJECT*)form;
+ }
+}
+
+static nsurl *gui_get_resource_url(const char *path)
+{
+ char buf[PATH_MAX];
+ nsurl *url = NULL;
+
+ atari_find_resource((char*)&buf, path, path);
+
+ netsurf_path_to_nsurl(buf, &url);
+
+ return url;
+}
+
+/**
+ * Set option defaults for atari frontend
+ *
+ * @param defaults The option table to update.
+ * @return error status.
+ */
+static nserror set_defaults(struct nsoption_s *defaults)
+{
+ /* Set defaults for absent option strings */
+ nsoption_setnull_charp(cookie_file, strdup("cookies"));
+ if (nsoption_charp(cookie_file) == NULL) {
+ LOG("Failed initialising string options");
+ return NSERROR_BAD_PARAMETER;
+ }
+ return NSERROR_OK;
+}
+
+static char *theapp = (char*)"NetSurf";
+
+/**
+ * Initialise atari gui.
+ */
+static void gui_init(int argc, char** argv)
+{
+ char buf[PATH_MAX];
+ OBJECT * cursors;
+
+ atari_find_resource(buf, "netsurf.rsc", "./res/netsurf.rsc");
+ LOG("Using RSC file: %s ", (char *)&buf);
+ if (rsrc_load(buf)==0) {
+
+ char msg[1024];
+
+ snprintf(msg, 1024, "Unable to open GEM Resource file (%s)!", buf);
+ die(msg);
+ }
+
+ wind_get_grect(0, WF_WORKXYWH, &desk_area);
+
+ create_cursor(0, POINT_HAND, NULL, &gem_cursors.hand );
+ create_cursor(0, TEXT_CRSR, NULL, &gem_cursors.ibeam );
+ create_cursor(0, THIN_CROSS, NULL, &gem_cursors.cross);
+ create_cursor(0, BUSY_BEE, NULL, &gem_cursors.wait);
+ create_cursor(0, ARROW, NULL, &gem_cursors.arrow);
+ create_cursor(0, OUTLN_CROSS, NULL, &gem_cursors.sizeall);
+ create_cursor(0, OUTLN_CROSS, NULL, &gem_cursors.sizenesw);
+ create_cursor(0, OUTLN_CROSS, NULL, &gem_cursors.sizenwse);
+ cursors = gemtk_obj_get_tree(CURSOR);
+ create_cursor(MFORM_EX_FLAG_USERFORM, CURSOR_APPSTART,
+ cursors, &gem_cursors.appstarting);
+ gem_set_cursor( &gem_cursors.appstarting );
+ create_cursor(MFORM_EX_FLAG_USERFORM, CURSOR_SIZEWE,
+ cursors, &gem_cursors.sizewe);
+ create_cursor(MFORM_EX_FLAG_USERFORM, CURSOR_SIZENS,
+ cursors, &gem_cursors.sizens);
+ create_cursor(MFORM_EX_FLAG_USERFORM, CURSOR_NODROP,
+ cursors, &gem_cursors.nodrop);
+ create_cursor(MFORM_EX_FLAG_USERFORM, CURSOR_DENY,
+ cursors, &gem_cursors.deny);
+ create_cursor(MFORM_EX_FLAG_USERFORM, CURSOR_MENU,
+ cursors, &gem_cursors.menu);
+ create_cursor(MFORM_EX_FLAG_USERFORM, CURSOR_HELP,
+ cursors, &gem_cursors.help);
+
+ LOG("Enabling core select menu");
+ nsoption_set_bool(core_select_menu, true);
+
+ LOG("Loading url.db from: %s", nsoption_charp(url_file));
+ if( strlen(nsoption_charp(url_file)) ) {
+ urldb_load(nsoption_charp(url_file));
+ }
+
+ LOG("Loading cookies from: %s", nsoption_charp(cookie_file));
+ if( strlen(nsoption_charp(cookie_file)) ) {
+ urldb_load_cookies(nsoption_charp(cookie_file));
+ }
+
+ if (process_cmdline(argc,argv) != true)
+ die("unable to process command line.\n");
+
+ LOG("Initializing NKC...");
+ nkc_init();
+
+ LOG("Initializing plotters...");
+ plot_init(nsoption_charp(atari_font_driver));
+
+ aes_event_in.emi_m1leave = MO_LEAVE;
+ aes_event_in.emi_m1.g_w = 1;
+ aes_event_in.emi_m1.g_h = 1;
+ //next_poll = clock() + (CLOCKS_PER_SEC>>3);
+
+ deskmenu_init();
+ menu_register( -1, theapp);
+ if (sys_type() & (SYS_MAGIC|SYS_NAES|SYS_XAAES)) {
+ menu_register( _AESapid, (char*)" NetSurf ");
+ }
+ gemtk_wm_init();
+
+ /* Initialize the netsurf treeview framework with default font size: */
+ treeview_init(0);
+
+ /* Initialize the specific treeview windows: */
+ atari_global_history_init();
+ atari_hotlist_init();
+ atari_cookie_manager_init();
+
+ /* Initialize the toolbar framework: */
+ toolbar_init();
+}
+
+static struct gui_window_table atari_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 = atari_window_reformat,
+
+ .set_title = gui_window_set_title,
+ .set_url = gui_window_set_url,
+ .set_icon = gui_window_set_icon,
+ .set_status = atari_window_set_status,
+ .set_pointer = gui_window_set_pointer,
+ .place_caret = gui_window_place_caret,
+ .remove_caret = gui_window_remove_caret,
+ .new_content = gui_window_new_content,
+ .start_throbber = gui_window_start_throbber,
+ .stop_throbber = gui_window_stop_throbber,
+};
+
+static struct gui_clipboard_table atari_clipboard_table = {
+ .get = gui_get_clipboard,
+ .set = gui_set_clipboard,
+};
+
+static struct gui_fetch_table atari_fetch_table = {
+ .filetype = fetch_filetype,
+
+ .get_resource_url = gui_get_resource_url,
+};
+
+static struct gui_misc_table atari_misc_table = {
+ .schedule = atari_schedule,
+ .warning = atari_warn_user,
+
+ .quit = gui_quit,
+ .cert_verify = gui_cert_verify,
+ .login = gui_401login_open,
+};
+
+/* #define WITH_DBG_LOGFILE 1 */
+/**
+ * Entry point from OS.
+ *
+ * /param argc The number of arguments in the string vector.
+ * /param argv The argument string vector.
+ * /return The return code to the OS
+ */
+int main(int argc, char** argv)
+{
+ char messages[PATH_MAX];
+ char store[PATH_MAX];
+ const char *addr;
+ char * file_url = NULL;
+ struct stat stat_buf;
+ nsurl *url;
+ nserror ret;
+
+ struct netsurf_table atari_table = {
+ .misc = &atari_misc_table,
+ .window = &atari_window_table,
+ .clipboard = &atari_clipboard_table,
+ .download = atari_download_table,
+ .fetch = &atari_fetch_table,
+ .file = atari_file_table,
+ .utf8 = atari_utf8_table,
+ .search = atari_search_table,
+ .llcache = filesystem_llcache_table,
+ .bitmap = atari_bitmap_table,
+ .layout = atari_layout_table
+ };
+
+ ret = netsurf_register(&atari_table);
+ if (ret != NSERROR_OK) {
+ die("NetSurf operation table failed registration");
+ }
+
+ /** @todo logging file descriptor update belongs in a nslog_init callback */
+ setbuf(stderr, NULL);
+ setbuf(stdout, NULL);
+#ifdef WITH_DBG_LOGFILE
+ freopen("stdout.log", "a+", stdout);
+ freopen("stderr.log", "a+", stderr);
+#endif
+
+ graf_mouse(BUSY_BEE, NULL);
+
+ init_app(NULL);
+
+ init_os_info();
+
+ atari_find_resource((char*)&messages, "messages", "res/messages");
+ atari_find_resource((char*)&options, "Choices", "Choices");
+ atari_find_resource((char*)&store, "cache", "res/cache");
+
+ /* initialise logging - not fatal if it fails but not much we can
+ * do about it
+ */
+ nslog_init(NULL, &argc, argv);
+
+ /* user options setup */
+ ret = nsoption_init(set_defaults, &nsoptions, &nsoptions_default);
+ if (ret != NSERROR_OK) {
+ die("Options failed to initialise");
+ }
+ nsoption_read(options, NULL);
+ nsoption_commandline(&argc, argv, NULL);
+
+ ret = messages_add_from_file(messages);
+
+ /* common initialisation */
+ LOG("Initialising core...");
+ ret = netsurf_init(store);
+ if (ret != NSERROR_OK) {
+ die("NetSurf failed to initialise");
+ }
+
+ LOG("Initializing GUI...");
+ gui_init(argc, argv);
+
+ graf_mouse( ARROW , NULL);
+
+ LOG("Creating initial browser window...");
+ addr = option_homepage_url;
+ if (strncmp(addr, "file://", 7) && strncmp(addr, "http://", 7)) {
+ if (stat(addr, &stat_buf) == 0) {
+ file_url = local_file_to_url(addr);
+ addr = file_url;
+ }
+ }
+
+ /* create an initial browser window */
+ ret = nsurl_create(addr, &url);
+ if (ret == NSERROR_OK) {
+ ret = browser_window_create(BW_CREATE_HISTORY,
+ url,
+ NULL,
+ NULL,
+ NULL);
+ nsurl_unref(url);
+ }
+ if (ret != NSERROR_OK) {
+ atari_warn_user(messages_get_errorcode(ret), 0);
+ } else {
+ LOG("Entering Atari event mainloop...");
+ while (!atari_quit) {
+ atari_poll();
+ }
+ }
+
+ netsurf_exit();
+
+ free(file_url);
+
+#ifdef WITH_DBG_LOGFILE
+ fclose(stdout);
+ fclose(stderr);
+#endif
+ LOG("exit_gem");
+ exit_gem();
+
+ return 0;
+}
diff --git a/frontends/atari/gui.h b/frontends/atari/gui.h
new file mode 100644
index 000000000..50184d029
--- /dev/null
+++ b/frontends/atari/gui.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.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 NS_ATARI_GUI_H_
+#define NS_ATARI_GUI_H_
+
+#include <stdbool.h>
+#include <mt_gem.h>
+
+#include "desktop/mouse.h"
+
+#include "atari/redrawslots.h"
+#include "atari/gemtk/gemtk.h"
+
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
+#define CARET_STATE_VISIBLE 0x01
+#define CARET_STATE_ENABLED 0x02
+
+struct s_caret {
+ GRECT dimensions;
+ MFDB symbol;
+ int fd_size;
+ unsigned short state;
+};
+
+struct point_s {
+ int x;
+ int y;
+};
+
+typedef struct point_s POINT;
+
+#define MFORM_EX_FLAG_USERFORM 0x01
+
+struct mform_ex_s
+{
+ unsigned char flags;
+ int number;
+ OBJECT * tree;
+};
+
+typedef struct mform_ex_s MFORM_EX;
+
+struct s_gem_cursors {
+ MFORM_EX hand;
+ MFORM_EX ibeam;
+ MFORM_EX cross;
+ MFORM_EX sizeall;
+ MFORM_EX sizewe;
+ MFORM_EX sizens;
+ MFORM_EX sizenesw;
+ MFORM_EX sizenwse;
+ MFORM_EX wait;
+ MFORM_EX appstarting;
+ MFORM_EX nodrop;
+ MFORM_EX deny;
+ MFORM_EX help;
+ MFORM_EX menu;
+ MFORM_EX arrow;
+} gem_cursors;
+
+enum focus_element_type {
+ WIDGET_NONE=0,
+ URL_WIDGET,
+ SEARCH_INPUT,
+ BROWSER
+};
+
+
+struct s_focus_info
+{
+ enum focus_element_type type;
+ void * element;
+};
+
+/* defines for data attached to components: */
+#define CDT_OBJECT 0x004f424aUL
+#define CDT_OWNER 0x03UL
+#define CDT_ICON 0x04UL
+#define CDT_ICON_TYPE 0x05UL
+# define CDT_ICON_TYPE_NONE 0x00UL
+# define CDT_ICON_TYPE_OBJECT 0x01UL
+# define CDT_ICON_TYPE_BITMAP 0x02UL
+
+
+struct gui_window;
+struct s_browser;
+struct s_statusbar;
+struct s_toolbar;
+
+typedef struct s_toolbar * CMP_TOOLBAR;
+typedef struct s_statusbar * CMP_STATUSBAR;
+typedef struct s_browser * CMP_BROWSER;
+
+/*
+ This is the "main" window. It can consist of several components
+ and also holds information shared by several frames within
+ the window.
+*/
+struct s_gui_win_root
+{
+ short aes_handle;
+ GUIWIN *win;
+ CMP_TOOLBAR toolbar;
+ CMP_STATUSBAR statusbar;
+ struct s_focus_info focus;
+ float scale;
+ char * title;
+ struct bitmap * icon;
+ struct gui_window *active_gui_window;
+ struct s_redrw_slots redraw_slots;
+ struct s_caret caret;
+ /* current size of window on screen: */
+ GRECT loc;
+};
+typedef struct s_gui_win_root ROOTWIN;
+
+struct s_browser
+{
+ struct browser_window * bw;
+ bool attached;
+};
+
+/*
+ This is the part of the gui which is known by netsurf core.
+ You must implement it. Altough, you are free how to do it.
+ Each of the browser "viewports" managed by netsurf are bound
+ to this structure.
+*/
+struct gui_window {
+ struct s_gui_win_root * root;
+ struct s_browser * browser;
+ MFORM_EX *cursor;
+ /* icon to be drawn when iconified, or NULL for default resource. */
+ char * status;
+ char * title;
+ char * url;
+ float scale;
+ struct bitmap * icon;
+ struct s_caret caret;
+ struct s_search_form_session *search;
+ struct gui_window *next, *prev;
+};
+
+extern struct gui_window *window_list;
+
+/* -------------------------------------------------------------------------- */
+/* Public - non core gui window functions */
+/* -------------------------------------------------------------------------- */
+void gui_set_input_gui_window(struct gui_window *gw);
+struct gui_window *gui_get_input_window(void);
+char *gui_window_get_url(struct gui_window *gw);
+char *gui_window_get_title(struct gui_window *gw);
+
+/**
+ * Set the status bar of a browser window.
+ *
+ * \param w The gui_window to update.
+ * \param text new status text
+ */
+void atari_window_set_status(struct gui_window *w, const char *text);
+void gui_window_set_pointer(struct gui_window *gw, gui_pointer_shape shape);
+void gui_window_destroy(struct gui_window *w);
+
+#endif
diff --git a/frontends/atari/history.c b/frontends/atari/history.c
new file mode 100644
index 000000000..ba72c7f00
--- /dev/null
+++ b/frontends/atari/history.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2013 Ole Loots <ole@monochrom.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 <inttypes.h>
+
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "desktop/mouse.h"
+#include "desktop/global_history.h"
+#include "desktop/core_window.h"
+
+#include "atari/treeview.h"
+#include "atari/history.h"
+#include "atari/gemtk/gemtk.h"
+#include "atari/res/netsurf.rsh"
+
+extern GRECT desk_area;
+
+struct atari_global_history_s atari_global_history;
+
+/* Setup Atari Treeview Callbacks: */
+
+static nserror
+atari_global_history_init_phase2(struct core_window *cw,
+ struct core_window_callback_table *cb_t)
+{
+ LOG("cw %p", cw);
+ return(global_history_init(cb_t, cw));
+}
+
+static void atari_global_history_finish(struct core_window *cw)
+{
+ LOG("cw %p", cw);
+ global_history_fini();
+}
+
+static void atari_global_history_draw(struct core_window *cw, int x,
+ int y, struct rect *clip,
+ const struct redraw_context *ctx)
+{
+ global_history_redraw(x, y, clip, ctx);
+}
+
+static void atari_global_history_keypress(struct core_window *cw, uint32_t ucs4)
+{
+ LOG("ucs4: %"PRIu32, ucs4);
+ global_history_keypress(ucs4);
+}
+
+static void
+atari_global_history_mouse_action(struct core_window *cw,
+ browser_mouse_state mouse,
+ int x, int y)
+{
+ LOG("x: %d, y: %d\n", x, y);
+
+ global_history_mouse_action(mouse, x, y);
+}
+
+void atari_global_history_close(void)
+{
+ atari_treeview_close(atari_global_history.tv);
+}
+
+
+static short handle_event(GUIWIN *win, EVMULT_OUT *ev_out, short msg[8])
+{
+ short retval = 0;
+
+ LOG("win %p", win);
+
+ if (ev_out->emo_events & MU_MESAG) {
+ switch (msg[0]) {
+ case WM_CLOSED:
+ atari_global_history_close();
+ retval = 1;
+ break;
+
+ default: break;
+ }
+ }
+
+ return(retval);
+}
+
+static struct atari_treeview_callbacks atari_global_history_treeview_callbacks = {
+ .init_phase2 = atari_global_history_init_phase2,
+ .finish = atari_global_history_finish,
+ .draw = atari_global_history_draw,
+ .keypress = atari_global_history_keypress,
+ .mouse_action = atari_global_history_mouse_action,
+ .gemtk_user_func = handle_event
+};
+
+void atari_global_history_init(void)
+{
+ if (atari_global_history.init == false) {
+ if( atari_global_history.window == NULL ) {
+ int flags = ATARI_TREEVIEW_WIDGETS;
+ short handle = -1;
+ OBJECT * tree = gemtk_obj_get_tree(TOOLBAR_HISTORY);
+ assert( tree );
+
+ handle = wind_create(flags, 0, 0, desk_area.g_w, desk_area.g_h);
+ atari_global_history.window = gemtk_wm_add(handle, GEMTK_WM_FLAG_DEFAULTS, NULL);
+ if( atari_global_history.window == NULL ) {
+ gemtk_msg_box_show(GEMTK_MSG_BOX_ALERT,
+ "Failed to allocate History");
+ return;
+ }
+ wind_set_str(handle, WF_NAME, (char*)messages_get("History"));
+ gemtk_wm_set_toolbar(atari_global_history.window, tree, 0, 0);
+ gemtk_wm_unlink(atari_global_history.window);
+
+ atari_global_history.tv = atari_treeview_create(
+ atari_global_history.window,
+ &atari_global_history_treeview_callbacks,
+ NULL, flags);
+
+ if (atari_global_history.tv == NULL) {
+ /* handle it properly, clean up previous allocs */
+ LOG("Failed to allocate treeview");
+ return;
+ }
+ }
+ }
+ atari_global_history.init = true;
+}
+
+void atari_global_history_open(void)
+{
+ assert(atari_global_history.init);
+
+ if (atari_global_history.init == false) {
+ return;
+ }
+
+ if (atari_treeview_is_open(atari_global_history.tv) == false) {
+
+ GRECT pos;
+ pos.g_x = desk_area.g_w - desk_area.g_w / 4;
+ pos.g_y = desk_area.g_y;
+ pos.g_w = desk_area.g_w / 4;
+ pos.g_h = desk_area.g_h;
+
+ atari_treeview_open(atari_global_history.tv, &pos);
+ } else {
+ wind_set(gemtk_wm_get_handle(atari_global_history.window), WF_TOP, 1, 0, 0, 0);
+ }
+}
+
+
+void atari_global_history_destroy(void)
+{
+
+ if ( atari_global_history.init == false) {
+ return;
+ }
+
+ if ( atari_global_history.window != NULL ) {
+ if (atari_treeview_is_open(atari_global_history.tv))
+ atari_global_history_close();
+ wind_delete(gemtk_wm_get_handle(atari_global_history.window));
+ gemtk_wm_remove(atari_global_history.window);
+ atari_global_history.window = NULL;
+ atari_treeview_delete(atari_global_history.tv);
+ atari_global_history.init = false;
+ }
+ LOG("done");
+}
+
+void atari_global_history_redraw(void)
+{
+ atari_treeview_redraw(atari_global_history.tv);
+}
diff --git a/frontends/atari/history.h b/frontends/atari/history.h
new file mode 100644
index 000000000..06a5d32f2
--- /dev/null
+++ b/frontends/atari/history.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2013 Ole Loots <ole@monochrom.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 NS_ATARI_HISTORY_H
+#define NS_ATARI_HISTORY_H
+
+struct core_window;
+
+struct atari_global_history_s {
+ GUIWIN * window;
+ //struct atari_treeview_window * tv; /*< The hotlist treeview handle. */
+ struct core_window *tv;
+ bool init;
+};
+
+extern struct atari_global_history_s atari_global_history;
+
+void atari_global_history_init(void);
+void atari_global_history_open(void);
+void atari_global_history_close(void);
+void atari_global_history_destroy(void);
+void atari_global_history_redraw(void);
+
+#endif
diff --git a/frontends/atari/hotlist.c b/frontends/atari/hotlist.c
new file mode 100644
index 000000000..1130e6251
--- /dev/null
+++ b/frontends/atari/hotlist.c
@@ -0,0 +1,315 @@
+/*
+ * Copyright 2013 Ole Loots <ole@monochrom.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 <ctype.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/utils.h"
+#include "content/content.h"
+#include "content/hlcache.h"
+#include "content/urldb.h"
+#include "utils/nsoption.h"
+#include "desktop/hotlist.h"
+#include "desktop/tree.h"
+#include "desktop/core_window.h"
+
+#include "atari/gui.h"
+#include "atari/misc.h"
+#include "atari/treeview.h"
+#include "atari/hotlist.h"
+#include "atari/findfile.h"
+#include "atari/gemtk/gemtk.h"
+#include "atari/res/netsurf.rsh"
+
+extern GRECT desk_area;
+
+struct atari_hotlist hl;
+
+/* Setup Atari Treeview Callbacks: */
+static nserror atari_hotlist_init_phase2(struct core_window *cw,
+ struct core_window_callback_table * default_callbacks);
+static void atari_hotlist_finish(struct core_window *cw);
+static void atari_hotlist_keypress(struct core_window *cw,
+ uint32_t ucs4);
+static void atari_hotlist_mouse_action(struct core_window *cw,
+ browser_mouse_state mouse,
+ int x, int y);
+static void atari_hotlist_draw(struct core_window *cw, int x,
+ int y, struct rect *clip,
+ const struct redraw_context *ctx);
+static short handle_event(GUIWIN *win, EVMULT_OUT *ev_out, short msg[8]);
+
+static struct atari_treeview_callbacks atari_hotlist_treeview_callbacks = {
+ .init_phase2 = atari_hotlist_init_phase2,
+ .finish = atari_hotlist_finish,
+ .draw = atari_hotlist_draw,
+ .keypress = atari_hotlist_keypress,
+ .mouse_action = atari_hotlist_mouse_action,
+ .gemtk_user_func = handle_event
+};
+
+static nserror atari_hotlist_init_phase2(struct core_window *cw,
+ struct core_window_callback_table *cb_t)
+{
+ LOG("cw:%p", cw);
+ return(hotlist_init(cb_t, cw, hl.path));
+}
+
+static void atari_hotlist_finish(struct core_window *cw)
+{
+ LOG("cw:%p", cw);
+ hotlist_fini(hl.path);
+}
+
+static void atari_hotlist_draw(struct core_window *cw, int x,
+ int y, struct rect *clip,
+ const struct redraw_context *ctx)
+{
+ hotlist_redraw(x, y, clip, ctx);
+}
+
+static void atari_hotlist_keypress(struct core_window *cw, uint32_t ucs4)
+{
+ GUIWIN *gemtk_win;
+ GRECT area;
+ LOG("ucs4: %"PRIu32 , ucs4);
+ hotlist_keypress(ucs4);
+ gemtk_win = atari_treeview_get_gemtk_window(cw);
+ atari_treeview_get_grect(cw, TREEVIEW_AREA_CONTENT, &area);
+ //gemtk_wm_exec_redraw(gemtk_win, &area);
+}
+
+static void atari_hotlist_mouse_action(struct core_window *cw,
+ browser_mouse_state mouse,
+ int x, int y)
+{
+ LOG("x: %d, y: %d\n", x, y);
+
+ hotlist_mouse_action(mouse, x, y);
+}
+
+
+
+static short handle_event(GUIWIN *win, EVMULT_OUT *ev_out, short msg[8])
+{
+ char *cur_url = NULL;
+ char *cur_title = NULL;
+ short retval = 0;
+ struct atari_treeview_window *tv = NULL;
+ struct core_window *cw;
+ struct gui_window * gw;
+ OBJECT *toolbar;
+ GRECT tb_area;
+ GUIWIN * gemtk_win;
+
+ LOG("gw:%p", win);
+
+ tv = (struct atari_treeview_window*) gemtk_wm_get_user_data(win);
+ cw = (struct core_window *)tv;
+
+ if (ev_out->emo_events & MU_MESAG) {
+ switch (msg[0]) {
+
+ case WM_TOOLBAR:
+ LOG("WM_TOOLBAR");
+
+ toolbar = gemtk_obj_get_tree(TOOLBAR_HOTLIST);
+
+ assert(toolbar);
+ assert(tv);
+
+ switch (msg[4]) {
+ case TOOLBAR_HOTLIST_CREATE_FOLDER:
+ hotlist_add_folder(NULL, 0, 0);
+ break;
+
+ case TOOLBAR_HOTLIST_ADD:
+ gw = gui_get_input_window();
+ if(gw && gw->browser){
+ cur_url = gui_window_get_url(gw);
+ cur_title = gui_window_get_title(gw);
+ // TODO: read language string.
+ cur_title = (cur_title ? cur_title : (char*)"New bookmark");
+ } else {
+ cur_url = (char*)"http://www";
+ }
+ atari_hotlist_add_page(cur_url, cur_title);
+ break;
+
+ case TOOLBAR_HOTLIST_DELETE:
+ hotlist_keypress(NS_KEY_DELETE_LEFT);
+ break;
+
+ case TOOLBAR_HOTLIST_EDIT:
+ hotlist_edit_selection();
+ break;
+ }
+
+ gemtk_win = atari_treeview_get_gemtk_window(cw);
+ assert(gemtk_win);
+ toolbar[msg[4]].ob_state &= ~OS_SELECTED;
+ atari_treeview_get_grect(cw, TREEVIEW_AREA_TOOLBAR, &tb_area);
+ evnt_timer(150);
+ gemtk_wm_exec_redraw(gemtk_win, &tb_area);
+ retval = 1;
+ break;
+
+ case WM_CLOSED:
+ atari_hotlist_close();
+ retval = 1;
+ break;
+
+ default: break;
+ }
+ }
+
+ return(retval);
+}
+
+
+
+void atari_hotlist_init(void)
+{
+ if (hl.init == false) {
+ if( strcmp(nsoption_charp(hotlist_file), "") == 0 ){
+ atari_find_resource( (char*)&hl.path, "hotlist", "hotlist" );
+ } else {
+ strncpy( (char*)&hl.path, nsoption_charp(hotlist_file), PATH_MAX-1 );
+ }
+
+ LOG("Hotlist: %s", (char *)&hl.path);
+
+ if( hl.window == NULL ){
+ int flags = ATARI_TREEVIEW_WIDGETS;
+ short handle = -1;
+ OBJECT * tree = gemtk_obj_get_tree(TOOLBAR_HOTLIST);
+ assert( tree );
+
+ handle = wind_create(flags, 0, 0, desk_area.g_w, desk_area.g_h);
+ hl.window = gemtk_wm_add(handle, GEMTK_WM_FLAG_DEFAULTS, NULL);
+ if( hl.window == NULL ) {
+ gemtk_msg_box_show(GEMTK_MSG_BOX_ALERT,
+ "Failed to allocate Hotlist");
+ return;
+ }
+ wind_set_str(handle, WF_NAME, (char*)messages_get("Hotlist"));
+ gemtk_wm_set_toolbar(hl.window, tree, 0, 0);
+ gemtk_wm_unlink(hl.window);
+ tree_hotlist_path = (const char*)&hl.path;
+
+ hl.tv = atari_treeview_create(hl.window, &atari_hotlist_treeview_callbacks,
+ NULL, flags);
+
+ if (hl.tv == NULL) {
+ /* handle it properly, clean up previous allocs */
+ LOG("Failed to allocate treeview");
+ return;
+ }
+
+ } else {
+
+ }
+ }
+ hl.init = true;
+}
+
+void atari_hotlist_open(void)
+{
+ assert(hl.init);
+ if (hl.init == false) {
+ return;
+ }
+
+ if (atari_treeview_is_open(hl.tv) == false) {
+
+ GRECT pos;
+ pos.g_x = desk_area.g_w - desk_area.g_w / 4;
+ pos.g_y = desk_area.g_y;
+ pos.g_w = desk_area.g_w / 4;
+ pos.g_h = desk_area.g_h;
+
+ atari_treeview_open(hl.tv, &pos);
+ } else {
+ wind_set(gemtk_wm_get_handle(hl.window), WF_TOP, 1, 0, 0, 0);
+ }
+}
+
+void atari_hotlist_close(void)
+{
+ atari_treeview_close(hl.tv);
+}
+
+void atari_hotlist_destroy(void)
+{
+
+ if( hl.init == false) {
+ return;
+ }
+ if( hl.window != NULL ) {
+ if (atari_treeview_is_open(hl.tv))
+ atari_hotlist_close();
+ wind_delete(gemtk_wm_get_handle(hl.window));
+ gemtk_wm_remove(hl.window);
+ hl.window = NULL;
+ atari_treeview_delete(hl.tv);
+ hl.init = false;
+ }
+ LOG("done");
+}
+
+void atari_hotlist_redraw(void)
+{
+ atari_treeview_redraw(hl.tv);
+}
+
+struct node;
+
+void atari_hotlist_add_page( const char * url, const char * title )
+{
+ nsurl *nsurl;
+
+ if(hl.tv == NULL)
+ return;
+
+ atari_hotlist_open();
+
+ if (nsurl_create(url, &nsurl) != NSERROR_OK)
+ return;
+
+ if (hotlist_has_url(nsurl)) {
+ LOG("URL already added as Bookmark");
+ nsurl_unref(nsurl);
+ return;
+ }
+
+ /* doesn't look nice:
+ if( hl.tv->click.x >= 0 && hl.tv->click.y >= 0 ){
+ hotlist_add_entry( nsurl, title, true, hl.tv->click.y );
+ } else {
+
+ }*/
+ //hotlist_add_url(nsurl);
+ hotlist_add_entry(nsurl, title, 0, 0);
+ nsurl_unref(nsurl);
+}
diff --git a/frontends/atari/hotlist.h b/frontends/atari/hotlist.h
new file mode 100644
index 000000000..159878233
--- /dev/null
+++ b/frontends/atari/hotlist.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2013 Ole Loots <ole@monochrom.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 NS_ATARI_HOTLIST_H
+#define NS_ATARI_HOTLIST_H
+
+#include <stdbool.h>
+
+#include "desktop/tree.h"
+#include "atari/gemtk/gemtk.h"
+#include "atari/treeview.h"
+
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
+/* The hotlist window, toolbar and treeview data. */
+
+struct atari_hotlist {
+ GUIWIN * window;
+ //ATARI_TREEVIEW_PTR tv;/*< The hotlist treeview handle. */
+ struct core_window *tv;
+ bool init;
+ char path[PATH_MAX];
+};
+
+extern struct atari_hotlist hl;
+
+void atari_hotlist_init( void );
+void atari_hotlist_open( void );
+void atari_hotlist_close( void );
+void atari_hotlist_destroy( void );
+void atari_hotlist_add_page( const char * url, const char * title );
+void atari_hotlist_redraw( void );
+
+
+#endif
diff --git a/frontends/atari/login.c b/frontends/atari/login.c
new file mode 100644
index 000000000..c44b07750
--- /dev/null
+++ b/frontends/atari/login.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.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 <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <cflib.h>
+
+#include "utils/errors.h"
+#include "utils/utils.h"
+#include "utils/messages.h"
+#include "utils/log.h"
+#include "content/content.h"
+#include "content/hlcache.h"
+#include "content/urldb.h"
+#include "content/fetch.h"
+
+#include "atari/gui.h"
+#include "atari/misc.h"
+#include "atari/login.h"
+#include "atari/res/netsurf.rsh"
+
+
+bool login_form_do(nsurl * url, char * realm, char ** out)
+{
+ char user[255];
+ char pass[255];
+ //const char * auth;
+ short exit_obj = 0;
+ OBJECT * tree;
+
+ user[0] = 0;
+ pass[0] = 0;
+
+ // TODO: use auth details for predefined login data
+ // auth = urldb_get_auth_details(url, realm);
+ tree = gemtk_obj_get_tree(LOGIN);
+
+ assert(tree != NULL);
+
+ exit_obj = simple_mdial(tree, 0);
+
+ if(exit_obj == LOGIN_BT_LOGIN) {
+ get_string(tree, LOGIN_TB_USER, user);
+ get_string(tree, LOGIN_TB_PASSWORD, pass);
+ int size = strlen((char*)&user) + strlen((char*)&pass) + 2 ;
+ *out = malloc(size);
+ snprintf(*out, size, "%s:%s", user, pass);
+ } else {
+ *out = NULL;
+ }
+ return((exit_obj == LOGIN_BT_LOGIN));
+}
+
diff --git a/frontends/atari/login.h b/frontends/atari/login.h
new file mode 100644
index 000000000..b61808c71
--- /dev/null
+++ b/frontends/atari/login.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.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 NS_LOGIN_H_INCLUDED
+#define NS_LOGIN_H_INCLUDED
+
+#include "utils/nsurl.h"
+
+bool login_form_do( nsurl * host, char * realm, char **cbpw );
+
+#endif
diff --git a/frontends/atari/misc.c b/frontends/atari/misc.c
new file mode 100644
index 000000000..8688b93fd
--- /dev/null
+++ b/frontends/atari/misc.c
@@ -0,0 +1,408 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.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 <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <mint/osbind.h>
+
+#include "utils/dirent.h"
+#include "content/content.h"
+#include "content/hlcache.h"
+#include "desktop/cookie_manager.h"
+#include "desktop/mouse.h"
+#include "desktop/tree.h"
+#include "utils/nsoption.h"
+#include "utils/messages.h"
+#include "utils/utils.h"
+#include "utils/log.h"
+#include "utils/file.h"
+#include "content/fetch.h"
+
+#include "atari/gui.h"
+#include "atari/toolbar.h"
+
+#include "atari/misc.h"
+#include "atari/encoding.h"
+#include "atari/gemtk/gemtk.h"
+#include "cflib.h"
+
+extern void * h_gem_rsrc;
+
+struct is_process_running_callback_data {
+ const char * fname;
+ bool found;
+};
+
+/* exported function documented in atari/misc/h */
+nserror atari_warn_user(const char *warning, const char *detail)
+{
+ size_t len = 1 + ((warning != NULL) ? strlen(messages_get(warning)) :
+ 0) + ((detail != 0) ? strlen(detail) : 0);
+ char message[len];
+ snprintf(message, len, messages_get(warning), detail);
+
+ printf("%s\n", message);
+ gemtk_msg_box_show(GEMTK_MSG_BOX_ALERT, message);
+
+ return NSERROR_OK;
+}
+
+void die(const char *error)
+{
+ printf("%s\n", error);
+ gemtk_msg_box_show(GEMTK_MSG_BOX_ALERT, error);
+ exit(1);
+}
+
+
+struct gui_window * find_guiwin_by_aes_handle(short handle){
+
+ struct gui_window * gw;
+ gw = window_list;
+
+ if( handle == 0 ){
+ return( NULL );
+ }
+
+ while(gw != NULL) {
+ if(gw->root->win != NULL
+ && gemtk_wm_get_handle(gw->root->win) == handle) {
+ return(gw);
+ }
+ else
+ gw = gw->next;
+ }
+
+ return( NULL );
+}
+
+
+static int scan_process_list(scan_process_callback cb, void *data)
+{
+ int pid, count = 0;
+ DIR *dir;
+ char*dirname;
+ struct dirent *de;
+
+ if (( dir = opendir("U:/kern")) == NULL)
+ return(0);
+
+ while ((de = readdir( dir)) != NULL) {
+ dirname = de->d_name;
+
+ if( dirname[0] != '1' && dirname[0] != '2' && dirname[0] != '3' && dirname[0] != '4' && dirname[0] != '5'
+ && dirname[0] != '6' && dirname[0] != '7' && dirname[0] != '8' && dirname[0] != '9')
+ continue;
+
+ count++;
+ if (cb != NULL) {
+ /* when callback returns negative value, we stop scanning: */
+ pid = atoi(dirname);
+ if (cb(pid, data)<0) {
+ break;
+ }
+ }
+ }
+
+ closedir(dir);
+
+ return(count);
+}
+
+static int proc_running_callback(int pid, void * arg)
+{
+ char buf[PATH_MAX], fnamepath[256];
+ FILE *fp;
+ int nread;
+ struct is_process_running_callback_data *data;
+
+ data = (struct is_process_running_callback_data *)arg;
+
+ sprintf(fnamepath, "U:\\kern\\%d\\fname", pid);
+ printf("checking: %s\n", fnamepath);
+
+ fp = fopen(fnamepath, "r");
+ if(!fp)
+ return(0);
+
+ nread = fread(buf, 1, PATH_MAX-1, fp);
+ fclose(fp);
+ nread = MIN(PATH_MAX-1, nread);
+
+ if (nread > 0) {
+ buf[nread] = 0;
+
+ char *lastslash = strrchr(buf, '/');
+
+ if(lastslash == NULL)
+ lastslash = strrchr(buf, '\\');
+
+ if(lastslash==NULL)
+ lastslash = buf;
+ else
+ lastslash++;
+
+ if(strcasecmp(lastslash, data->fname)==0){
+ /* found process, check status: */
+ sprintf(fnamepath, "U:\\kern\\%d\\status", pid);
+ fp = fopen(fnamepath, "r");
+ if (fp) {
+ nread = fread(buf, 1, PATH_MAX-1, fp);
+ fclose(fp);
+ if (nread>0) {
+ nread = MIN(PATH_MAX-1,nread);
+ }
+ buf[nread] = 0;
+ if (strstr(buf, "zombie")==NULL) {
+ data->found = true;
+ return(-1);
+ }
+ }
+
+ }
+ }
+ return(0);
+}
+
+bool is_process_running(const char * name)
+{
+ struct is_process_running_callback_data data = {name, false};
+
+ scan_process_list(proc_running_callback, &data);
+
+ return( (data.found==1) ? true : false );
+}
+
+
+void gem_set_cursor( MFORM_EX * cursor )
+{
+ static unsigned char flags = 255;
+ static int number = 255;
+ if( flags == cursor->flags && number == cursor->number )
+ return;
+ if( cursor->flags & MFORM_EX_FLAG_USERFORM ) {
+ gemtk_obj_mouse_sprite(cursor->tree, cursor->number);
+ } else {
+ graf_mouse(cursor->number, NULL );
+ }
+ number = cursor->number;
+ flags = cursor->flags;
+}
+
+
+/* exported interface documented in atari/misc.h */
+long nkc_to_input_key(short nkc, long * ucs4_out)
+{
+ unsigned char ascii = (nkc & 0xFF);
+ long ik = 0;
+
+ // initialize result:
+ *ucs4_out = 0;
+
+ // sanitize input key:
+ nkc = (nkc & (NKF_CTRL|NKF_SHIFT|0xFF));
+
+ /* shift + cntrl key: */
+ if( ((nkc & NKF_CTRL) == NKF_CTRL) && ((nkc & (NKF_SHIFT))!=0) ) {
+
+ }
+ /* cntrl key only: */
+ else if( (nkc & NKF_CTRL) == NKF_CTRL ) {
+ switch ( ascii ) {
+ case 'A':
+ ik = NS_KEY_SELECT_ALL;
+ break;
+
+ case 'C':
+ ik = NS_KEY_COPY_SELECTION;
+ break;
+
+ case 'X':
+ ik = NS_KEY_CUT_SELECTION;
+ break;
+
+ case 'V':
+ ik = NS_KEY_PASTE;
+ break;
+
+ default:
+ break;
+ }
+ }
+ /* shift key only: */
+ else if( (nkc & NKF_SHIFT) != 0 ) {
+ switch( ascii ) {
+ case NK_TAB:
+ ik = NS_KEY_SHIFT_TAB;
+ break;
+
+ case NK_LEFT:
+ ik = NS_KEY_LINE_START;
+ break;
+
+ case NK_RIGHT:
+ ik = NS_KEY_LINE_END;
+ break;
+
+ case NK_UP:
+ ik = NS_KEY_PAGE_UP;
+ break;
+
+ case NK_DOWN:
+ ik = NS_KEY_PAGE_DOWN;
+ break;
+
+ default:
+ break;
+ }
+ }
+ /* No modifier keys: */
+ else {
+ switch( ascii ) {
+
+ case NK_INS:
+ ik = NS_KEY_PASTE;
+ break;
+
+ case NK_BS:
+ ik = NS_KEY_DELETE_LEFT;
+ break;
+
+ case NK_DEL:
+ ik = NS_KEY_DELETE_RIGHT;
+ break;
+
+ case NK_TAB:
+ ik = NS_KEY_TAB;
+ break;
+
+
+ case NK_ENTER:
+ ik = NS_KEY_NL;
+ break;
+
+ case NK_RET:
+ ik = NS_KEY_CR;
+ break;
+
+ case NK_ESC:
+ ik = NS_KEY_ESCAPE;
+ break;
+
+ case NK_CLRHOME:
+ ik = NS_KEY_TEXT_START;
+ break;
+
+ case NK_RIGHT:
+ ik = NS_KEY_RIGHT;
+ break;
+
+ case NK_LEFT:
+ ik = NS_KEY_LEFT;
+ break;
+
+ case NK_UP:
+ ik = NS_KEY_UP;
+ break;
+
+ case NK_UNDO:
+ ik = NS_KEY_UNDO;
+ break;
+
+ case NK_DOWN:
+ ik = NS_KEY_DOWN;
+ break;
+
+ case NK_M_PGUP:
+ ik = NS_KEY_PAGE_UP;
+ break;
+
+ case NK_M_PGDOWN:
+ ik = NS_KEY_PAGE_DOWN;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if( ik == 0 && ( (nkc & NKF_CTRL)==0) ) {
+ if (ascii >= 9 ) {
+ *ucs4_out = atari_to_ucs4(ascii);
+ }
+ }
+ return ( ik );
+}
+
+/**
+ * Show default file selector
+ *
+ * \param title The selector title.
+ * \param name Default file name
+ * \return a static char pointer or null if the user aborted the selection.
+ */
+const char * file_select(const char * title, const char * name) {
+
+ static char path[PATH_MAX]=""; // First usage : current directory
+ static char fullname[PATH_MAX]="";
+ char tmpname[255];
+ char * use_title = (char*)title;
+
+ if( strlen(name)>254)
+ return( NULL );
+
+ strcpy(tmpname, name);
+
+ if( use_title == NULL ){
+ use_title = (char*)"";
+ }
+
+ if (select_file(path, tmpname, (char*)"*", use_title, NULL)) {
+ snprintf(fullname, PATH_MAX, "%s%s", path, tmpname);
+ return((const char*)&fullname);
+ }
+
+ return( NULL );
+}
+
+
+void dbg_grect(const char * str, GRECT * r)
+{
+ printf("%s: x: %d, y: %d, w: %d, h: %d (x2: %d, y2: %d)\n", str,
+ r->g_x, r->g_y, r->g_w, r->g_h, r->g_x + r->g_w, r->g_y + r->g_h);
+}
+
+void dbg_pxy(const char * str, short * pxy )
+{
+ printf("%s: x: %d, y: %d, w: %d, h: %d\n", str,
+ pxy[0], pxy[1], pxy[2], pxy[3] );
+}
+
+void dbg_rect(const char * str, int * pxy)
+{
+ printf("%s: x0: %d, y0: %d, x1: %d, y1: %d (w: %d, h: %d)\n", str,
+ pxy[0], pxy[1], pxy[2], pxy[3],
+ pxy[2] - pxy[0],
+ pxy[3] - pxy[1] );
+}
+
diff --git a/frontends/atari/misc.h b/frontends/atari/misc.h
new file mode 100644
index 000000000..e581c23b2
--- /dev/null
+++ b/frontends/atari/misc.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.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 NS_ATARI_MISC_H
+#define NS_ATARI_MISC_H
+
+
+#define SBUF8_TO_LBUF8(sbuf,lbuf)\
+ lbuf[0] = (long)sbuf[0];\
+ lbuf[1] = (long)sbuf[1];\
+ lbuf[2] = (long)sbuf[2];\
+ lbuf[3] = (long)sbuf[3];\
+ lbuf[4] = (long)sbuf[4];\
+ lbuf[5] = (long)sbuf[5];\
+ lbuf[6] = (long)sbuf[6];\
+ lbuf[7] = (long)sbuf[7];
+
+#define RECT_TO_GRECT(r,g) \
+ (g)->g_x = (r->x0 < r->x1) ? r->x0 : r->x1 ; \
+ (g)->g_y = (r->y0 < r->y1) ? r->y0 : r->y1 ; \
+ (g)->g_w = (r->x0 < r->x1) ? r->x1 - r->x0 : r->x0 - r->x1 ; \
+ (g)->g_h = (r->y0 < r->y1) ? r->y1 - r->y0 : r->y0 - r->y1 ;
+
+
+
+/* Modes for find_gui_window: */
+#define BY_WINDOM_HANDLE 0x0
+#define BY_GEM_HANDLE 0x1
+
+/**
+ */
+typedef int (*scan_process_callback)(int pid, void *data);
+
+/**
+ */
+struct gui_window * find_guiwin_by_aes_handle(short handle);
+
+/**
+ */
+bool is_process_running(const char * name);
+
+/**
+ */
+void gem_set_cursor( MFORM_EX * cursor );
+
+/**
+ */
+void dbg_grect(const char * str, GRECT * r);
+
+/**
+ */
+void dbg_pxy(const char * str, short * pxy);
+
+/**
+ */
+void dbg_rect(const char * str, int * pxy);
+
+/**
+ */
+const char * file_select(const char * title, const char * name);
+
+/**
+ * Convert NKC to netsurf input key code and/or to ucs4 (depends on keycode).
+ *
+ * \param[in] nkc atari normalized key code
+ * \param[out] ucs4_out The ucs4 converted keycode
+ * \return The netsurf input keycode or 0 and ucs4_out updated with
+ * the NKC converted to UC4 encoding.
+ */
+long nkc_to_input_key(short nkc, long * ucs4_out);
+
+/**
+ * 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));
+
+/**
+ * Warn the user of an event.
+ *
+ * \param[in] warning A warning looked up in the message translation table
+ * \param[in] detail Additional text to be displayed or NULL.
+ * \return NSERROR_OK on success or error code if there was a
+ * faliure displaying the message to the user.
+ */
+nserror atari_warn_user(const char *warning, const char *detail);
+
+#endif
diff --git a/frontends/atari/options.h b/frontends/atari/options.h
new file mode 100644
index 000000000..4ae847d74
--- /dev/null
+++ b/frontends/atari/options.h
@@ -0,0 +1,48 @@
+/*
+ * 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/>.
+ */
+
+#ifndef NS_ATARI_OPTIONS_H_
+#define NS_ATARI_OPTIONS_H_
+
+/* setup longer default reflow time */
+#define DEFAULT_REFLOW_PERIOD 350 /* time in cs */
+
+#endif
+
+NSOPTION_STRING(atari_font_driver, "freetype")
+NSOPTION_INTEGER(atari_font_monochrom, 0)
+NSOPTION_INTEGER(atari_transparency, 1)
+NSOPTION_INTEGER(atari_dither, 1)
+NSOPTION_INTEGER(atari_gui_poll_timeout, 0)
+NSOPTION_STRING(atari_editor, NULL)
+NSOPTION_STRING(font_face_sans_serif, NULL)
+NSOPTION_STRING(font_face_sans_serif_bold, NULL)
+NSOPTION_STRING(font_face_sans_serif_italic, NULL)
+NSOPTION_STRING(font_face_sans_serif_italic_bold, NULL)
+NSOPTION_STRING(font_face_monospace, NULL)
+NSOPTION_STRING(font_face_monospace_bold, NULL)
+NSOPTION_STRING(font_face_serif, NULL)
+NSOPTION_STRING(font_face_serif_bold, NULL)
+NSOPTION_STRING(font_face_cursive, NULL)
+NSOPTION_STRING(font_face_fantasy, NULL)
+NSOPTION_STRING(downloads_path, "downloads")
+NSOPTION_STRING(url_file, "url.db")
+NSOPTION_STRING(hotlist_file, "hotlist")
+NSOPTION_STRING(tree_icons_path, "./res/icons")
+
+
diff --git a/frontends/atari/osspec.c b/frontends/atari/osspec.c
new file mode 100644
index 000000000..f64402e8d
--- /dev/null
+++ b/frontends/atari/osspec.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2010 <ole@monochrom.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 <sys/types.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <support.h>
+#include <mint/osbind.h>
+#include <mint/cookie.h>
+
+#include "utils/log.h"
+#include "atari/osspec.h"
+#include "atari/gemtk/gemtk.h"
+
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
+NS_ATARI_SYSINFO atari_sysinfo;
+
+void init_os_info(void)
+{
+ int16_t out[4];
+ long cookie_FSMC = 0;
+
+ atari_sysinfo.gemdos_version = Sversion();
+
+ if( tos_getcookie (C_FSMC, &cookie_FSMC ) == C_FOUND ) {
+ atari_sysinfo.gdos_FSMC = 1;
+ } else {
+ atari_sysinfo.gdos_FSMC = 0;
+ }
+ atari_sysinfo.large_sfont_pxh = 13;
+ atari_sysinfo.medium_sfont_pxh = 6;
+ atari_sysinfo.small_sfont_pxh = 4;
+ /* todo: detect if system font is monospaced */
+ atari_sysinfo.sfont_monospaced = true;
+ if( appl_xgetinfo(AES_LARGEFONT, &out[0], &out[1], &out[2], &out[3] ) > 0 ){
+ atari_sysinfo.large_sfont_pxh = out[0];
+ }
+ if( appl_xgetinfo(AES_SMALLFONT, &out[0], &out[1], &out[2], &out[3] ) > 0 ){
+ atari_sysinfo.small_sfont_pxh = out[0];
+ }
+ atari_sysinfo.aes_max_win_title_len = 79;
+ if (sys_type() & (SYS_MAGIC|SYS_NAES|SYS_XAAES)) {
+ if (sys_NAES()) {
+ atari_sysinfo.aes_max_win_title_len = 127;
+ }
+ if (sys_XAAES()) {
+ atari_sysinfo.aes_max_win_title_len = 200;
+ }
+ }
+}
+
+
+/* exported interface documented in atari/osspec.h */
+int tos_getcookie(long tag, long * value)
+{
+ COOKIE * cptr;
+
+ if( atari_sysinfo.gemdos_version > TOS4VER ){
+ return( Getcookie(tag, value) );
+ }
+
+ cptr = (COOKIE*)Setexc(0x0168, -1L);
+ if(cptr != NULL) {
+ do {
+ if( cptr->c == tag ){
+ if(cptr->v != 0 ){
+ if( value != NULL ){
+ *value = cptr->v;
+ }
+ return( C_FOUND );
+ }
+ }
+ } while( (cptr++)->c != 0L );
+ }
+ return( C_NOTFOUND );
+}
+
+/*
+
+ a fixed version of realpath() which returns valid
+ paths for TOS which have no U: drive
+
+*/
+
+char *gemdos_realpath(const char * path, char * rpath)
+{
+ char work[PATH_MAX+1];
+ char * r;
+
+ if (rpath == NULL) {
+ return (NULL);
+ }
+
+ // Check if the path is already absolute:
+ if(path[1] == ':'){
+ strcpy(rpath, path);
+ return(rpath);
+ }
+
+ LOG("realpath in: %s\n", path);
+ r = realpath(path, work);
+ if (r != NULL) {
+ unx2dos((const char *)r, rpath);
+ LOG("realpath out: %s\n", rpath);
+ return(rpath);
+ } else {
+ LOG("realpath out: NULL!\n");
+ }
+ return (NULL);
+}
diff --git a/frontends/atari/osspec.h b/frontends/atari/osspec.h
new file mode 100644
index 000000000..0c8d4cf66
--- /dev/null
+++ b/frontends/atari/osspec.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2011 Ole Loots <ole@monochrom.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 NS_ATARI_OSSPEC_H
+#define NS_ATARI_OSSPEC_H
+
+typedef struct {
+ long c;
+ long v;
+} COOKIE;
+
+typedef struct {
+ unsigned short gemdos_version;
+ unsigned short gdos_FSMC;
+ unsigned short systype;
+ unsigned short small_sfont_pxh;
+ unsigned short medium_sfont_pxh;
+ unsigned short large_sfont_pxh;
+ bool sfont_monospaced;
+ short aes_max_win_title_len;
+} NS_ATARI_SYSINFO;
+
+extern NS_ATARI_SYSINFO atari_sysinfo;
+
+void init_os_info(void);
+void fix_path(char * path);
+char * gemdos_realpath(const char * path, char * rpath);
+int tos_getcookie( long tag, long * value );
+
+#endif
diff --git a/frontends/atari/plot/eddi.h b/frontends/atari/plot/eddi.h
new file mode 100644
index 000000000..7d6b90d4b
--- /dev/null
+++ b/frontends/atari/plot/eddi.h
@@ -0,0 +1,54 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2009 Sam Lantinga
+
+ 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+
+#ifndef _atari_eddi_h
+#define _atari_eddi_h
+
+/*--- Defines ---*/
+
+/* EdDI versions */
+
+#define EDDI_10 (0x0100)
+#define EDDI_11 (0x0110)
+
+/* Screen format */
+
+enum {
+ VDI_FORMAT_UNKNOWN=-1,
+ VDI_FORMAT_INTER=0, /* Interleaved bitplanes */
+ VDI_FORMAT_VDI=1, /* VDI independent */
+ VDI_FORMAT_PACK=2 /* Packed pixels */
+};
+
+/* CLUT types */
+enum {
+ VDI_CLUT_NONE=0, /* Monochrome mode */
+ VDI_CLUT_HARDWARE, /* <256 colours mode */
+ VDI_CLUT_SOFTWARE /* True colour mode */
+};
+
+
+/*--- Functions ---*/
+
+unsigned long EdDI_version(void *function_pointer);
+
+#endif /* atari_eddi_s_h */
diff --git a/frontends/atari/plot/eddi.s b/frontends/atari/plot/eddi.s
new file mode 100644
index 000000000..f0ea18a1e
--- /dev/null
+++ b/frontends/atari/plot/eddi.s
@@ -0,0 +1,42 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2009 Sam Lantinga
+
+ 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+
+/*
+ *Read EdDI version
+ *
+ *Patrice Mandin
+ */
+
+.text
+
+.globl _EdDI_version
+
+/*--- Vector installer ---*/
+
+_EdDI_version:
+movel sp@(4),a0 /* Value of EdDI cookie */
+
+/* Call EdDI function #0 */
+clrl d0
+jsr (a0)
+
+rts
diff --git a/frontends/atari/plot/font_freetype.c b/frontends/atari/plot/font_freetype.c
new file mode 100644
index 000000000..a77aff855
--- /dev/null
+++ b/frontends/atari/plot/font_freetype.c
@@ -0,0 +1,714 @@
+/*
+ * Copyright 2005 James Bursa <bursa@users.sourceforge.net>
+ * 2008 Vincent Sanders <vince@simtec.co.uk>
+ * 2011 Ole Loots <ole@monochrom.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/>.
+ */
+
+#ifdef WITH_FREETYPE_FONT_DRIVER
+#include <assert.h>
+#include <ft2build.h>
+#include FT_CACHE_H
+
+#include "utils/log.h"
+#include "utils/nsoption.h"
+#include "desktop/mouse.h"
+#include "desktop/plot_style.h"
+
+#include "atari/gui.h"
+#include "atari/bitmap.h"
+#include "atari/plot/plot.h"
+#include "atari/plot/fontplot.h"
+#include "atari/plot/font_freetype.h"
+#include "atari/findfile.h"
+#include "atari/gemtk/gemtk.h"
+
+/* -------------------------------------------------------------------------- */
+/* Font Loading & Mapping scheme */
+/* -------------------------------------------------------------------------- */
+/*
+
+Truetype fonts are loaded in the following priority order:
+
+1. Option values.
+2. default resouce names (8.3 compatible).
+3. default font package installation path.
+
+
+Resource font names & their meanings:
+--------------------------------------------
+s.ttf => Serif
+sb.ttf => Serif Bold
+ss.ttf => Sans Serif *Default Font
+ssb.ttf => Sans Serif Bold
+ssi.ttf => Sans Serif Italic
+ssib.ttf => Sans Serif Italic Bold
+mono.ttf => Monospaced
+monob.ttf => Monospaced Bold
+cursive.ttf => Cursive
+fantasy.ttf => Fantasy
+*/
+
+#define FONT_RESOURCE_PATH "fonts/"
+#define DEJAVU_PATH "/usr/share/fonts/truetype/ttf-dejavu/"
+#define BITSTREAM_PATH "/usr/share/fonts/truetype/ttf-bitstream-vera/"
+
+#if !defined(USE_BITSTREAM_FONT_PACKAGE) && !defined(USE_DEJAVU_FONT_PACKAGE)
+# define USE_BITSTREAM_FONT_PACKAGE
+#endif
+
+#if defined(USE_DEJAVU_FONT_PACKAGE)
+# define FONT_PKG_PATH DEJAVU_PATH
+# define FONT_FILE_SANS "DejaVuSans.ttf"
+# define FONT_FILE_SANS_BOLD "DejaVuSans-Bold.ttf"
+# define FONT_FILE_SANS_OBLIQUE "DejaVuSans-Oblique.ttf"
+# define FONT_FILE_SANS_BOLD_OBLIQUE "DejaVuSans-BoldOblique.ttf"
+# define FONT_FILE_SERIF "DejaVuSerif.ttf"
+# define FONT_FILE_SERIF_BOLD "DejaVuSerif-Bold.ttf"
+# define FONT_FILE_MONO "DejaVuSansMono.ttf"
+# define FONT_FILE_MONO_BOLD "DejaVuSerif-Bold.ttf"
+# define FONT_FILE_OBLIQUE "DejaVuSansMono-Oblique.ttf"
+# define FONT_FILE_FANTASY "DejaVuSerifCondensed-Bold.ttf"
+#elif defined(USE_BITSTREAM_FONT_PACKAGE)
+# define FONT_PKG_PATH BITSTREAM_PATH
+# define FONT_FILE_SANS "Vera.ttf"
+# define FONT_FILE_SANS_BOLD "VeraBd.ttf"
+# define FONT_FILE_SANS_OBLIQUE "VeraIt.ttf"
+# define FONT_FILE_SANS_BOLD_OBLIQUE "VeraBI.ttf"
+# define FONT_FILE_SERIF "VeraSe.ttf"
+# define FONT_FILE_SERIF_BOLD "VeraSeBd.ttf"
+# define FONT_FILE_MONO "VeraMono.ttf"
+# define FONT_FILE_MONO_BOLD "VeraMoBd.ttf"
+# define FONT_FILE_OBLIQUE "VeraMoIt.ttf"
+# define FONT_FILE_FANTASY "VeraMoBI.ttf"
+
+#endif
+
+#define CACHE_SIZE 2048
+#define CACHE_MIN_SIZE (100 * 1024)
+#define BOLD_WEIGHT 700
+
+extern unsigned long atari_plot_flags;
+extern int atari_plot_vdi_handle;
+
+static FT_Library library;
+static FTC_Manager ft_cmanager;
+static FTC_CMapCache ft_cmap_cache ;
+static FTC_ImageCache ft_image_cache;
+
+int ft_load_type;
+
+/* cache manager faceID data to create freetype faceid on demand */
+typedef struct ftc_faceid_s {
+ char *fontfile; /* path to font */
+ int index; /* index of font */
+ int cidx; /* character map index for unicode */
+} ftc_faceid_t;
+
+static int dtor( FONT_PLOTTER self );
+static int str_width( FONT_PLOTTER self,const plot_font_style_t *fstyle,
+ const char * str, size_t length, int * width );
+static int str_split( FONT_PLOTTER self, const plot_font_style_t *fstyle,
+ const char *string, size_t length,int x,
+ size_t *char_offset, int *actual_x );
+static int pixel_pos( FONT_PLOTTER self, const plot_font_style_t *fstyle,
+ const char *string, size_t length,int x,
+ size_t *char_offset, int *actual_x );
+static int text( FONT_PLOTTER self, int x, int y, const char *text,
+ size_t length, const plot_font_style_t *fstyle );
+
+static void draw_glyph8(FONT_PLOTTER self, GRECT *clip, GRECT * loc,
+ uint8_t * pixdata, int pitch, uint32_t colour);
+static void draw_glyph1(FONT_PLOTTER self, GRECT * clip, GRECT * loc,
+ uint8_t * pixdata, int pitch, uint32_t colour);
+
+static ftc_faceid_t *font_faces[FONT_FACE_COUNT];
+static MFDB tmp;
+static int tmp_mfdb_size;
+static bool init = false;
+static struct bitmap * fontbmp;
+static size_t fontbmp_stride;
+static int fontbmp_allocated_height;
+static int fontbmp_allocated_width;
+
+
+
+/* map cache manager handle to face id */
+static FT_Error ft_face_requester(FTC_FaceID face_id, FT_Library library, FT_Pointer request_data, FT_Face *face )
+{
+ FT_Error error;
+ ftc_faceid_t *ft_face = (ftc_faceid_t *)face_id;
+ int cidx;
+
+ error = FT_New_Face(library, ft_face->fontfile, ft_face->index, face);
+ if (error) {
+ LOG("Could not find font (code %d)\n", error);
+ } else {
+ error = FT_Select_Charmap(*face, FT_ENCODING_UNICODE);
+ if (error) {
+ LOG("Could not select charmap (code %d)\n", error);
+ } else {
+ for (cidx = 0; cidx < (*face)->num_charmaps; cidx++) {
+ if ((*face)->charmap == (*face)->charmaps[cidx]) {
+ ft_face->cidx = cidx;
+ break;
+ }
+ }
+ }
+ }
+ LOG("Loaded face from %s\n", ft_face->fontfile);
+ return error;
+}
+
+/* create new framebuffer face and cause it to be loaded to check its ok */
+static ftc_faceid_t *
+ft_new_face(const char *option, const char *resname, const char *fontfile)
+{
+ ftc_faceid_t *newf;
+ FT_Error error;
+ FT_Face aface;
+ char buf[PATH_MAX];
+
+ newf = calloc(1, sizeof(ftc_faceid_t));
+ if (option != NULL) {
+ newf->fontfile = strdup(option);
+ } else {
+ atari_find_resource(buf, resname, fontfile);
+ newf->fontfile = strdup(buf);
+ }
+ error = FTC_Manager_LookupFace(ft_cmanager, (FTC_FaceID)newf, &aface);
+ if (error) {
+ LOG("Could not find font face %s (code %d)\n", fontfile, error);
+ free(newf);
+ newf = font_faces[FONT_FACE_DEFAULT]; /* use default */
+ }
+ return newf;
+}
+
+static void ft_fill_scalar(const plot_font_style_t *fstyle, FTC_Scaler srec)
+{
+ int selected_face = FONT_FACE_DEFAULT;
+
+ switch (fstyle->family) {
+
+ case PLOT_FONT_FAMILY_SERIF:
+ if (fstyle->weight >= BOLD_WEIGHT) {
+ selected_face = FONT_FACE_SERIF_BOLD;
+ } else {
+ selected_face = FONT_FACE_SERIF;
+ }
+ break;
+
+ case PLOT_FONT_FAMILY_MONOSPACE:
+ if (fstyle->weight >= BOLD_WEIGHT) {
+ selected_face = FONT_FACE_MONOSPACE_BOLD;
+ } else {
+ selected_face = FONT_FACE_MONOSPACE;
+ }
+ break;
+
+ case PLOT_FONT_FAMILY_CURSIVE:
+ selected_face = FONT_FACE_CURSIVE;
+ break;
+
+ case PLOT_FONT_FAMILY_FANTASY:
+ selected_face = FONT_FACE_FANTASY;
+ break;
+
+ case PLOT_FONT_FAMILY_SANS_SERIF:
+ default:
+ if ((fstyle->flags & FONTF_ITALIC) ||
+ (fstyle->flags & FONTF_OBLIQUE)) {
+ if (fstyle->weight >= BOLD_WEIGHT) {
+ selected_face = FONT_FACE_SANS_SERIF_ITALIC_BOLD;
+ } else {
+ selected_face = FONT_FACE_SANS_SERIF_ITALIC;
+ }
+ } else {
+ if (fstyle->weight >= BOLD_WEIGHT) {
+ selected_face = FONT_FACE_SANS_SERIF_BOLD;
+ } else {
+ selected_face = FONT_FACE_SANS_SERIF;
+ }
+ }
+ }
+
+ srec->face_id = (FTC_FaceID)font_faces[selected_face];
+
+ srec->width = srec->height = (fstyle->size * 64) / FONT_SIZE_SCALE;
+ srec->pixel = 0;
+
+ /* calculate x/y resolution, when browser_get_dpi() isn't available */
+ /* 72 is an good value. */
+ /* TODO: because browser_get_dpi() is to large, calculate that value */
+ /* by VDI values. */
+ srec->x_res = srec->y_res = 72; // browser_get_dpi();
+}
+
+static FT_Glyph ft_getglyph(const plot_font_style_t *fstyle, uint32_t ucs4)
+{
+ FT_UInt glyph_index;
+ FTC_ScalerRec srec;
+ FT_Glyph glyph;
+ FT_Error error;
+ ftc_faceid_t *ft_face;
+
+ ft_fill_scalar(fstyle, &srec);
+ ft_face = (ftc_faceid_t *)srec.face_id;
+ glyph_index = FTC_CMapCache_Lookup(ft_cmap_cache, srec.face_id, ft_face->cidx, ucs4);
+ error = FTC_ImageCache_LookupScaler(ft_image_cache,
+ &srec,
+ FT_LOAD_RENDER |
+ FT_LOAD_FORCE_AUTOHINT |
+ ft_load_type,
+ glyph_index,
+ &glyph,
+ NULL);
+ return glyph;
+}
+
+
+/* initialise font handling */
+static bool ft_font_init(void)
+{
+ FT_Error error;
+ FT_ULong max_cache_size;
+ FT_UInt max_faces = 6;
+ int i;
+
+ /* freetype library initialise */
+ error = FT_Init_FreeType( &library );
+ if (error) {
+ LOG("Freetype could not initialised (code %d)\n", error);
+ return false;
+ }
+
+ /* set the Glyph cache size up */
+ max_cache_size = CACHE_SIZE * 1024;
+ if (max_cache_size < CACHE_MIN_SIZE) {
+ max_cache_size = CACHE_MIN_SIZE;
+ }
+
+ /* cache manager initialise */
+ error = FTC_Manager_New(library,
+ max_faces,
+ 0,
+ max_cache_size,
+ ft_face_requester,
+ NULL,
+ &ft_cmanager);
+ if (error) {
+ LOG("Freetype could not initialise cache manager (code %d)\n", error);
+ FT_Done_FreeType(library);
+ return false;
+ }
+
+ error = FTC_CMapCache_New(ft_cmanager, &ft_cmap_cache);
+ error = FTC_ImageCache_New(ft_cmanager, &ft_image_cache);
+
+ /* Optain font faces */
+
+
+ /* Default font, Sans Serif */
+ font_faces[FONT_FACE_SANS_SERIF] = NULL;
+ font_faces[FONT_FACE_SANS_SERIF] = ft_new_face(
+ nsoption_charp(font_face_sans_serif),
+ FONT_RESOURCE_PATH "ss.ttf",
+ FONT_PKG_PATH FONT_FILE_SANS
+ );
+ if (font_faces[FONT_FACE_SANS_SERIF] == NULL) {
+ LOG("Could not find default font (code %d)\n", error);
+ FTC_Manager_Done(ft_cmanager);
+ FT_Done_FreeType(library);
+ return false;
+ }
+
+ /* Sans Serif Bold*/
+ font_faces[FONT_FACE_SANS_SERIF_BOLD] =
+ ft_new_face(nsoption_charp(font_face_sans_serif_bold),
+ FONT_RESOURCE_PATH "ssb.ttf",
+ FONT_PKG_PATH FONT_FILE_SANS_BOLD);
+
+ /* Sans Serif Italic */
+ font_faces[FONT_FACE_SANS_SERIF_ITALIC] =
+ ft_new_face(nsoption_charp(font_face_sans_serif_italic),
+ FONT_RESOURCE_PATH "ssi.ttf",
+ FONT_PKG_PATH FONT_FILE_SANS_OBLIQUE);
+
+ /* Sans Serif Italic Bold */
+ font_faces[FONT_FACE_SANS_SERIF_ITALIC_BOLD] =
+ ft_new_face(nsoption_charp(font_face_sans_serif_italic_bold),
+ FONT_RESOURCE_PATH "ssib.ttf",
+ FONT_PKG_PATH FONT_FILE_SANS_BOLD_OBLIQUE);
+
+ /* Monospaced */
+ font_faces[FONT_FACE_MONOSPACE] =
+ ft_new_face(nsoption_charp(font_face_monospace),
+ FONT_RESOURCE_PATH "mono.ttf",
+ FONT_PKG_PATH FONT_FILE_MONO);
+
+ /* Mospaced Bold */
+ font_faces[FONT_FACE_MONOSPACE_BOLD] =
+ ft_new_face(nsoption_charp(font_face_monospace_bold),
+ FONT_RESOURCE_PATH "monob.ttf",
+ FONT_PKG_PATH FONT_FILE_MONO_BOLD);
+
+ /* Serif */
+ font_faces[FONT_FACE_SERIF] =
+ ft_new_face(nsoption_charp(font_face_serif),
+ FONT_RESOURCE_PATH "s.ttf",
+ FONT_PKG_PATH FONT_FILE_SERIF);
+
+ /* Serif Bold */
+ font_faces[FONT_FACE_SERIF_BOLD] =
+ ft_new_face(nsoption_charp(font_face_serif_bold),
+ FONT_RESOURCE_PATH "sb.ttf",
+ FONT_PKG_PATH FONT_FILE_SERIF_BOLD);
+
+ /* Cursive */
+ font_faces[FONT_FACE_CURSIVE] =
+ ft_new_face(nsoption_charp(font_face_cursive),
+ FONT_RESOURCE_PATH "cursive.ttf",
+ FONT_PKG_PATH FONT_FILE_OBLIQUE);
+
+ /* Fantasy */
+ font_faces[FONT_FACE_FANTASY] =
+ ft_new_face(nsoption_charp(font_face_fantasy),
+ FONT_RESOURCE_PATH "fantasy.ttf",
+ FONT_PKG_PATH FONT_FILE_FANTASY);
+
+ for (i=1; i<FONT_FACE_COUNT; i++) {
+ if (font_faces[i] == NULL){
+ font_faces[i] = font_faces[FONT_FACE_SANS_SERIF];
+ }
+ }
+
+ return true;
+}
+
+
+static bool ft_font_finalise(void)
+{
+ FTC_Manager_Done(ft_cmanager );
+ FT_Done_FreeType(library);
+ return true;
+}
+
+static int str_width( FONT_PLOTTER self,const plot_font_style_t *fstyle,
+ const char *string, size_t length,
+ int *width)
+{
+ uint32_t ucs4;
+ size_t nxtchr = 0;
+ FT_Glyph glyph;
+
+ *width = 0;
+ while (nxtchr < length) {
+ ucs4 = utf8_to_ucs4(string + nxtchr, length - nxtchr);
+ nxtchr = utf8_next(string, length, nxtchr);
+
+ glyph = ft_getglyph(fstyle, ucs4);
+ if (glyph == NULL)
+ continue;
+ *width += glyph->advance.x >> 16;
+ }
+ return(1);
+}
+
+
+static int str_split( FONT_PLOTTER self, const plot_font_style_t *fstyle,
+ const char *string, size_t length,
+ int x, size_t *char_offset, int *actual_x)
+{
+ uint32_t ucs4;
+ size_t nxtchr = 0;
+ int last_space_x = 0;
+ int last_space_idx = 0;
+ FT_Glyph glyph;
+
+ *actual_x = 0;
+ while (nxtchr < length) {
+ ucs4 = utf8_to_ucs4(string + nxtchr, length - nxtchr);
+ glyph = ft_getglyph(fstyle, ucs4);
+ if (glyph == NULL)
+ continue;
+ if (ucs4 == 0x20) {
+ last_space_x = *actual_x;
+ last_space_idx = nxtchr;
+ }
+ *actual_x += glyph->advance.x >> 16;
+ if (*actual_x > x && last_space_idx != 0) {
+ /* string has exceeded available width and we've
+ * found a space; return previous space */
+ *actual_x = last_space_x;
+ *char_offset = last_space_idx;
+ return true;
+ }
+ nxtchr = utf8_next(string, length, nxtchr);
+ }
+ *char_offset = nxtchr;
+ return (1);
+}
+
+
+static int pixel_pos( FONT_PLOTTER self, const plot_font_style_t *fstyle,
+ const char *string, size_t length,
+ int x, size_t *char_offset, int *actual_x)
+{
+ uint32_t ucs4;
+ size_t nxtchr = 0;
+ FT_Glyph glyph;
+ int prev_x = 0;
+
+ *actual_x = 0;
+ while (nxtchr < length) {
+ ucs4 = utf8_to_ucs4(string + nxtchr, length - nxtchr);
+ glyph = ft_getglyph(fstyle, ucs4);
+ if (glyph == NULL)
+ continue;
+ *actual_x += glyph->advance.x >> 16;
+ if (*actual_x > x)
+ break;
+
+ prev_x = *actual_x;
+ nxtchr = utf8_next(string, length, nxtchr);
+ }
+
+ /* choose nearest of previous and last x */
+ if (abs(*actual_x - x) > abs(prev_x - x))
+ *actual_x = prev_x;
+ *char_offset = nxtchr;
+ return ( 1 );
+}
+
+
+static void draw_glyph8(FONT_PLOTTER self, GRECT * clip, GRECT * loc, uint8_t * pixdata, int pitch, uint32_t colour)
+{
+ uint32_t * linebuf;
+ uint32_t fontpix;
+ int xloop,yloop,xoff,yoff;
+ int x,y,w,h;
+
+ x = loc->g_x;
+ y = loc->g_y;
+ w = loc->g_w;
+ h = loc->g_h;
+
+ if( !rc_intersect( clip, loc ) ){
+ return;
+ }
+
+ xoff = loc->g_x - x;
+ yoff = loc->g_y - y;
+
+ assert( loc->g_h <= h );
+ assert( loc->g_w <= w );
+
+ h = loc->g_h;
+ w = loc->g_w;
+
+ assert( h <= fontbmp_allocated_height );
+ assert( w <= fontbmp_allocated_width );
+
+ fontbmp->height = h;
+ fontbmp->width = w;
+ for( yloop = 0; yloop < MIN(fontbmp_allocated_height, h); yloop++) {
+ linebuf = (uint32_t *)(fontbmp->pixdata + (fontbmp_stride * yloop));
+ for(xloop = 0; xloop < MIN(fontbmp_allocated_width, w); xloop++){
+ fontpix = (uint32_t)(pixdata[(( yoff + yloop ) * pitch) + xloop + xoff]);
+ linebuf[xloop] = (uint32_t)(colour | fontpix);
+ }
+ }
+ plot_blit_bitmap(fontbmp, loc->g_x, loc->g_y, 0, BITMAPF_MONOGLYPH);
+}
+
+static void draw_glyph1(FONT_PLOTTER self, GRECT * clip, GRECT * loc, uint8_t * pixdata, int pitch, uint32_t colour)
+{
+ int xloop,yloop,xoff,yoff;
+ int x,y,w,h;
+ uint8_t bitm;
+ const uint8_t *fntd;
+
+ x = loc->g_x;
+ y = loc->g_y;
+ w = loc->g_w;
+ h = loc->g_h;
+
+ if( !rc_intersect( clip, loc ) ){
+ return;
+ }
+
+ xoff = loc->g_x - x;
+ yoff = loc->g_y - y;
+
+ if (h > loc->g_h)
+ h = loc->g_h;
+
+ if (w > loc->g_w)
+ w = loc->g_w;
+
+ int stride = MFDB_STRIDE( w );
+ if( tmp.fd_addr == NULL || tmp_mfdb_size < MFDB_SIZE( 1, stride, h) ){
+ tmp_mfdb_size = init_mfdb( 1, w, h, MFDB_FLAG_STAND | MFDB_FLAG_ZEROMEM, &tmp );
+ } else {
+ void * buf = tmp.fd_addr;
+ int size = init_mfdb( 1, w, h, MFDB_FLAG_STAND | MFDB_FLAG_NOALLOC, &tmp );
+ tmp.fd_addr = buf;
+ memset( tmp.fd_addr, 0, size );
+ }
+ short * buf;
+ for( yloop = 0; yloop < h; yloop++) {
+ fntd = pixdata + (pitch * (yloop+yoff))+(xoff>>3);
+ buf = tmp.fd_addr;
+ buf += (tmp.fd_wdwidth*yloop);
+ for ( xloop = 0, bitm = (1<<(7-(xoff%8))); xloop < w; xloop++, bitm=(bitm>>1) ) {
+ if( (*fntd & bitm) != 0 ){
+ short whichbit = (1<<(15-(xloop%16)));
+ buf[xloop>>4] = ((buf[xloop>>4])|(whichbit));
+ }
+ if( bitm == 1 ) {
+ fntd++;
+ bitm = 128;
+ }
+ }
+ }
+#ifdef WITH_8BPP_SUPPORT
+ if( app.nplanes > 8 ){
+#endif
+ plot_blit_mfdb(loc, &tmp, OFFSET_CUSTOM_COLOR, PLOT_FLAG_TRANS );
+#ifdef WITH_8BPP_SUPPORT
+ } else {
+ plot_blit_mfdb(loc, &tmp, colour, PLOT_FLAG_TRANS );
+ }
+#endif
+
+}
+
+static int text( FONT_PLOTTER self, int x, int y, const char *text, size_t length,
+ const plot_font_style_t *fstyle )
+{
+ uint32_t ucs4;
+ size_t nxtchr = 0;
+ FT_Glyph glyph;
+ FT_BitmapGlyph bglyph;
+ GRECT loc, clip;
+ uint32_t c = fstyle->foreground ;
+ struct rect clipping;
+ /* in -> BGR */
+ /* out -> ARGB */
+ if( !(self->flags & FONTPLOT_FLAG_MONOGLYPH) ){
+ c = ABGR_TO_RGB(c);
+ } else {
+#ifdef WITH_8BPP_SUPPORT
+ if( app.nplanes > 8 ){
+#endif
+ RGB1000 out; /* struct with RGB shorts */
+ rgb_to_vdi1000( (unsigned char*)&c, &out);
+ vs_color(atari_plot_vdi_handle, OFFSET_CUSTOM_COLOR,
+ (short*)&out);
+#ifdef WITH_8BPP_SUPPORT
+ } else {
+ c = RGB_TO_VDI(c);
+ }
+#endif
+ }
+
+ plot_get_clip(&clipping);
+ clip.g_x = clipping.x0;
+ clip.g_y = clipping.y0;
+ clip.g_w = (clipping.x1 - clipping.x0)+1;
+ clip.g_h = (clipping.y1 - clipping.y0)+1;
+
+ fontbmp = atari_bitmap_realloc( clip.g_w, clip.g_h,
+ 4, clip.g_w << 2,
+ BITMAP_GROW, fontbmp );
+ fontbmp_stride = atari_bitmap_get_rowstride(fontbmp);
+ fontbmp_allocated_height = clip.g_h;
+ fontbmp_allocated_width = clip.g_w;
+
+ while (nxtchr < length) {
+ ucs4 = utf8_to_ucs4(text + nxtchr, length - nxtchr);
+ nxtchr = utf8_next(text, length, nxtchr);
+
+ glyph = ft_getglyph(fstyle, ucs4);
+ if (glyph == NULL){
+ continue;
+ }
+
+ if (glyph->format == FT_GLYPH_FORMAT_BITMAP) {
+ bglyph = (FT_BitmapGlyph)glyph;
+ loc.g_x = x + bglyph->left;
+ loc.g_y = y - bglyph->top;
+ loc.g_w = bglyph->bitmap.width;
+ loc.g_h = bglyph->bitmap.rows;
+
+ if( loc.g_w > 0) {
+ self->draw_glyph( self,
+ &clip, &loc,
+ bglyph->bitmap.buffer,
+ bglyph->bitmap.pitch,
+ c
+ );
+ }
+ }
+ x += glyph->advance.x >> 16;
+ }
+ return( 0 );
+}
+
+
+int ctor_font_plotter_freetype( FONT_PLOTTER self )
+{
+ self->dtor = dtor;
+ self->str_width = str_width;
+ self->str_split = str_split;
+ self->pixel_pos = pixel_pos;
+ self->text = text;
+
+ /* set the default render mode */
+ if( (self->flags & FONTPLOT_FLAG_MONOGLYPH) != 0 ){
+ ft_load_type = FT_LOAD_MONOCHROME;
+ self->draw_glyph = draw_glyph1;
+ }
+ else{
+ ft_load_type = 0;
+ self->draw_glyph = draw_glyph8;
+ }
+
+ LOG("%s: %s\n", (char *)__FILE__, __FUNCTION__);
+ if( !init ) {
+ ft_font_init();
+ fontbmp = atari_bitmap_create(48, 48, 0);
+ fontbmp->opaque = false;
+ init = true;
+ }
+
+ return( 1 );
+}
+
+static int dtor( FONT_PLOTTER self )
+{
+ ft_font_finalise();
+ if( fontbmp != NULL ) {
+ atari_bitmap_destroy( fontbmp );
+ fontbmp = NULL;
+ }
+ if( tmp.fd_addr != NULL ){
+ free( tmp.fd_addr );
+ }
+ return( 1 );
+}
+
+#endif
diff --git a/frontends/atari/plot/font_freetype.h b/frontends/atari/plot/font_freetype.h
new file mode 100644
index 000000000..58a5372a4
--- /dev/null
+++ b/frontends/atari/plot/font_freetype.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2011 Ole Loots <ole@monochrom.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 FONT_PLOTTER_FREETYPE
+#define FONT_PLOTTER_FREETYPE
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_GLYPH_H
+#include "utils/utf8.h"
+
+/* defines for accesing the faces */
+#define FONT_FACE_DEFAULT 0
+
+#define FONT_FACE_SANS_SERIF 0
+#define FONT_FACE_SANS_SERIF_BOLD 1
+#define FONT_FACE_SANS_SERIF_ITALIC 2
+#define FONT_FACE_SANS_SERIF_ITALIC_BOLD 3
+#define FONT_FACE_MONOSPACE 4
+#define FONT_FACE_MONOSPACE_BOLD 5
+#define FONT_FACE_SERIF 6
+#define FONT_FACE_SERIF_BOLD 7
+#define FONT_FACE_CURSIVE 8
+#define FONT_FACE_FANTASY 9
+
+#define FONT_FACE_COUNT 10
+
+struct font_desc {
+ const char *name;
+ int width, height;
+ const char *encoding;
+};
+
+/* extern int ft_load_type; */
+
+int ctor_font_plotter_freetype( FONT_PLOTTER self );
+
+#endif
diff --git a/frontends/atari/plot/font_internal.c b/frontends/atari/plot/font_internal.c
new file mode 100644
index 000000000..89a56d0e5
--- /dev/null
+++ b/frontends/atari/plot/font_internal.c
@@ -0,0 +1,2386 @@
+/*
+ * Copyright 2008 Vincent Sanders <vince@simtec.co.uk>
+ * Copyright 2011 Ole Loots <ole@monochrom.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/>.
+ */
+
+#ifdef WITH_INTERNAL_FONT_DRIVER
+
+#include <assert.h>
+#include <unistd.h>
+
+#include "utils/utf8.h"
+#include "utils/log.h"
+#include "desktop/mouse.h"
+#include "desktop/plot_style.h"
+
+#include "atari/gui.h"
+#include "atari/bitmap.h"
+#include "atari/plot/plot.h"
+#include "atari/plot/fontplot.h"
+#include "atari/plot/font_internal.h"
+
+
+extern unsigned long atari_plot_flags;
+extern int atari_plot_vdi_handle;
+
+static int dtor( FONT_PLOTTER self );
+static int str_width( FONT_PLOTTER self,const plot_font_style_t *fstyle, const char * str, size_t length, int * width );
+static int str_split( FONT_PLOTTER self, const plot_font_style_t *fstyle,const char *string,
+ size_t length,int x, size_t *char_offset, int *actual_x );
+static int pixel_pos( FONT_PLOTTER self, const plot_font_style_t *fstyle,const char *string,
+ size_t length,int x, size_t *char_offset, int *actual_x );
+static int text( FONT_PLOTTER self, int x, int y, const char *text, size_t length, const plot_font_style_t *fstyle );
+
+static bool init = false;
+static int vdih;
+static struct bitmap * fontbmp;
+extern struct s_vdi_sysinfo vdi_sysinfo;
+
+const struct fb_font_desc font_regular;
+const struct fb_font_desc font_italic;
+const struct fb_font_desc font_bold;
+const struct fb_font_desc font_italic_bold;
+
+static MFDB tmp;
+static int tmp_mfdb_size;
+
+#define FONTDATAMAX 4096
+
+static const struct fb_font_desc*
+fb_get_font(const plot_font_style_t *fstyle)
+{
+ if (fstyle->weight >= 700) {
+ if ((fstyle->flags & FONTF_ITALIC) ||
+ (fstyle->flags & FONTF_OBLIQUE)) {
+ return &font_italic_bold;
+ } else {
+ return &font_bold;
+ }
+ } else {
+ if ((fstyle->flags & FONTF_ITALIC) ||
+ (fstyle->flags & FONTF_OBLIQUE)) {
+ return &font_italic;
+ } else {
+ return &font_regular;
+ }
+ }
+}
+
+static nserror utf8_to_font_encoding(const struct fb_font_desc* font,
+ const char *string,
+ size_t len,
+ char **result)
+{
+ return utf8_to_enc(string, font->encoding, len, result);
+
+}
+
+int ctor_font_plotter_internal( FONT_PLOTTER self )
+{
+ self->dtor = dtor;
+ self->str_width = str_width;
+ self->str_split = str_split;
+ self->pixel_pos = pixel_pos;
+ self->text = text;
+ LOG("%s: %s\n", (char *)__FILE__, __FUNCTION__);
+ if( !init ) {
+ vdih = self->vdi_handle;
+ fontbmp = atari_bitmap_create(48, 48, 0);
+ fontbmp->opaque = false;
+ }
+ init = true;
+ return( 1 );
+}
+
+static int dtor( FONT_PLOTTER self )
+{
+ if( tmp.fd_addr != NULL ){
+ free( tmp.fd_addr );
+ }
+ return( 1 );
+}
+
+static int str_width( FONT_PLOTTER self,const plot_font_style_t *fstyle, const char * str,
+ size_t length, int * width )
+{
+ const struct fb_font_desc* fb_font = fb_get_font(fstyle);
+ *width = fb_font->width * utf8_bounded_length(str, length);
+ return( 1 );
+}
+
+static int str_split( FONT_PLOTTER self, const plot_font_style_t * fstyle, const char *string,
+ size_t length,int x, size_t *char_offset, int *actual_x )
+{
+ const struct fb_font_desc* fb_font = fb_get_font(fstyle);
+ int c_off = *char_offset = x / fb_font->width;
+ if (*char_offset > length) {
+ *char_offset = length;
+ } else {
+ while (*char_offset > 0) {
+ if (string[*char_offset] == ' ')
+ break;
+ (*char_offset)--;
+ }
+ if (*char_offset == 0) {
+ *char_offset = c_off;
+ while (*char_offset < length &&
+ string[*char_offset] != ' ') {
+ (*char_offset)++;
+ }
+ }
+ }
+ *actual_x = *char_offset * fb_font->width;
+ return( 1 );
+}
+
+static int pixel_pos( FONT_PLOTTER self, const plot_font_style_t * fstyle,const char *string,
+ size_t length,int x, size_t *char_offset, int *actual_x )
+{
+ const struct fb_font_desc* fb_font = fb_get_font(fstyle);
+ *char_offset = x / fb_font->width;
+ if (*char_offset > length)
+ *char_offset = length;
+ *actual_x = *char_offset * fb_font->width;
+ return( 1 );
+}
+
+static void draw_glyph1(FONT_PLOTTER self, GRECT *inloc, uint8_t *chrp, int pitch, uint32_t colour )
+{
+ size_t bmpstride;
+ GRECT clip;
+ uint32_t * fontdata;
+ int xloop,yloop;
+ int stride = pitch / 8;
+ uint32_t * linebuf;
+ GRECT loc = *inloc;
+
+ fontbmp = atari_bitmap_realloc( loc.g_w, loc.g_h, fontbmp->bpp, loc.g_w * fontbmp->bpp, BITMAP_GROW, fontbmp );
+ bmpstride = atari_bitmap_get_rowstride(fontbmp);
+ for( yloop = 0; yloop < loc.g_h; yloop++) {
+ uint32_t pixmask = 1 ;
+ linebuf = (uint32_t *)(fontbmp->pixdata + (bmpstride * yloop));
+ fontdata = (uint32_t*)(chrp + (stride*yloop));
+ for(xloop = loc.g_w-1; xloop>=0; xloop--){
+ linebuf[xloop] = ((pixmask & *fontdata) == 0) ? 0 : colour;
+ pixmask = (pixmask << 1);
+ }
+ }
+ plot_blit_bitmap(fontbmp, loc.g_x, loc.g_y, 0, BITMAPF_MONOGLYPH );
+}
+
+static int text( FONT_PLOTTER self, int x, int y, const char *text, size_t length,
+ const plot_font_style_t *fstyle )
+{
+ const struct fb_font_desc* fb_font = fb_get_font(fstyle);
+ const uint32_t *chrp;
+ char *buffer = NULL;
+ int chr;
+ int blen;
+ GRECT loc;
+ uint32_t c;
+
+ utf8_to_font_encoding(fb_font, text, length, &buffer);
+ if (buffer == NULL)
+ return 1;
+
+ /* y is given to the fonts baseline we need it to the fonts top */
+ y-=((fb_font->height * 75)/100);
+
+ /* needed? */
+ y+=1; /* the coord is the bottom-left of the pixels offset by 1 to make
+ * it work since fb coords are the top-left of pixels
+ */
+ blen = strlen(buffer);
+ if ( blen < 1 ) {
+ return( 1 );
+ }
+
+ if(atari_plot_flags & PLOT_FLAG_OFFSCREEN ){
+ /* when the plotter is an offscreen plotter the call to
+ bitmap() isn't that expensive. Draw an 8 bit bitmap into the
+ offscreen buffer.
+ */
+ c = fstyle->foreground;
+ /* in -> BGR */
+ /* out -> ARGB */
+ c = (ABGR_TO_RGB(c) | 0xFF);
+ loc.g_y = y;
+ loc.g_x = x;
+ loc.g_w = fb_font->width;
+ loc.g_h = fb_font->height;
+ for (chr = 0; chr < blen; chr++) {
+ loc.g_x = x;
+ chrp = fb_font->data + ((unsigned char)buffer[chr] * fb_font->height);
+ draw_glyph1(self, &loc, (uint8_t *)chrp, 32, c);
+ x+=fb_font->width;
+ }
+ } else {
+ /* render the whole string into an monochrom mfdb */
+ /* and plot that to reduce overhead */
+ loc.g_x = x;
+ loc.g_y = y;
+ loc.g_w = blen * fb_font->width;
+ assert( loc.g_w > 0 );
+ loc.g_h = fb_font->height;
+ int stride = MFDB_STRIDE( loc.g_w );
+ if( tmp.fd_addr == NULL || tmp_mfdb_size < MFDB_SIZE( 1, stride, loc.g_h) ){
+ tmp_mfdb_size = init_mfdb( 1, loc.g_w, loc.g_h+1, MFDB_FLAG_STAND | MFDB_FLAG_ZEROMEM, &tmp );
+ } else {
+ void * buf = tmp.fd_addr;
+ int size = init_mfdb( 1, loc.g_w, loc.g_h+1, MFDB_FLAG_STAND | MFDB_FLAG_NOALLOC, &tmp );
+ tmp.fd_addr = buf;
+ memset( tmp.fd_addr, 0, size );
+ }
+ short ypos;
+ int rowsize = tmp.fd_wdwidth << 1;
+ char * d;
+ uint32_t * pp;
+ for (chr = 0; chr < blen; chr++) {
+ pp = (uint32_t*)fb_font->data + ((unsigned char)buffer[chr] * fb_font->height);
+ d = ((uint8_t*)tmp.fd_addr) + chr;
+ for( ypos=0; ypos<loc.g_h; ypos++){
+ *d = (unsigned char)*pp++;
+ d += rowsize;
+ }
+ }
+#ifdef WITH_8BPP_SUPPORT
+ if( app.nplanes > 8 ){
+#endif
+ //unsigned short out[4];
+ RGB1000 out;
+ //rgb_to_vdi1000( (unsigned char*)&fstyle->foreground, (unsigned short*)&out );
+ out.blue = 0;
+ out.green = 1000;
+ out.red = 0;
+ vs_color(atari_plot_vdi_handle, OFFSET_CUSTOM_COLOR, (short *)&out);
+ vq_color(atari_plot_vdi_handle, OFFSET_CUSTOM_COLOR, 1, (short *)&out);
+ //printf("r:%d,g:%d,b:%d", out.red, out.green, out.blue);
+ //vsl_color(atari_plot_vdi_handle, OFFSET_CUSTOM_COLOR);
+ //vsf_color(atari_plot_vdi_handle, OFFSET_CUSTOM_COLOR);
+ plot_blit_mfdb(&loc, &tmp, OFFSET_CUSTOM_COLOR, PLOT_FLAG_TRANS);
+#ifdef WITH_8BPP_SUPPORT
+ } else {
+ unsigned char c = RGB_TO_VDI(fstyle->foreground);
+ plot_blit_mfdb(&loc, &tmp, c, PLOT_FLAG_TRANS );
+ }
+#endif
+ }
+
+ free(buffer);
+ return( 1 );
+}
+
+/* ------------------*/
+/* Fontdata */
+/* ------------------*/
+
+static const uint32_t fontdata_bold[FONTDATAMAX] = {
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0xE4, 0xAC, 0xA4, 0xA4, 0xEE, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0xEC, 0xA2, 0xA4, 0xA8, 0xEE, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0xEC, 0xA2, 0xAC, 0xA2, 0xEC, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0xEA, 0xAA, 0xAE, 0xA2, 0xE2, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0xEE, 0xA8, 0xAE, 0xA2, 0xEE, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0xE6, 0xA8, 0xAE, 0xAA, 0xEE, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0xEE, 0xA2, 0xA4, 0xA4, 0xE4, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0xEE, 0xAA, 0xAE, 0xAA, 0xEE, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0xEE, 0xAA, 0xAE, 0xA2, 0xE2, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0xE4, 0xAA, 0xAE, 0xAA, 0xEA, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0xEC, 0xAA, 0xAC, 0xAA, 0xEC, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0xE4, 0xAA, 0xA8, 0xAA, 0xE4, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0xEC, 0xAA, 0xAA, 0xAA, 0xEC, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0xEE, 0xA8, 0xAC, 0xA8, 0xEE, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0xEE, 0xA8, 0xAC, 0xA8, 0xE8, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0x4E, 0xCA, 0x4A, 0x4A, 0xEE, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0x44, 0xCC, 0x44, 0x44, 0xEE, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0x4C, 0xC2, 0x44, 0x48, 0xEE, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0x4C, 0xC2, 0x4C, 0x42, 0xEC, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0x4A, 0xCA, 0x4E, 0x42, 0xE2, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0x4E, 0xC8, 0x4E, 0x42, 0xEE, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0x46, 0xC8, 0x4E, 0x4A, 0xEE, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0x4E, 0xC2, 0x44, 0x44, 0xE4, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0x4E, 0xCA, 0x4E, 0x4A, 0xEE, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0x4E, 0xCA, 0x4E, 0x42, 0xE2, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0x44, 0xCA, 0x4E, 0x4A, 0xEA, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0x4C, 0xCA, 0x4C, 0x4A, 0xEC, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0x44, 0xCA, 0x48, 0x4A, 0xE4, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0x4C, 0xCA, 0x4A, 0x4A, 0xEC, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0x4E, 0xC8, 0x4C, 0x48, 0xEE, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0x4E, 0xC8, 0x4C, 0x48, 0xE8, 0x00, 0xFE,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C,
+ 0x1C, 0x00, 0x1C, 0x1C, 0x1C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x6C, 0x6C, 0xFE, 0xFE, 0xFE, 0x6C, 0x6C,
+ 0xFE, 0xFE, 0xFE, 0x6C, 0x6C, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x7C, 0xFE, 0xF6, 0xF0, 0xF8, 0x7C,
+ 0x3E, 0x1E, 0xDE, 0xFE, 0x7C, 0x10, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xE0, 0xE6, 0xEE, 0x1C,
+ 0x38, 0x70, 0xEE, 0xCE, 0x0E, 0x00, 0x00, 0x00,
+ 0x00, 0x70, 0xF8, 0xF8, 0xF8, 0xF8, 0x76, 0xFE,
+ 0xFE, 0xEC, 0xEE, 0xFE, 0x76, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x06, 0x0C, 0x1C, 0x38, 0x38, 0x70, 0x70, 0x70,
+ 0x70, 0x70, 0x38, 0x38, 0x1C, 0x0C, 0x06, 0x00,
+ 0x60, 0x30, 0x38, 0x1C, 0x1C, 0x0E, 0x0E, 0x0E,
+ 0x0E, 0x0E, 0x1C, 0x1C, 0x38, 0x30, 0x60, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x54, 0xFE, 0x7C, 0x38,
+ 0x7C, 0xFE, 0x54, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x38, 0xFE,
+ 0xFE, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x38, 0x78, 0x70, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE,
+ 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x1E, 0x3C,
+ 0x78, 0xF0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x38, 0x7C, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0x7C, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x18, 0x38, 0x78, 0x78, 0x38, 0x38, 0x38,
+ 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x7C, 0xFE, 0xEE, 0x0E, 0x0E, 0x7E, 0xFC,
+ 0xE0, 0xE0, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x7C, 0xFE, 0xEE, 0x0E, 0x0E, 0x3C, 0x3C,
+ 0x0E, 0x0E, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x04, 0x0C, 0x1C, 0x3C, 0x7C, 0x6C, 0xEC,
+ 0xFE, 0xFE, 0x1C, 0x1C, 0x1C, 0x00, 0x00, 0x00,
+ 0x00, 0xFE, 0xFE, 0xE0, 0xE0, 0xFC, 0xFE, 0x0E,
+ 0x0E, 0x0E, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x7C, 0xFC, 0xE0, 0xE0, 0xFC, 0xFE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0xFE, 0xFE, 0x0E, 0x0E, 0x1C, 0x1C, 0x1C,
+ 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x7C, 0xFE, 0xEE, 0xEE, 0xFE, 0x7C, 0xFE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x7C, 0xFE, 0xEE, 0xEE, 0xEE, 0xFE, 0x7E,
+ 0x0E, 0x0E, 0x0E, 0x7C, 0x78, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x38, 0x00,
+ 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x38, 0x00,
+ 0x00, 0x18, 0x38, 0x38, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0x0E, 0x1C, 0x38, 0x70,
+ 0x70, 0x38, 0x1C, 0x0E, 0x06, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x00,
+ 0x00, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x60, 0x70, 0x38, 0x1C, 0x0E,
+ 0x0E, 0x1C, 0x38, 0x70, 0x60, 0x00, 0x00, 0x00,
+ 0x00, 0x7C, 0xFE, 0xEE, 0x0E, 0x0E, 0x3E, 0x7C,
+ 0x70, 0x00, 0x70, 0x70, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x7C, 0xFE, 0xEE, 0xEE, 0xEE, 0xFE, 0xFE,
+ 0xEC, 0xE0, 0xE0, 0xFC, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x7C, 0xFE, 0xEE, 0xEE, 0xEE, 0xEE, 0xFE,
+ 0xFE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00,
+ 0x00, 0xFC, 0xFE, 0xEE, 0xEE, 0xEE, 0xFC, 0xFC,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0xFC, 0x00, 0x00, 0x00,
+ 0x00, 0x7C, 0xFE, 0xEE, 0xEE, 0xE0, 0xE0, 0xE0,
+ 0xE0, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0xF8, 0xFC, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFC, 0xF8, 0x00, 0x00, 0x00,
+ 0x00, 0xFE, 0xFE, 0xE0, 0xE0, 0xE0, 0xF8, 0xF8,
+ 0xE0, 0xE0, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0xFE, 0xFE, 0xE0, 0xE0, 0xE0, 0xF8, 0xF8,
+ 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0x00, 0x00, 0x00,
+ 0x00, 0x7C, 0xFE, 0xEE, 0xEE, 0xE0, 0xE0, 0xFE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xFE, 0xFE,
+ 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00,
+ 0x00, 0xFE, 0xFE, 0x38, 0x38, 0x38, 0x38, 0x38,
+ 0x38, 0x38, 0x38, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E,
+ 0x0E, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0xE0, 0xE6, 0xEE, 0xFE, 0xFC, 0xF8, 0xF0,
+ 0xF8, 0xFC, 0xFE, 0xEE, 0xE6, 0x00, 0x00, 0x00,
+ 0x00, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0,
+ 0xE0, 0xE0, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0xC6, 0xEE, 0xFE, 0xFE, 0xFE, 0xFE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00,
+ 0x00, 0xCE, 0xEE, 0xEE, 0xFE, 0xFE, 0xFE, 0xFE,
+ 0xFE, 0xFE, 0xEE, 0xEE, 0xE6, 0x00, 0x00, 0x00,
+ 0x00, 0x7C, 0xFE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0xFC, 0xFE, 0xEE, 0xEE, 0xEE, 0xEE, 0xFE,
+ 0xFC, 0xE0, 0xE0, 0xE0, 0xE0, 0x00, 0x00, 0x00,
+ 0x00, 0x7C, 0xFE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
+ 0xEE, 0xFE, 0xFE, 0xFE, 0x7E, 0x06, 0x00, 0x00,
+ 0x00, 0xFC, 0xFE, 0xEE, 0xEE, 0xEE, 0xFE, 0xFC,
+ 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00,
+ 0x00, 0x7C, 0xFE, 0xEE, 0xE0, 0xE0, 0xFC, 0x7E,
+ 0x0E, 0x0E, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0xFE, 0xFE, 0x38, 0x38, 0x38, 0x38, 0x38,
+ 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
+ 0x6C, 0x7C, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
+ 0xFE, 0xFE, 0xFE, 0xEE, 0x44, 0x00, 0x00, 0x00,
+ 0x00, 0xEE, 0xEE, 0xEE, 0xEE, 0x7C, 0x38, 0x38,
+ 0x7C, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00,
+ 0x00, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x7C, 0x38,
+ 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0xFE, 0xFE, 0x0E, 0x0E, 0x1C, 0x38, 0x38,
+ 0x70, 0xE0, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x3E, 0x3E, 0x38, 0x38, 0x38, 0x38, 0x38,
+ 0x38, 0x38, 0x38, 0x3E, 0x3E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0xE0, 0xF0, 0x78,
+ 0x3C, 0x1E, 0x0E, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xFC, 0xFC, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C,
+ 0x1C, 0x1C, 0x1C, 0xFC, 0xFC, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x38, 0x7C, 0xEE, 0xC6, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00,
+ 0x00, 0x00, 0x00, 0x30, 0x38, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x7E, 0x0E,
+ 0x7E, 0xFE, 0xEE, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0xE0, 0xE0, 0xE0, 0xE0, 0xFC, 0xFE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0xFC, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xFE, 0xEE,
+ 0xE0, 0xE0, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x0E, 0x0E, 0x0E, 0x0E, 0x7E, 0xFE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xFE, 0xEE,
+ 0xFE, 0xFE, 0xE0, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x3E, 0x7E, 0x70, 0x70, 0x70, 0xF8, 0xF8,
+ 0x70, 0x70, 0x70, 0x70, 0x70, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xFE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7E, 0x0E, 0x7E, 0x7C,
+ 0x00, 0x00, 0xE0, 0xE0, 0xE0, 0xFC, 0xFE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x38, 0x38, 0x00, 0x78, 0x78, 0x38,
+ 0x38, 0x38, 0x38, 0x7C, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x1C, 0x1C, 0x00, 0x3C, 0x3C, 0x1C,
+ 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x7C, 0x78,
+ 0x00, 0xE0, 0xE0, 0xE0, 0xE6, 0xEE, 0xFE, 0xFC,
+ 0xF8, 0xFC, 0xFE, 0xEE, 0xE6, 0x00, 0x00, 0x00,
+ 0x00, 0x78, 0x78, 0x38, 0x38, 0x38, 0x38, 0x38,
+ 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0xFE, 0xFE,
+ 0xFE, 0xFE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xFE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0xFC, 0xE0, 0xE0, 0xE0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xFE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7E, 0x0E, 0x0F, 0x0F,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xDE, 0xFE, 0xE0,
+ 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xFE, 0xE0,
+ 0xFC, 0x7E, 0x0E, 0xFE, 0xFC, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x30, 0x70, 0x70, 0xFC, 0xFC, 0x70,
+ 0x70, 0x70, 0x70, 0x7E, 0x3E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xEE, 0xEE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xEE, 0xEE, 0xEE,
+ 0xEE, 0xEE, 0x7C, 0x38, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xEE, 0xEE, 0xEE,
+ 0xFE, 0xFE, 0xFE, 0xEE, 0x44, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xEE, 0xEE, 0xEE,
+ 0x7C, 0x7C, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xEE, 0xEE, 0xEE,
+ 0xEE, 0xEE, 0xFE, 0x7E, 0x0E, 0x0E, 0xFE, 0xFC,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x1E,
+ 0x3C, 0x78, 0xF0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x1E, 0x3E, 0x38, 0x38, 0x38, 0xF0, 0xF0,
+ 0x38, 0x38, 0x38, 0x3E, 0x1E, 0x00, 0x00, 0x00,
+ 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
+ 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x00,
+ 0x00, 0xF0, 0xF8, 0x38, 0x38, 0x38, 0x1E, 0x1E,
+ 0x38, 0x38, 0x38, 0xF8, 0xF0, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x66, 0xFE, 0xFE, 0xCC, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0xEE, 0x28, 0x4C, 0x48, 0x48, 0x00, 0xFE,
+ 0x00, 0x38, 0x7C, 0xEE, 0xE0, 0xFC, 0xE0, 0xF8,
+ 0xE0, 0xE0, 0xEE, 0x7C, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x38, 0x38, 0x6C, 0x54, 0xF6, 0xEE,
+ 0x6C, 0x7C, 0x28, 0x38, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x38, 0x38, 0x18, 0x30, 0x00,
+ 0x00, 0x3E, 0x7E, 0x70, 0x70, 0x70, 0xF8, 0xF8,
+ 0x70, 0x70, 0x70, 0x70, 0x70, 0xF0, 0xE0, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xEE, 0xEE, 0x66, 0xCC, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xDB, 0xDB, 0xDB, 0x00, 0x00, 0x00,
+ 0x00, 0x38, 0x38, 0x38, 0x38, 0xFE, 0xFE, 0x38,
+ 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00,
+ 0x00, 0x38, 0x38, 0x38, 0xFE, 0xFE, 0x38, 0xFE,
+ 0xFE, 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00,
+ 0x00, 0x7C, 0xEE, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xCE, 0x1C,
+ 0x38, 0x70, 0xE0, 0xDB, 0x1B, 0x00, 0x00, 0x00,
+ 0xEE, 0x7C, 0x00, 0x7C, 0xFE, 0xEE, 0xE0, 0xFC,
+ 0x7E, 0x0E, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0E, 0x1C,
+ 0x38, 0x70, 0x38, 0x1C, 0x0E, 0x06, 0x00, 0x00,
+ 0x00, 0x7F, 0xFF, 0xEE, 0xEE, 0xEE, 0xEF, 0xEF,
+ 0xEE, 0xEE, 0xEE, 0xFF, 0x7F, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x38, 0x38, 0x6C, 0x54, 0xF6, 0xEE,
+ 0x6C, 0x7C, 0x28, 0x38, 0x10, 0x00, 0x00, 0x00,
+ 0xEE, 0x7C, 0x00, 0xFE, 0xFE, 0x0E, 0x1E, 0x3C,
+ 0x78, 0xF0, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x38, 0x38, 0x6C, 0x54, 0xF6, 0xEE,
+ 0x6C, 0x7C, 0x28, 0x38, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x38, 0x38, 0x6C, 0x54, 0xF6, 0xEE,
+ 0x6C, 0x7C, 0x28, 0x38, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x30, 0x30, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x36, 0x6C, 0x6C, 0x6C, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x36, 0x36, 0x36, 0x6C, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x7E,
+ 0x7E, 0x7E, 0x7E, 0x3C, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x7B, 0xDE, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xF1, 0xFB, 0x5F, 0x55, 0x51, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xEE, 0x7C, 0x38, 0x00, 0x7E, 0xFE, 0xE0,
+ 0xFC, 0x7E, 0x0E, 0xFE, 0xFC, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x70, 0x38,
+ 0x1C, 0x0E, 0x1C, 0x38, 0x70, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x6C, 0xFE, 0xFA,
+ 0xDE, 0xDE, 0xFC, 0xFE, 0x6E, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x38, 0x38, 0x6C, 0x54, 0xF6, 0xEE,
+ 0x6C, 0x7C, 0x28, 0x38, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0xEE, 0x7C, 0x38, 0x00, 0xFE, 0xFE, 0x1E,
+ 0x3C, 0x78, 0xF0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0xEE, 0x00, 0xEE, 0xEE, 0xEE, 0xEE, 0x7C,
+ 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x38, 0x00,
+ 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x10, 0x7C, 0xFE, 0xD6,
+ 0xD0, 0xD0, 0xD6, 0xFE, 0x7C, 0x10, 0x10, 0x00,
+ 0x00, 0x3C, 0x7E, 0x76, 0x70, 0xFC, 0xFC, 0xFC,
+ 0x70, 0x76, 0xFE, 0xFE, 0xDC, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xEE, 0xEE, 0x7C, 0xFE,
+ 0xFE, 0xFE, 0xFE, 0x7C, 0xEE, 0xEE, 0x00, 0x00,
+ 0x00, 0x00, 0xEE, 0xEE, 0xEE, 0x7C, 0x38, 0xFE,
+ 0x38, 0xFE, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x38, 0x38, 0x38, 0x38, 0x00,
+ 0x00, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x3C, 0x7C, 0x7C, 0x70, 0x3C, 0x7E, 0x66,
+ 0x7E, 0x3C, 0x0E, 0x3E, 0x3E, 0x3C, 0x00, 0x00,
+ 0x00, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x3C, 0x7E, 0xC3, 0x99, 0xBD, 0xA5, 0xA1,
+ 0xA5, 0xBD, 0x99, 0xC3, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x7C, 0x00, 0xFC,
+ 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E,
+ 0x7C, 0xF8, 0xF8, 0x7C, 0x3E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x7E, 0x7E, 0x7E, 0x06, 0x02, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x7E, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x3C, 0x7E, 0xC3, 0xB9, 0xBD, 0xA5, 0xB9,
+ 0xB9, 0xA5, 0xA5, 0xC3, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x78, 0xFC, 0xCC, 0xFC, 0x78, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x38, 0x38, 0xFE, 0xFE, 0xFE, 0x38,
+ 0x38, 0x00, 0xFE, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xF0, 0xF8, 0x18, 0x78, 0xF0, 0xC0,
+ 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xF0, 0xF8, 0x18, 0x30, 0x18, 0xF8,
+ 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x38, 0x70, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0xFC, 0xE0, 0xE0, 0xC0,
+ 0x00, 0x00, 0x00, 0x7F, 0xDB, 0xDB, 0xDB, 0x7B,
+ 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x38,
+ 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x18, 0x1C, 0x0C, 0x1C, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x60, 0xE0, 0x60, 0x60, 0x60, 0xF0,
+ 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x70, 0xF8, 0x88, 0xF8, 0x70, 0x00, 0xF8,
+ 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8,
+ 0x6C, 0x36, 0x36, 0x6C, 0xD8, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x60, 0xE0, 0x62, 0x66, 0xFE, 0x1C,
+ 0x38, 0x76, 0xEE, 0xD6, 0x3E, 0x3E, 0x06, 0x00,
+ 0x00, 0x00, 0x60, 0xE0, 0x62, 0x66, 0xFE, 0x1C,
+ 0x38, 0x70, 0xFC, 0xC6, 0x0C, 0x18, 0x1E, 0x00,
+ 0x00, 0x00, 0xE0, 0x30, 0x62, 0x36, 0xEE, 0x1C,
+ 0x3A, 0x76, 0xEE, 0xD6, 0x3E, 0x3E, 0x06, 0x00,
+ 0x00, 0x00, 0x1C, 0x1C, 0x1C, 0x00, 0x1C, 0x1C,
+ 0x7C, 0xF8, 0xE0, 0xEE, 0xEE, 0xFE, 0x7C, 0x00,
+ 0x00, 0xE0, 0x70, 0x00, 0x10, 0x38, 0x7C, 0xEE,
+ 0xFE, 0xFE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00,
+ 0x00, 0x0E, 0x1C, 0x00, 0x10, 0x38, 0x7C, 0xEE,
+ 0xFE, 0xFE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00,
+ 0x00, 0x38, 0x6C, 0xC6, 0x10, 0x38, 0x7C, 0xEE,
+ 0xFE, 0xFE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00,
+ 0x00, 0x76, 0xDC, 0x00, 0x10, 0x38, 0x7C, 0xEE,
+ 0xFE, 0xFE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00,
+ 0x00, 0xEE, 0xEE, 0x10, 0x38, 0x7C, 0xEE, 0xFE,
+ 0xFE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00,
+ 0x00, 0x38, 0x6C, 0x38, 0x38, 0x7C, 0xEE, 0xFE,
+ 0xFE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00,
+ 0x00, 0x1F, 0x3F, 0x7F, 0xFE, 0xEE, 0xFF, 0xFF,
+ 0xFE, 0xEE, 0xEF, 0xEF, 0xEF, 0x00, 0x00, 0x00,
+ 0x00, 0x7C, 0xFE, 0xEE, 0xE0, 0xE0, 0xE0, 0xE0,
+ 0xE0, 0xE0, 0xEE, 0xFE, 0x7C, 0x0E, 0x6E, 0x7C,
+ 0x00, 0x70, 0x38, 0x00, 0xFE, 0xFE, 0xE0, 0xE0,
+ 0xF8, 0xE0, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x1C, 0x38, 0x00, 0xFE, 0xFE, 0xE0, 0xE0,
+ 0xF8, 0xE0, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x7C, 0xEE, 0x00, 0xFE, 0xFE, 0xE0, 0xE0,
+ 0xF8, 0xE0, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0xEE, 0xEE, 0x00, 0xFE, 0xFE, 0xE0, 0xE0, 0xF8,
+ 0xF8, 0xE0, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x70, 0x38, 0x00, 0x38, 0x38, 0x38, 0x38,
+ 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x1C, 0x38, 0x00, 0x38, 0x38, 0x38, 0x38,
+ 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x38, 0x6C, 0x38, 0x38, 0x38, 0x38, 0x38,
+ 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0xEE, 0xEE, 0x00, 0x38, 0x38, 0x38, 0x38,
+ 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xF8, 0xFC, 0xEE, 0xEE, 0xEE, 0xFE,
+ 0xEE, 0xEE, 0xEE, 0xFC, 0xF8, 0x00, 0x00, 0x00,
+ 0x00, 0x76, 0xDC, 0x00, 0xEE, 0xEE, 0xEE, 0xF6,
+ 0xFE, 0xDE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00,
+ 0x00, 0x70, 0x38, 0x00, 0x7C, 0xFE, 0xEE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x1C, 0x38, 0x00, 0x7C, 0xFE, 0xEE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x7C, 0xEE, 0x00, 0x7C, 0xFE, 0xEE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x76, 0xDC, 0x00, 0x7C, 0xFE, 0xEE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0xEE, 0xEE, 0x00, 0x7C, 0xFE, 0xEE, 0xEE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xEE, 0x7C,
+ 0x38, 0x38, 0x7C, 0xEE, 0xC6, 0x00, 0x00, 0x00,
+ 0x00, 0x7A, 0xFC, 0xEE, 0xEE, 0xEE, 0xFE, 0xFE,
+ 0xFE, 0xEE, 0xEE, 0xFE, 0x7C, 0x80, 0x00, 0x00,
+ 0x00, 0x70, 0x38, 0x00, 0xEE, 0xEE, 0xEE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x1C, 0x38, 0x00, 0xEE, 0xEE, 0xEE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x7C, 0xEE, 0x00, 0xEE, 0xEE, 0xEE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0xEE, 0xEE, 0x00, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x1C, 0x38, 0x00, 0xEE, 0xEE, 0xEE, 0xEE,
+ 0x7C, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xE0, 0xE0, 0xFC, 0xFE, 0xEE, 0xEE,
+ 0xEE, 0xFE, 0xFC, 0xE0, 0xE0, 0x00, 0x00, 0x00,
+ 0x00, 0x7C, 0xFE, 0xEE, 0xEE, 0xEE, 0xFE, 0xFC,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0xFC, 0xE0, 0xC0, 0x00,
+ 0x00, 0x00, 0x70, 0x38, 0x00, 0x7C, 0x7E, 0x0E,
+ 0x7E, 0xFE, 0xEE, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x1C, 0x38, 0x00, 0x7C, 0x7E, 0x0E,
+ 0x7E, 0xFE, 0xEE, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x38, 0x7C, 0xEE, 0x00, 0x7C, 0x7E, 0x0E,
+ 0x7E, 0xFE, 0xEE, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x76, 0xDC, 0x00, 0x7C, 0x7E, 0x0E,
+ 0x7E, 0xFE, 0xEE, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xEE, 0xEE, 0x00, 0x7C, 0x7E, 0x0E,
+ 0x7E, 0xFE, 0xEE, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x38, 0x6C, 0x38, 0x00, 0x7C, 0x7E, 0x0E,
+ 0x7E, 0xFE, 0xEE, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x74, 0x7E, 0x7E, 0x1A,
+ 0x7E, 0xFE, 0xD8, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xFE,
+ 0xEE, 0xE0, 0xEE, 0xFE, 0x7C, 0x1C, 0x7E, 0x7C,
+ 0x00, 0x00, 0x70, 0x38, 0x00, 0x7C, 0xFE, 0xEE,
+ 0xFE, 0xFE, 0xE0, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x38, 0x70, 0x00, 0x7C, 0xFE, 0xEE,
+ 0xFE, 0xFE, 0xE0, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x38, 0x7C, 0xEE, 0x00, 0x7C, 0xFE, 0xEE,
+ 0xFE, 0xFE, 0xE0, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xEE, 0xEE, 0x00, 0x7C, 0xFE, 0xEE,
+ 0xFE, 0xFE, 0xE0, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x70, 0x38, 0x00, 0x38, 0x38, 0x38,
+ 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x1C, 0x38, 0x00, 0x38, 0x38, 0x38,
+ 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x38, 0x7C, 0xEE, 0x00, 0x38, 0x38, 0x38,
+ 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xEE, 0xEE, 0x00, 0x38, 0x38, 0x38,
+ 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0xEC, 0x7C, 0xF8, 0xFC, 0x7E, 0xFE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x76, 0xFE, 0xDC, 0x00, 0xFC, 0xFE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xE0, 0x70, 0x00, 0x7C, 0xFE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x38, 0x70, 0x00, 0x7C, 0xFE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x38, 0x7C, 0xEE, 0x00, 0x7C, 0xFE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x76, 0xFE, 0xDC, 0x00, 0x7C, 0xFE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xEE, 0xEE, 0x00, 0x7C, 0xFE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0xFE,
+ 0xFE, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x7C, 0xFE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x80, 0x00, 0x00,
+ 0x00, 0x00, 0xE0, 0x70, 0x00, 0xEE, 0xEE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x38, 0x70, 0x00, 0xEE, 0xEE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x38, 0x7C, 0xEE, 0x00, 0xEE, 0xEE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xEE, 0xEE, 0x00, 0xEE, 0xEE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x1C, 0x38, 0x00, 0xEE, 0xEE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7E, 0x0E, 0xFE, 0xFC,
+ 0x00, 0x00, 0xE0, 0xE0, 0xFC, 0xFE, 0xEE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xEE, 0xFE, 0xFC, 0xE0, 0xE0,
+ 0x00, 0x00, 0xEE, 0xEE, 0x00, 0xEE, 0xEE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7E, 0x0E, 0xFE, 0xFC,
+};
+
+const struct fb_font_desc font_bold = {
+ .name = "NetSurf Bold",
+ .width = 8,
+ .height = 16,
+ .encoding = "CP1252",
+ .data = fontdata_bold,
+};
+
+
+static const uint32_t fontdata_italic[FONTDATAMAX] = {
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0xE4, 0xAC, 0xA4, 0xA4, 0xEE, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0xEC, 0xA2, 0xA4, 0xA8, 0xEE, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0xEC, 0xA2, 0xAC, 0xA2, 0xEC, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0xEA, 0xAA, 0xAE, 0xA2, 0xE2, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0xEE, 0xA8, 0xAE, 0xA2, 0xEE, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0xE6, 0xA8, 0xAE, 0xAA, 0xEE, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0xEE, 0xA2, 0xA4, 0xA4, 0xE4, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0xEE, 0xAA, 0xAE, 0xAA, 0xEE, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0xEE, 0xAA, 0xAE, 0xA2, 0xE2, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0xE4, 0xAA, 0xAE, 0xAA, 0xEA, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0xEC, 0xAA, 0xAC, 0xAA, 0xEC, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0xE4, 0xAA, 0xA8, 0xAA, 0xE4, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0xEC, 0xAA, 0xAA, 0xAA, 0xEC, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0xEE, 0xA8, 0xAC, 0xA8, 0xEE, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0xEE, 0xA8, 0xAC, 0xA8, 0xE8, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0x4E, 0xCA, 0x4A, 0x4A, 0xEE, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0x44, 0xCC, 0x44, 0x44, 0xEE, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0x4C, 0xC2, 0x44, 0x48, 0xEE, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0x4C, 0xC2, 0x4C, 0x42, 0xEC, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0x4A, 0xCA, 0x4E, 0x42, 0xE2, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0x4E, 0xC8, 0x4E, 0x42, 0xEE, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0x46, 0xC8, 0x4E, 0x4A, 0xEE, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0x4E, 0xC2, 0x44, 0x44, 0xE4, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0x4E, 0xCA, 0x4E, 0x4A, 0xEE, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0x4E, 0xCA, 0x4E, 0x42, 0xE2, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0x44, 0xCA, 0x4E, 0x4A, 0xEA, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0x4C, 0xCA, 0x4C, 0x4A, 0xEC, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0x44, 0xCA, 0x48, 0x4A, 0xE4, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0x4C, 0xCA, 0x4A, 0x4A, 0xEC, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0x4E, 0xC8, 0x4C, 0x48, 0xEE, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0x4E, 0xC8, 0x4C, 0x48, 0xE8, 0x00, 0xFE,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x06, 0x06, 0x06, 0x06, 0x0C, 0x0C, 0x0C,
+ 0x0C, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x1B, 0x1B, 0x36, 0x36, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x1B, 0x1B, 0x1B, 0x7F, 0x7F, 0x36, 0x36,
+ 0xFF, 0xFF, 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00,
+ 0x00, 0x04, 0x3E, 0x7F, 0x6B, 0x68, 0x78, 0x3C,
+ 0x1E, 0x16, 0xD6, 0xFE, 0x7C, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xCE, 0x1C,
+ 0x38, 0x70, 0xE6, 0xC6, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x1C, 0x3E, 0x36, 0x36, 0x3C, 0x39, 0x7F,
+ 0x6E, 0xCC, 0xCC, 0xFE, 0x7A, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x06, 0x0C, 0x0C, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x06, 0x0E, 0x1C, 0x38, 0x30, 0x60, 0x60, 0xC0,
+ 0xC0, 0xC0, 0xC0, 0xC0, 0xE0, 0x70, 0x30, 0x00,
+ 0x18, 0x1C, 0x0E, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x0C, 0x0C, 0x18, 0x38, 0x70, 0xE0, 0xC0, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x1C, 0x7F,
+ 0xFE, 0x38, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E,
+ 0xFC, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x38, 0x70, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xFC,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0E, 0x1C,
+ 0x38, 0x70, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x1E, 0x3F, 0x33, 0x33, 0x67, 0x6E, 0x76,
+ 0xE6, 0xCC, 0xCC, 0xFC, 0x78, 0x00, 0x00, 0x00,
+ 0x00, 0x06, 0x0E, 0x1E, 0x3C, 0x0C, 0x0C, 0x18,
+ 0x18, 0x18, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x1E, 0x3F, 0x33, 0x03, 0x07, 0x1E, 0x7C,
+ 0x60, 0xC0, 0xC0, 0xFC, 0xFC, 0x00, 0x00, 0x00,
+ 0x00, 0x1E, 0x3F, 0x33, 0x03, 0x06, 0x1E, 0x1E,
+ 0x06, 0x06, 0xCC, 0xFC, 0x78, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1E, 0x36, 0x7F,
+ 0x7F, 0x0C, 0x0C, 0x18, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x1F, 0x1F, 0x30, 0x30, 0x7C, 0x7E, 0x06,
+ 0x06, 0x06, 0xCE, 0xFC, 0x78, 0x00, 0x00, 0x00,
+ 0x00, 0x0F, 0x1F, 0x38, 0x30, 0x60, 0x7C, 0x7E,
+ 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x3F, 0x7F, 0x63, 0x03, 0x06, 0x06, 0x0C,
+ 0x0C, 0x18, 0x18, 0x30, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x1E, 0x3F, 0x33, 0x33, 0x33, 0x1E, 0x7C,
+ 0x66, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x1E, 0x3F, 0x33, 0x63, 0x63, 0x7E, 0x3E,
+ 0x06, 0x0C, 0x1C, 0xF8, 0xF0, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00,
+ 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00,
+ 0x00, 0x00, 0x18, 0x38, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x0E, 0x1C, 0x38, 0x70, 0x70,
+ 0x70, 0x38, 0x1C, 0x0C, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3E, 0x7C, 0x00, 0x00,
+ 0x7C, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x18, 0x0C, 0x0C, 0x06, 0x0E,
+ 0x1C, 0x38, 0x70, 0x60, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x1E, 0x3F, 0x33, 0x33, 0x03, 0x07, 0x0E,
+ 0x1C, 0x18, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x1E, 0x3F, 0x33, 0x63, 0x6F, 0x6B, 0x6B,
+ 0xCF, 0xCE, 0xC0, 0xFC, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x1E, 0x3F, 0x33, 0x33, 0x66, 0x7E, 0x7E,
+ 0x66, 0xCC, 0xCC, 0xCC, 0xCC, 0x00, 0x00, 0x00,
+ 0x00, 0x3E, 0x3F, 0x33, 0x63, 0x63, 0x7E, 0x7C,
+ 0x66, 0xC6, 0xC6, 0xFE, 0xFC, 0x00, 0x00, 0x00,
+ 0x00, 0x1E, 0x3F, 0x33, 0x30, 0x60, 0x60, 0x60,
+ 0x60, 0xC0, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x3E, 0x3F, 0x33, 0x63, 0x63, 0x63, 0x63,
+ 0xC3, 0xC6, 0xCE, 0xFC, 0xF8, 0x00, 0x00, 0x00,
+ 0x00, 0x3F, 0x3F, 0x30, 0x30, 0x60, 0x7C, 0x7C,
+ 0x60, 0xC0, 0xC0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x3F, 0x3F, 0x30, 0x30, 0x60, 0x7C, 0x7C,
+ 0x60, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00,
+ 0x00, 0x1E, 0x3F, 0x33, 0x30, 0x60, 0x60, 0x6E,
+ 0x6E, 0xC6, 0xCE, 0xFC, 0x78, 0x00, 0x00, 0x00,
+ 0x00, 0x33, 0x33, 0x33, 0x63, 0x66, 0x7E, 0x7E,
+ 0xC6, 0xC6, 0xCC, 0xCC, 0xCC, 0x00, 0x00, 0x00,
+ 0x00, 0x3F, 0x3F, 0x0C, 0x0C, 0x18, 0x18, 0x18,
+ 0x18, 0x30, 0x30, 0xFC, 0xFC, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0x03, 0x03, 0x03, 0x06, 0x06, 0x06,
+ 0x06, 0x0C, 0xCC, 0xFC, 0x78, 0x00, 0x00, 0x00,
+ 0x00, 0x30, 0x30, 0x33, 0x36, 0x7C, 0x78, 0x70,
+ 0x78, 0xF8, 0xDC, 0xCE, 0xC6, 0x00, 0x00, 0x00,
+ 0x00, 0x30, 0x30, 0x30, 0x30, 0x60, 0x60, 0x60,
+ 0x60, 0xC0, 0xC0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x33, 0x33, 0x3F, 0x3F, 0x7F, 0x6B, 0x66,
+ 0x66, 0xC6, 0xCC, 0xCC, 0xCC, 0x00, 0x00, 0x00,
+ 0x00, 0x33, 0x33, 0x3B, 0x3B, 0x7B, 0x7E, 0x6E,
+ 0x6E, 0xCE, 0xCC, 0xCC, 0xCC, 0x00, 0x00, 0x00,
+ 0x00, 0x1E, 0x3F, 0x33, 0x33, 0x63, 0x66, 0x66,
+ 0xC6, 0xCC, 0xCC, 0xFC, 0x78, 0x00, 0x00, 0x00,
+ 0x00, 0x3E, 0x3F, 0x33, 0x33, 0x67, 0x7E, 0x7C,
+ 0x60, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00,
+ 0x00, 0x1E, 0x3F, 0x33, 0x33, 0x63, 0x66, 0x66,
+ 0xC6, 0xF6, 0xDC, 0xF8, 0x7C, 0x0C, 0x00, 0x00,
+ 0x00, 0x3E, 0x3F, 0x33, 0x33, 0x63, 0x7E, 0x7C,
+ 0x6E, 0xC6, 0xC6, 0xCC, 0xCC, 0x00, 0x00, 0x00,
+ 0x00, 0x1E, 0x3F, 0x33, 0x60, 0x60, 0x7C, 0x3E,
+ 0x06, 0x06, 0xCE, 0xFC, 0x78, 0x00, 0x00, 0x00,
+ 0x00, 0x7F, 0x7F, 0x18, 0x18, 0x30, 0x30, 0x30,
+ 0x30, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00,
+ 0x00, 0x33, 0x33, 0x33, 0x33, 0x63, 0x66, 0x66,
+ 0x66, 0xC6, 0xCC, 0xFC, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x33, 0x33, 0x33, 0x33, 0x63, 0x63, 0x66,
+ 0x66, 0x6C, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x33, 0x33, 0x33, 0x33, 0x63, 0x63, 0x6B,
+ 0x6B, 0xFE, 0xFE, 0xEE, 0x44, 0x00, 0x00, 0x00,
+ 0x00, 0x63, 0x63, 0x63, 0x77, 0x3E, 0x1C, 0x38,
+ 0x7C, 0xEE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00,
+ 0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x3C, 0x18,
+ 0x18, 0x30, 0x30, 0x60, 0x60, 0x00, 0x00, 0x00,
+ 0x00, 0x7F, 0x7F, 0x03, 0x07, 0x0E, 0x0C, 0x18,
+ 0x38, 0x70, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x0F, 0x0F, 0x0C, 0x0C, 0x18, 0x18, 0x18,
+ 0x18, 0x30, 0x30, 0x3E, 0x3E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE0, 0x70,
+ 0x38, 0x1C, 0x0E, 0x06, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x1F, 0x1F, 0x03, 0x03, 0x06, 0x06, 0x06,
+ 0x06, 0x0C, 0x0C, 0x7C, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x04, 0x0E, 0x1F, 0x3B, 0x63, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x00,
+ 0x00, 0x00, 0x00, 0x0C, 0x0E, 0x0C, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x3E, 0x06,
+ 0x7E, 0xFC, 0xCC, 0xFC, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x18, 0x18, 0x30, 0x30, 0x3E, 0x7F, 0x63,
+ 0x63, 0xC6, 0xC6, 0xFE, 0xFC, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x7E, 0x66,
+ 0xC0, 0xC0, 0xCC, 0xFC, 0x78, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0x03, 0x03, 0x06, 0x3E, 0x7E, 0x66,
+ 0xC6, 0xCC, 0xCC, 0xFC, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x7E, 0x66,
+ 0xFE, 0xFC, 0xC0, 0xFC, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x07, 0x0F, 0x0C, 0x18, 0x7E, 0x7E, 0x30,
+ 0x30, 0x30, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x7F, 0x63,
+ 0x63, 0xC6, 0xC6, 0xFE, 0x7E, 0x0C, 0xFC, 0xF8,
+ 0x00, 0x00, 0x30, 0x30, 0x30, 0x6E, 0x7F, 0x73,
+ 0x63, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x06, 0x00, 0x1C, 0x3C, 0x0C,
+ 0x0C, 0x18, 0x18, 0x7C, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x03, 0x03, 0x00, 0x0E, 0x1E, 0x06,
+ 0x06, 0x0C, 0x0C, 0x0C, 0x0C, 0x18, 0xF8, 0xF0,
+ 0x00, 0x30, 0x30, 0x30, 0x33, 0x67, 0x6E, 0x7C,
+ 0x7C, 0xDC, 0xCE, 0xC6, 0xC6, 0x00, 0x00, 0x00,
+ 0x00, 0x0E, 0x0E, 0x06, 0x06, 0x0C, 0x0C, 0x0C,
+ 0x0C, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x7F, 0x7F,
+ 0x6B, 0xD6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x7E, 0x76,
+ 0x66, 0xCC, 0xCC, 0xCC, 0xCC, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x7E, 0x66,
+ 0x66, 0xCC, 0xCC, 0xFC, 0x78, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x3F, 0x33,
+ 0x63, 0x66, 0x66, 0xFE, 0xFC, 0xC0, 0xC0, 0xC0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x7F, 0x63,
+ 0x63, 0xC6, 0xC6, 0xFE, 0x7C, 0x0C, 0x0E, 0x0E,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x6F, 0x7F, 0x70,
+ 0x60, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x7F, 0x60,
+ 0x7C, 0x3E, 0x06, 0xFE, 0xFC, 0x00, 0x00, 0x00,
+ 0x00, 0x06, 0x06, 0x0C, 0x0C, 0x3F, 0x3F, 0x18,
+ 0x18, 0x30, 0x30, 0x3E, 0x1C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0x66,
+ 0x66, 0x66, 0xCC, 0xFE, 0x76, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66,
+ 0xCC, 0xCC, 0xF8, 0x70, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x63, 0x63,
+ 0x6B, 0xDE, 0xFE, 0xFE, 0x6C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x63, 0x77,
+ 0x3E, 0x7C, 0xEE, 0xC6, 0xC6, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x63, 0x63,
+ 0x63, 0xC6, 0xC6, 0xFE, 0x7E, 0x0C, 0xFC, 0xF8,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x7F, 0x07,
+ 0x1E, 0x78, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x07, 0x0E, 0x0C, 0x0C, 0x18, 0x70, 0x70,
+ 0x18, 0x18, 0x30, 0x38, 0x1C, 0x00, 0x00, 0x00,
+ 0x06, 0x06, 0x06, 0x06, 0x0C, 0x0C, 0x0C, 0x0C,
+ 0x18, 0x18, 0x18, 0x18, 0x30, 0x30, 0x30, 0x00,
+ 0x00, 0x38, 0x1C, 0x0C, 0x18, 0x18, 0x0E, 0x0E,
+ 0x18, 0x30, 0x30, 0x70, 0xE0, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x1D, 0x3F, 0x37, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0xEE, 0x28, 0x4C, 0x48, 0x48, 0x00, 0xFE,
+ 0x00, 0x06, 0x0F, 0x1B, 0x18, 0x7E, 0x30, 0x7C,
+ 0x60, 0x60, 0x6C, 0x3C, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x38, 0x38, 0x6C, 0x54, 0xF6, 0xEE,
+ 0x6C, 0x7C, 0x28, 0x38, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x18, 0x10, 0x20, 0x00,
+ 0x00, 0x07, 0x0F, 0x0C, 0x18, 0x7E, 0x7E, 0x30,
+ 0x30, 0x30, 0x60, 0x60, 0x60, 0xC0, 0x80, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x66, 0x66, 0x44, 0x88, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xDB, 0xDB, 0x00, 0x00, 0x00,
+ 0x00, 0x06, 0x06, 0x06, 0x1F, 0x3F, 0x0C, 0x0C,
+ 0x0C, 0x18, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00,
+ 0x00, 0x06, 0x06, 0x06, 0x1F, 0x3F, 0x0C, 0x3F,
+ 0x3F, 0x18, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00,
+ 0x00, 0x3E, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x63, 0x06,
+ 0x0C, 0x30, 0x60, 0xDB, 0x9B, 0x00, 0x00, 0x00,
+ 0x63, 0x3E, 0x00, 0x1E, 0x3F, 0x33, 0x60, 0x7C,
+ 0x3E, 0x06, 0xCE, 0xFC, 0x78, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0E,
+ 0x1C, 0x30, 0x38, 0x1C, 0x0C, 0x00, 0x00, 0x00,
+ 0x00, 0x1F, 0x3F, 0x33, 0x33, 0x66, 0x67, 0x67,
+ 0x66, 0xCC, 0xCC, 0xFF, 0x7F, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x38, 0x38, 0x6C, 0x54, 0xF6, 0xEE,
+ 0x6C, 0x7C, 0x28, 0x38, 0x10, 0x00, 0x00, 0x00,
+ 0x63, 0x3E, 0x00, 0x7F, 0x7F, 0x03, 0x07, 0x0E,
+ 0x18, 0x70, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x38, 0x38, 0x6C, 0x54, 0xF6, 0xEE,
+ 0x6C, 0x7C, 0x28, 0x38, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x38, 0x38, 0x6C, 0x54, 0xF6, 0xEE,
+ 0x6C, 0x7C, 0x28, 0x38, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x08, 0x10, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0C, 0x04, 0x08, 0x10, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x09, 0x12, 0x1B, 0x36, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x1B, 0x1B, 0x09, 0x12, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x3F,
+ 0x3F, 0x7E, 0x7E, 0x3C, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x19, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xFB, 0xFF, 0x55, 0xA2, 0xA2, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x63, 0x36, 0x1C, 0x00, 0x3F, 0x7F, 0x60,
+ 0x7C, 0x3E, 0x06, 0xFE, 0xFC, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1C,
+ 0x0E, 0x0C, 0x1C, 0x38, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x7F, 0x6D,
+ 0x6F, 0xDE, 0xD8, 0xFE, 0x6E, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x38, 0x38, 0x6C, 0x54, 0xF6, 0xEE,
+ 0x6C, 0x7C, 0x28, 0x38, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x63, 0x36, 0x1C, 0x00, 0x7F, 0x7F, 0x07,
+ 0x1E, 0x78, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x33, 0x00, 0x66, 0x66, 0x66, 0x3C, 0x3C,
+ 0x18, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00,
+ 0x0C, 0x18, 0x18, 0x18, 0x18, 0x30, 0x30, 0x00,
+ 0x00, 0x00, 0x00, 0x04, 0x04, 0x3E, 0x7F, 0x6B,
+ 0x68, 0xD0, 0xD6, 0xFE, 0x7C, 0x20, 0x20, 0x00,
+ 0x00, 0x0F, 0x1F, 0x19, 0x18, 0x30, 0x7C, 0x7C,
+ 0x30, 0x60, 0xE6, 0xFE, 0xDC, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x19, 0x33, 0x1E, 0x3F,
+ 0x33, 0x66, 0x7E, 0x3C, 0x66, 0xCC, 0x00, 0x00,
+ 0x00, 0x00, 0x19, 0x19, 0x19, 0x1E, 0x0C, 0x3F,
+ 0x0C, 0x7E, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0x06, 0x0C, 0x0C, 0x00,
+ 0x00, 0x18, 0x18, 0x30, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x07, 0x0E, 0x18, 0x18, 0x3C, 0x7E, 0x66,
+ 0x7E, 0x3C, 0x18, 0x18, 0x70, 0xE0, 0x00, 0x00,
+ 0x00, 0x00, 0x33, 0x66, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x0E, 0x1F, 0x21, 0x21, 0x4D, 0x51, 0x51,
+ 0x91, 0xA1, 0x9A, 0x82, 0x7C, 0x38, 0x00, 0x00,
+ 0x00, 0x1C, 0x02, 0x1E, 0x22, 0x3C, 0x00, 0x7C,
+ 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B,
+ 0x36, 0xD8, 0xD8, 0x6C, 0x36, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x1E, 0x3E, 0x06, 0x0C, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x0E, 0x1F, 0x21, 0x49, 0x55, 0x55, 0x59,
+ 0x99, 0xA5, 0xA5, 0x82, 0x7E, 0x78, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x1E, 0x3F, 0x33, 0x3F, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0x06, 0x3F, 0x3F, 0x0C,
+ 0x0C, 0x00, 0x7E, 0x7E, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x3C, 0x3E, 0x06, 0x3C, 0x78, 0x60,
+ 0x7C, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x3C, 0x3E, 0x06, 0x18, 0x0C, 0x7C,
+ 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0x0C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33,
+ 0x33, 0x66, 0x66, 0x7E, 0x7C, 0xC0, 0xC0, 0x80,
+ 0x00, 0x00, 0x00, 0x3F, 0x6F, 0xDB, 0xDB, 0x7B,
+ 0x1B, 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C,
+ 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x18, 0x1C, 0x0C, 0x1C, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x38, 0x18, 0x30, 0x30, 0x78,
+ 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x0C, 0x1E, 0x22, 0x3C, 0x18, 0x00, 0x3C,
+ 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6C,
+ 0x36, 0x36, 0x36, 0x6C, 0xD8, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x10, 0x30, 0x10, 0x23, 0x76, 0x0C,
+ 0x18, 0x64, 0xCC, 0x94, 0x3E, 0x08, 0x08, 0x00,
+ 0x00, 0x00, 0x10, 0x30, 0x10, 0x23, 0x76, 0x0C,
+ 0x18, 0x60, 0xDC, 0x82, 0x1C, 0x20, 0x3C, 0x00,
+ 0x00, 0x00, 0x38, 0x04, 0x18, 0x0B, 0x76, 0x0C,
+ 0x18, 0x64, 0xCC, 0x96, 0x3E, 0x08, 0x08, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x0C, 0x0C,
+ 0x3C, 0x70, 0xC0, 0xC6, 0xC6, 0xFC, 0x78, 0x00,
+ 0x00, 0x18, 0x0C, 0x00, 0x04, 0x1C, 0x36, 0x63,
+ 0x7F, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0x06, 0x00, 0x04, 0x1C, 0x36, 0x63,
+ 0x7F, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00,
+ 0x00, 0x0E, 0x1B, 0x11, 0x04, 0x1C, 0x36, 0x63,
+ 0x7F, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00,
+ 0x00, 0x1D, 0x37, 0x00, 0x04, 0x1C, 0x36, 0x63,
+ 0x7F, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00,
+ 0x00, 0x1B, 0x1B, 0x04, 0x0E, 0x36, 0x63, 0x7F,
+ 0x7F, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00,
+ 0x00, 0x0E, 0x11, 0x0E, 0x0E, 0x36, 0x63, 0x7F,
+ 0x7F, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00,
+ 0x00, 0x07, 0x0F, 0x1F, 0x3B, 0x66, 0x7F, 0x7F,
+ 0x66, 0xCC, 0xCC, 0xCF, 0xCF, 0x00, 0x00, 0x00,
+ 0x00, 0x1E, 0x3F, 0x33, 0x30, 0x60, 0x60, 0x60,
+ 0x60, 0xC0, 0xC6, 0xFE, 0x7C, 0x1C, 0xCC, 0x78,
+ 0x00, 0x0C, 0x06, 0x00, 0x3F, 0x7F, 0x60, 0x78,
+ 0x78, 0xC0, 0xC0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0x06, 0x00, 0x3F, 0x7F, 0x60, 0x78,
+ 0x78, 0xC0, 0xC0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x0E, 0x1B, 0x00, 0x3F, 0x7F, 0x60, 0x78,
+ 0x78, 0xC0, 0xC0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x1B, 0x1B, 0x00, 0x3F, 0x3F, 0x60, 0x60, 0x78,
+ 0x78, 0xC0, 0xC0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x0C, 0x06, 0x00, 0x1F, 0x1F, 0x0C, 0x0C,
+ 0x0C, 0x18, 0x18, 0x7C, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0x06, 0x00, 0x1F, 0x1F, 0x0C, 0x0C,
+ 0x0C, 0x18, 0x18, 0x7C, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x06, 0x09, 0x1F, 0x1F, 0x0C, 0x0C, 0x0C,
+ 0x0C, 0x18, 0x18, 0x7C, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x1B, 0x1B, 0x00, 0x1F, 0x1F, 0x0C, 0x0C,
+ 0x0C, 0x18, 0x18, 0x7C, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x1E, 0x1F, 0x1B, 0x33, 0x33, 0x7B,
+ 0x33, 0x66, 0x6E, 0x7C, 0x78, 0x00, 0x00, 0x00,
+ 0x00, 0x1D, 0x37, 0x00, 0x31, 0x63, 0x73, 0x7B,
+ 0x7F, 0xDE, 0xCE, 0xC6, 0xC6, 0x00, 0x00, 0x00,
+ 0x00, 0x0C, 0x06, 0x00, 0x3E, 0x7F, 0x63, 0x63,
+ 0x63, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0x06, 0x00, 0x3E, 0x7F, 0x63, 0x63,
+ 0x63, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x0E, 0x1B, 0x00, 0x3E, 0x7F, 0x63, 0x63,
+ 0x63, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x1D, 0x37, 0x00, 0x3E, 0x7F, 0x63, 0x63,
+ 0x63, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x1B, 0x1B, 0x00, 0x3E, 0x7F, 0x63, 0x63,
+ 0x63, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x77, 0x3E,
+ 0x1C, 0x38, 0x7C, 0xEE, 0xC6, 0x00, 0x00, 0x00,
+ 0x00, 0x1D, 0x3E, 0x37, 0x6B, 0x6B, 0x6B, 0xD6,
+ 0xD6, 0xD6, 0xEE, 0x7C, 0xB8, 0x00, 0x00, 0x00,
+ 0x00, 0x0C, 0x06, 0x00, 0x33, 0x33, 0x63, 0x66,
+ 0x66, 0xC6, 0xCE, 0xFC, 0x78, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0x06, 0x00, 0x33, 0x33, 0x63, 0x66,
+ 0x66, 0xC6, 0xCE, 0xFC, 0x78, 0x00, 0x00, 0x00,
+ 0x00, 0x0E, 0x1B, 0x00, 0x33, 0x33, 0x63, 0x66,
+ 0x66, 0xC6, 0xCE, 0xFC, 0x78, 0x00, 0x00, 0x00,
+ 0x1B, 0x1B, 0x00, 0x33, 0x33, 0x63, 0x63, 0x63,
+ 0x66, 0xC6, 0xCE, 0xFC, 0x78, 0x00, 0x00, 0x00,
+ 0x00, 0x06, 0x0C, 0x00, 0x33, 0x33, 0x66, 0x6E,
+ 0x7C, 0x38, 0x30, 0x60, 0x60, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x18, 0x1F, 0x3F, 0x33, 0x33,
+ 0x3F, 0x7C, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00,
+ 0x00, 0x0E, 0x1F, 0x1B, 0x1B, 0x33, 0x3F, 0x3E,
+ 0x33, 0x66, 0x66, 0x7E, 0x7C, 0xC0, 0x80, 0x00,
+ 0x00, 0x00, 0x0C, 0x06, 0x00, 0x3F, 0x7F, 0x63,
+ 0x63, 0xCE, 0xCE, 0xFE, 0x76, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x0C, 0x00, 0x3F, 0x7F, 0x63,
+ 0x63, 0xC6, 0xCE, 0xFE, 0x76, 0x00, 0x00, 0x00,
+ 0x00, 0x04, 0x0E, 0x1B, 0x00, 0x3F, 0x7F, 0x63,
+ 0x63, 0xC6, 0xCE, 0xFE, 0x76, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x1D, 0x37, 0x00, 0x3F, 0x7F, 0x63,
+ 0x63, 0xC6, 0xCE, 0xFE, 0x76, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x1B, 0x1B, 0x00, 0x3F, 0x7F, 0x63,
+ 0x63, 0xC6, 0xCE, 0xFE, 0x76, 0x00, 0x00, 0x00,
+ 0x00, 0x0E, 0x1B, 0x0E, 0x00, 0x3E, 0x7F, 0x63,
+ 0x63, 0xC6, 0xCE, 0xFE, 0x76, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x3F, 0x0D,
+ 0x1F, 0x7E, 0xD8, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x7F,
+ 0x63, 0xC0, 0xC6, 0xFE, 0x7C, 0x30, 0xF8, 0xF0,
+ 0x00, 0x00, 0x0C, 0x06, 0x00, 0x3E, 0x7F, 0x63,
+ 0x7F, 0xFE, 0xC0, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x0C, 0x00, 0x3E, 0x7F, 0x63,
+ 0x7F, 0xFE, 0xC0, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x04, 0x0E, 0x1B, 0x00, 0x3E, 0x7F, 0x63,
+ 0x7F, 0xFE, 0xC0, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x1B, 0x1B, 0x00, 0x3E, 0x7F, 0x63,
+ 0x7F, 0xFE, 0xC0, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0C, 0x06, 0x00, 0x0C, 0x0C, 0x0C,
+ 0x0C, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x03, 0x06, 0x00, 0x0C, 0x0C, 0x0C,
+ 0x0C, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x06, 0x0F, 0x19, 0x00, 0x0C, 0x0C, 0x0C,
+ 0x0C, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x1B, 0x1B, 0x00, 0x0C, 0x0C, 0x0C,
+ 0x0C, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x1B, 0x1F, 0x3E, 0x37, 0x3E, 0x7F, 0x63,
+ 0x63, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x1D, 0x3F, 0x37, 0x00, 0x7E, 0x7F, 0x63,
+ 0x63, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x0C, 0x00, 0x3E, 0x7F, 0x63,
+ 0x63, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x0C, 0x00, 0x3E, 0x7F, 0x63,
+ 0x63, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x04, 0x0E, 0x1B, 0x00, 0x3E, 0x7F, 0x63,
+ 0x63, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x1D, 0x3F, 0x37, 0x00, 0x3E, 0x7F, 0x63,
+ 0x63, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x1B, 0x1B, 0x00, 0x3E, 0x7F, 0x63,
+ 0x63, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00, 0x3F,
+ 0x7E, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x7F, 0x67,
+ 0x6B, 0xD6, 0xE6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x0C, 0x00, 0x63, 0x63, 0x63,
+ 0x63, 0xC6, 0xC6, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x0C, 0x00, 0x63, 0x63, 0x63,
+ 0x63, 0xC6, 0xC6, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x04, 0x0E, 0x1B, 0x00, 0x63, 0x63, 0x63,
+ 0x63, 0xC6, 0xC6, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x1B, 0x1B, 0x00, 0x63, 0x63, 0x63,
+ 0x63, 0xC6, 0xC6, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x03, 0x06, 0x00, 0x63, 0x63, 0x63,
+ 0x63, 0xC6, 0xC6, 0xFE, 0x7E, 0x0C, 0xF8, 0xF0,
+ 0x00, 0x00, 0x18, 0x18, 0x18, 0x3E, 0x3F, 0x33,
+ 0x33, 0x66, 0x66, 0x7E, 0x7C, 0xC0, 0xC0, 0xC0,
+ 0x00, 0x00, 0x00, 0x1B, 0x00, 0x63, 0x63, 0x63,
+ 0x63, 0xC6, 0xC6, 0xFE, 0x7E, 0x0C, 0xF8, 0xF0,
+};
+
+const struct fb_font_desc font_italic = {
+ .name = "NetSurf Italic",
+ .width = 8,
+ .height = 16,
+ .encoding = "CP1252",
+ .data = fontdata_italic,
+};
+
+
+static const uint32_t fontdata_italic_bold[FONTDATAMAX] = {
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0xE4, 0xAC, 0xA4, 0xA4, 0xEE, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0xEC, 0xA2, 0xA4, 0xA8, 0xEE, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0xEC, 0xA2, 0xAC, 0xA2, 0xEC, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0xEA, 0xAA, 0xAE, 0xA2, 0xE2, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0xEE, 0xA8, 0xAE, 0xA2, 0xEE, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0xE6, 0xA8, 0xAE, 0xAA, 0xEE, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0xEE, 0xA2, 0xA4, 0xA4, 0xE4, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0xEE, 0xAA, 0xAE, 0xAA, 0xEE, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0xEE, 0xAA, 0xAE, 0xA2, 0xE2, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0xE4, 0xAA, 0xAE, 0xAA, 0xEA, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0xEC, 0xAA, 0xAC, 0xAA, 0xEC, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0xE4, 0xAA, 0xA8, 0xAA, 0xE4, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0xEC, 0xAA, 0xAA, 0xAA, 0xEC, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0xEE, 0xA8, 0xAC, 0xA8, 0xEE, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0xEE, 0xA8, 0xAC, 0xA8, 0xE8, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0x4E, 0xCA, 0x4A, 0x4A, 0xEE, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0x44, 0xCC, 0x44, 0x44, 0xEE, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0x4C, 0xC2, 0x44, 0x48, 0xEE, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0x4C, 0xC2, 0x4C, 0x42, 0xEC, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0x4A, 0xCA, 0x4E, 0x42, 0xE2, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0x4E, 0xC8, 0x4E, 0x42, 0xEE, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0x46, 0xC8, 0x4E, 0x4A, 0xEE, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0x4E, 0xC2, 0x44, 0x44, 0xE4, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0x4E, 0xCA, 0x4E, 0x4A, 0xEE, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0x4E, 0xCA, 0x4E, 0x42, 0xE2, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0x44, 0xCA, 0x4E, 0x4A, 0xEA, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0x4C, 0xCA, 0x4C, 0x4A, 0xEC, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0x44, 0xCA, 0x48, 0x4A, 0xE4, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0x4C, 0xCA, 0x4A, 0x4A, 0xEC, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0x4E, 0xC8, 0x4C, 0x48, 0xEE, 0x00, 0xFE,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0x4E, 0xC8, 0x4C, 0x48, 0xE8, 0x00, 0xFE,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x0E, 0x0E, 0x0E, 0x0E, 0x1C, 0x1C, 0x1C,
+ 0x1C, 0x00, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x36, 0x36, 0x7F, 0x7F, 0x7F, 0x36, 0x6C,
+ 0xFE, 0xFE, 0xFE, 0x6C, 0x6C, 0x00, 0x00, 0x00,
+ 0x00, 0x08, 0x3E, 0x7F, 0x7B, 0x78, 0x7C, 0x7C,
+ 0x3E, 0x1E, 0xDE, 0xFE, 0x7C, 0x10, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x70, 0x73, 0x77, 0x0E,
+ 0x3C, 0x70, 0xEE, 0xCE, 0x0E, 0x00, 0x00, 0x00,
+ 0x00, 0x1C, 0x3E, 0x7E, 0x7C, 0x7C, 0x3B, 0xFE,
+ 0xFE, 0xEC, 0xEE, 0xFE, 0x74, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x1C, 0x1C, 0x1C, 0x1C, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x06, 0x0E, 0x1C, 0x1C, 0x38, 0x38, 0x70,
+ 0x70, 0x70, 0x38, 0x38, 0x1C, 0x0C, 0x06, 0x00,
+ 0x60, 0x30, 0x38, 0x1C, 0x1C, 0x0E, 0x0E, 0x0E,
+ 0x1C, 0x1C, 0x38, 0x38, 0x70, 0x60, 0xC0, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x2A, 0x7F, 0x3E, 0x18,
+ 0x7C, 0xFE, 0x54, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x1C, 0x7E,
+ 0x7E, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x38, 0x78, 0x70, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE,
+ 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0F, 0x3C,
+ 0x78, 0xF0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x1C, 0x3E, 0x77, 0x77, 0x77, 0x77, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0x7C, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x0C, 0x1C, 0x3C, 0x3C, 0x1C, 0x1C, 0x38,
+ 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x3E, 0x7F, 0x77, 0x07, 0x07, 0x3E, 0x7C,
+ 0xE0, 0xE0, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x3E, 0x7F, 0x77, 0x07, 0x07, 0x1E, 0x3C,
+ 0x0E, 0x0E, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x02, 0x06, 0x0E, 0x1E, 0x3E, 0x76, 0xEC,
+ 0xFE, 0xFE, 0x1C, 0x1C, 0x1C, 0x00, 0x00, 0x00,
+ 0x00, 0x7F, 0x7F, 0x70, 0x70, 0x7C, 0x7E, 0x0E,
+ 0x0E, 0x0E, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x3E, 0x7E, 0x70, 0x70, 0x7C, 0x7E, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x7F, 0x7F, 0x07, 0x07, 0x0E, 0x0E, 0x1C,
+ 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x3E, 0x7F, 0x77, 0x77, 0x7F, 0x3E, 0x7E,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x3E, 0x7F, 0x77, 0x77, 0x77, 0x7F, 0x3E,
+ 0x0E, 0x0E, 0x0E, 0x7C, 0x78, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x1C, 0x00,
+ 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x1C, 0x00,
+ 0x00, 0x18, 0x38, 0x38, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0x07, 0x0E, 0x1C, 0x70,
+ 0x70, 0x38, 0x1C, 0x0E, 0x06, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x7F, 0x00,
+ 0x00, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x30, 0x38, 0x1C, 0x0E, 0x0E,
+ 0x0E, 0x1C, 0x38, 0x70, 0x60, 0x00, 0x00, 0x00,
+ 0x00, 0x3E, 0x7F, 0x77, 0x07, 0x07, 0x1E, 0x7C,
+ 0x70, 0x00, 0x70, 0x70, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x3E, 0x7F, 0x77, 0x77, 0x77, 0x7F, 0xFE,
+ 0xEC, 0xE0, 0xE0, 0xFC, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x3E, 0x7F, 0x77, 0x77, 0x77, 0x76, 0xFE,
+ 0xFE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00,
+ 0x00, 0x7E, 0x7F, 0x77, 0x77, 0x77, 0x7E, 0xFC,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0xFC, 0x00, 0x00, 0x00,
+ 0x00, 0x3E, 0x7F, 0x77, 0x77, 0x70, 0x70, 0xE0,
+ 0xE0, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x7C, 0x7E, 0x77, 0x77, 0x77, 0x76, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFC, 0xF8, 0x00, 0x00, 0x00,
+ 0x00, 0x7F, 0x7F, 0x70, 0x70, 0x70, 0x7C, 0xF8,
+ 0xE0, 0xE0, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x7F, 0x7F, 0x70, 0x70, 0x70, 0x7C, 0xF8,
+ 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0x00, 0x00, 0x00,
+ 0x00, 0x3E, 0x7F, 0x77, 0x77, 0x70, 0x70, 0xFE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x7E, 0xFE,
+ 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00,
+ 0x00, 0x7F, 0x7F, 0x1C, 0x1C, 0x1C, 0x1C, 0x38,
+ 0x38, 0x38, 0x38, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x0E,
+ 0x0E, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x70, 0x70, 0x72, 0x77, 0x7F, 0x7E, 0xF8,
+ 0xF8, 0xFC, 0xFE, 0xEE, 0xE6, 0x00, 0x00, 0x00,
+ 0x00, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0xE0,
+ 0xE0, 0xE0, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x63, 0x77, 0x7F, 0x7F, 0x7F, 0x7E, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00,
+ 0x00, 0x67, 0x77, 0x77, 0x7F, 0x7F, 0x7E, 0xFE,
+ 0xFE, 0xFE, 0xEE, 0xEE, 0xE6, 0x00, 0x00, 0x00,
+ 0x00, 0x3E, 0x7F, 0x77, 0x77, 0x77, 0x76, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x7E, 0x7F, 0x77, 0x77, 0x77, 0x77, 0xFE,
+ 0xFC, 0xE0, 0xE0, 0xE0, 0xE0, 0x00, 0x00, 0x00,
+ 0x00, 0x3E, 0x7F, 0x77, 0x77, 0x77, 0x76, 0xEE,
+ 0xEE, 0xFE, 0xFE, 0xFE, 0x7E, 0x06, 0x00, 0x00,
+ 0x00, 0x7E, 0x7F, 0x77, 0x77, 0x77, 0x7E, 0xFC,
+ 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00,
+ 0x00, 0x3E, 0x7F, 0x77, 0x70, 0x70, 0x7C, 0x3E,
+ 0x0E, 0x0E, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x7F, 0x7F, 0x1C, 0x1C, 0x1C, 0x1C, 0x38,
+ 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x76, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x76, 0xEE,
+ 0x6C, 0x7C, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x76, 0xEE,
+ 0xFE, 0xFE, 0xFE, 0xEE, 0x44, 0x00, 0x00, 0x00,
+ 0x00, 0x77, 0x77, 0x77, 0x77, 0x3E, 0x1C, 0x38,
+ 0x7C, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00,
+ 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x3E, 0x38,
+ 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x7F, 0x7F, 0x07, 0x07, 0x0E, 0x1C, 0x38,
+ 0x70, 0xE0, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x1F, 0x1F, 0x1C, 0x1C, 0x1C, 0x1C, 0x38,
+ 0x38, 0x38, 0x38, 0x3E, 0x3E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x70, 0x78, 0x38,
+ 0x1C, 0x1E, 0x0E, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x7E, 0x7E, 0x0E, 0x0E, 0x0E, 0x0E, 0x1C,
+ 0x1C, 0x1C, 0x1C, 0xFC, 0xFC, 0x00, 0x00, 0x00,
+ 0x00, 0x08, 0x1C, 0x3E, 0x77, 0x63, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x1C, 0x0C, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x3E, 0x0E,
+ 0x3E, 0x7E, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x38, 0x38, 0x38, 0x70, 0x7C, 0x7E, 0x6E,
+ 0xEE, 0xEE, 0xEE, 0xFC, 0xF8, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x7E, 0xEE,
+ 0xE0, 0xE0, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x07, 0x07, 0x07, 0x07, 0x3F, 0x7E, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x7E, 0xEE,
+ 0xFE, 0xFC, 0xE0, 0xFC, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x1F, 0x3F, 0x38, 0x38, 0x70, 0x7C, 0x7C,
+ 0x70, 0xE0, 0xE0, 0xE0, 0xE0, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x7E, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x1C, 0xFC, 0xF8,
+ 0x00, 0x00, 0x70, 0x70, 0x70, 0x7C, 0x7E, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0E, 0x0E, 0x00, 0x1E, 0x3E, 0x1C,
+ 0x1C, 0x38, 0x38, 0x7C, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0E, 0x0E, 0x00, 0x1E, 0x3E, 0x0E,
+ 0x1C, 0x1C, 0x1C, 0x1C, 0x38, 0x38, 0xF8, 0xF0,
+ 0x00, 0x38, 0x38, 0x38, 0x3A, 0x7F, 0x7E, 0x7C,
+ 0x70, 0xF8, 0xFC, 0xEE, 0xEE, 0x00, 0x00, 0x00,
+ 0x00, 0x3C, 0x3C, 0x1C, 0x1C, 0x38, 0x38, 0x38,
+ 0x38, 0x70, 0x70, 0x70, 0x70, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x7E, 0xFE,
+ 0xFE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x7E, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x7E, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFC, 0x78, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x7E, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFC, 0xF8, 0xE0, 0xE0, 0xE0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x7E, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFC, 0x7C, 0x1C, 0x1E, 0x1E,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x7E, 0x70,
+ 0x70, 0xE0, 0xE0, 0xE0, 0xE0, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x3E, 0x70,
+ 0x7C, 0x3E, 0x0E, 0x7C, 0xF8, 0x00, 0x00, 0x00,
+ 0x00, 0x38, 0x38, 0x38, 0x70, 0x7C, 0x7C, 0x70,
+ 0xE0, 0xE0, 0xE0, 0xFC, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x76, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x76, 0xEE,
+ 0xEE, 0xEE, 0x7C, 0x38, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x76, 0xEE,
+ 0xFE, 0xFE, 0xFE, 0xEE, 0x44, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x76, 0x7E,
+ 0x38, 0x7C, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x76, 0xEE,
+ 0xEE, 0xEE, 0xFE, 0x7E, 0x1C, 0x1C, 0xFC, 0xF8,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x7E, 0x1E,
+ 0x3C, 0x78, 0xF0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x0F, 0x1F, 0x1C, 0x1C, 0x1C, 0x78, 0xF0,
+ 0x38, 0x38, 0x38, 0x3E, 0x1E, 0x00, 0x00, 0x00,
+ 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x38,
+ 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x00,
+ 0x00, 0x78, 0x7C, 0x1C, 0x1C, 0x1C, 0x0F, 0x1E,
+ 0x38, 0x38, 0x38, 0xF8, 0xF0, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x33, 0x7F, 0x7F, 0x66, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77,
+ 0x00, 0xEE, 0x28, 0x4C, 0x48, 0x48, 0x00, 0xFE,
+ 0x00, 0x06, 0x1F, 0x3B, 0x70, 0xFE, 0x70, 0xF8,
+ 0xE0, 0xE0, 0xEE, 0xFC, 0x70, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x38, 0x38, 0x6C, 0x54, 0xF6, 0xEE,
+ 0x6C, 0x7C, 0x28, 0x38, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x38, 0x38, 0x30, 0x60, 0x00,
+ 0x00, 0x1F, 0x3F, 0x38, 0x38, 0x70, 0x7C, 0x7C,
+ 0x70, 0xE0, 0xE0, 0xE0, 0xE0, 0xC0, 0xC0, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xEE, 0xEE, 0xCC, 0x98, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xDB, 0xDB, 0xDB, 0x00, 0x00, 0x00,
+ 0x00, 0x1C, 0x1C, 0x1C, 0x1C, 0x7F, 0x7F, 0x38,
+ 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00,
+ 0x00, 0x1C, 0x1C, 0x1C, 0x7F, 0x7F, 0x1C, 0xFE,
+ 0xFE, 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00,
+ 0x00, 0x3E, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x67, 0x1C,
+ 0x38, 0x70, 0xE0, 0xDB, 0x1B, 0x00, 0x00, 0x00,
+ 0x77, 0x3E, 0x00, 0x3E, 0x7F, 0x77, 0x70, 0x7C,
+ 0x3E, 0x0E, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x1C,
+ 0x38, 0x70, 0x38, 0x1C, 0x0E, 0x06, 0x00, 0x00,
+ 0x00, 0x3F, 0x7F, 0x77, 0x77, 0x77, 0x77, 0xEF,
+ 0xEE, 0xEE, 0xEE, 0xFF, 0x7F, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x38, 0x38, 0x6C, 0x54, 0xF6, 0xEE,
+ 0x6C, 0x7C, 0x28, 0x38, 0x10, 0x00, 0x00, 0x00,
+ 0x77, 0x3E, 0x00, 0x7F, 0x7F, 0x07, 0x0E, 0x1C,
+ 0x38, 0x70, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x38, 0x38, 0x6C, 0x54, 0xF6, 0xEE,
+ 0x6C, 0x7C, 0x28, 0x38, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x38, 0x38, 0x6C, 0x54, 0xF6, 0xEE,
+ 0x6C, 0x7C, 0x28, 0x38, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0C, 0x18, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x1B, 0x36, 0x36, 0x36, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x1B, 0x1B, 0x1B, 0x36, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x7E,
+ 0x7E, 0x7E, 0x7E, 0x3C, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x3B, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x79, 0x7F, 0x2F, 0x29, 0x29, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x77, 0x3E, 0x1C, 0x00, 0x1F, 0x3E, 0x70,
+ 0x7C, 0x3E, 0x0E, 0x7C, 0xF8, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x38, 0x38,
+ 0x1C, 0x0E, 0x1C, 0x38, 0x70, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x7F, 0xFA,
+ 0xDE, 0xDE, 0xFC, 0xFE, 0x6E, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x38, 0x38, 0x6C, 0x54, 0xF6, 0xEE,
+ 0x6C, 0x7C, 0x28, 0x38, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x77, 0x3E, 0x1C, 0x00, 0x7F, 0x7E, 0x1E,
+ 0x3C, 0x78, 0xF0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x3B, 0x00, 0x77, 0x77, 0x77, 0x77, 0x3E,
+ 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x1C, 0x00,
+ 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x08, 0x3E, 0x7F, 0xD6,
+ 0xD0, 0xD0, 0xD6, 0xFE, 0x7C, 0x10, 0x10, 0x00,
+ 0x00, 0x1E, 0x3F, 0x3B, 0x38, 0x7E, 0x7E, 0xFC,
+ 0x70, 0x76, 0xFE, 0xFE, 0xDC, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x3E, 0xFE,
+ 0xFE, 0xFE, 0xFE, 0x7C, 0xEE, 0xEE, 0x00, 0x00,
+ 0x00, 0x00, 0x77, 0x77, 0x77, 0x3E, 0x1C, 0xFE,
+ 0x38, 0xFE, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x1C, 0x1C, 0x1C, 0x1C, 0x00,
+ 0x00, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x1E, 0x3E, 0x3E, 0x38, 0x1E, 0x3F, 0x66,
+ 0x7E, 0x3C, 0x0E, 0x3E, 0x3E, 0x3C, 0x00, 0x00,
+ 0x00, 0x77, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x1E, 0x3F, 0x61, 0x4D, 0x5D, 0x51, 0xA1,
+ 0xA5, 0xBD, 0x99, 0xC3, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x3C, 0x06, 0x3E, 0x66, 0x3E, 0x00, 0xFC,
+ 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E,
+ 0x7C, 0xF8, 0xF8, 0x7C, 0x3E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x3F, 0x3F, 0x3F, 0x03, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x7E, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x1E, 0x3F, 0x61, 0x59, 0x5D, 0x55, 0xB9,
+ 0xB9, 0xA5, 0xA5, 0xC3, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x7F, 0x7F, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x3C, 0x7E, 0x66, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x1C, 0x1C, 0x7F, 0x7F, 0x7F, 0x38,
+ 0x38, 0x00, 0xFE, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x78, 0x7C, 0x0C, 0x3C, 0x78, 0xC0,
+ 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x78, 0x7C, 0x0C, 0x18, 0x0C, 0xF8,
+ 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x1C, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0xFC, 0xE0, 0xE0, 0xC0,
+ 0x00, 0x00, 0x00, 0x3F, 0x6D, 0x6D, 0x6D, 0x7A,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x38,
+ 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x18, 0x1C, 0x0C, 0x1C, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x30, 0x70, 0x30, 0x30, 0x30, 0xF0,
+ 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x38, 0x7C, 0x44, 0x7C, 0x38, 0x00, 0xF8,
+ 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8,
+ 0x6C, 0x36, 0x36, 0x6C, 0xD8, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x30, 0x70, 0x31, 0x33, 0x7F, 0x1C,
+ 0x38, 0x76, 0xEE, 0xD6, 0x3E, 0x3E, 0x06, 0x00,
+ 0x00, 0x00, 0x30, 0x70, 0x31, 0x33, 0x7F, 0x1C,
+ 0x38, 0x70, 0xFC, 0xC6, 0x0C, 0x18, 0x1E, 0x00,
+ 0x00, 0x00, 0x70, 0x18, 0x31, 0x1B, 0x77, 0x1C,
+ 0x3A, 0x76, 0xEE, 0xD6, 0x3E, 0x3E, 0x06, 0x00,
+ 0x00, 0x00, 0x0E, 0x0E, 0x0E, 0x00, 0x0E, 0x1C,
+ 0x7C, 0xF8, 0xE0, 0xEE, 0xEE, 0xFE, 0x7C, 0x00,
+ 0x00, 0x70, 0x38, 0x00, 0x08, 0x1C, 0x3E, 0xEE,
+ 0xFE, 0xFE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00,
+ 0x00, 0x07, 0x0E, 0x00, 0x08, 0x1C, 0x3E, 0xEE,
+ 0xFE, 0xFE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00,
+ 0x00, 0x1C, 0x36, 0x63, 0x08, 0x1C, 0x3E, 0xEE,
+ 0xFE, 0xFE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00,
+ 0x00, 0x3B, 0x6E, 0x00, 0x08, 0x1C, 0x3E, 0xEE,
+ 0xFE, 0xFE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00,
+ 0x00, 0x77, 0x77, 0x08, 0x1C, 0x3E, 0x76, 0xFE,
+ 0xFE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00,
+ 0x00, 0x1C, 0x36, 0x1C, 0x1C, 0x3E, 0x76, 0xFE,
+ 0xFE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00,
+ 0x00, 0x0F, 0x1F, 0x3F, 0x7F, 0x77, 0x7F, 0xFF,
+ 0xFE, 0xEE, 0xEF, 0xEF, 0xEF, 0x00, 0x00, 0x00,
+ 0x00, 0x3E, 0x7F, 0x77, 0x70, 0x70, 0x70, 0xE0,
+ 0xE0, 0xE0, 0xEE, 0xFE, 0x7C, 0x0E, 0x6E, 0x7C,
+ 0x00, 0x38, 0x1C, 0x00, 0x7F, 0x7F, 0x70, 0xE0,
+ 0xF8, 0xE0, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x0E, 0x1C, 0x00, 0x7F, 0x7F, 0x70, 0xE0,
+ 0xF8, 0xE0, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x3E, 0x77, 0x00, 0x7F, 0x7F, 0x70, 0xE0,
+ 0xF8, 0xE0, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x77, 0x77, 0x00, 0x7F, 0x7F, 0x70, 0x70, 0xF8,
+ 0xF8, 0xE0, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x38, 0x1C, 0x00, 0x1C, 0x1C, 0x1C, 0x38,
+ 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x0E, 0x1C, 0x00, 0x1C, 0x1C, 0x1C, 0x38,
+ 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x1C, 0x36, 0x1C, 0x1C, 0x1C, 0x1C, 0x38,
+ 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x77, 0x77, 0x00, 0x1C, 0x1C, 0x1C, 0x38,
+ 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x7C, 0x7E, 0x77, 0x77, 0x76, 0xFE,
+ 0xEE, 0xEE, 0xEE, 0xFC, 0xF8, 0x00, 0x00, 0x00,
+ 0x00, 0x3B, 0x6E, 0x00, 0x77, 0x77, 0x76, 0xF6,
+ 0xFE, 0xDE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00,
+ 0x00, 0x38, 0x1C, 0x00, 0x3E, 0x7F, 0x76, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x0E, 0x1C, 0x00, 0x3E, 0x7F, 0x76, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x3E, 0x77, 0x00, 0x3E, 0x7F, 0x76, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x3B, 0x6E, 0x00, 0x3E, 0x7F, 0x76, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x77, 0x77, 0x00, 0x3E, 0x7F, 0x77, 0x76, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x76, 0x7C,
+ 0x38, 0x38, 0x7C, 0xEE, 0xC6, 0x00, 0x00, 0x00,
+ 0x00, 0x3D, 0x7E, 0x77, 0x77, 0x77, 0x7E, 0xFE,
+ 0xFE, 0xEE, 0xEE, 0xFE, 0x7C, 0x80, 0x00, 0x00,
+ 0x00, 0x38, 0x1C, 0x00, 0x77, 0x77, 0x76, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x0E, 0x1C, 0x00, 0x77, 0x77, 0x76, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x3E, 0x77, 0x00, 0x77, 0x77, 0x76, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x77, 0x77, 0x00, 0x77, 0x77, 0x77, 0x76, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x0E, 0x1C, 0x00, 0x77, 0x77, 0x76, 0xEE,
+ 0x7C, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x70, 0x70, 0x7E, 0x7F, 0x76, 0xEE,
+ 0xEE, 0xFE, 0xFC, 0xE0, 0xE0, 0x00, 0x00, 0x00,
+ 0x00, 0x3E, 0x7F, 0x77, 0x77, 0x77, 0x7E, 0xFC,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0xFC, 0xE0, 0xC0, 0x00,
+ 0x00, 0x00, 0x70, 0x38, 0x00, 0x3C, 0x3E, 0x0E,
+ 0x3E, 0x7E, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x1C, 0x38, 0x00, 0x3C, 0x3E, 0x0E,
+ 0x3E, 0x7E, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x38, 0x7C, 0xEE, 0x00, 0x3C, 0x3E, 0x0E,
+ 0x3E, 0x7E, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x76, 0xDC, 0x00, 0x3C, 0x3E, 0x0E,
+ 0x3E, 0x7E, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xEE, 0xEE, 0x00, 0x3C, 0x3E, 0x0E,
+ 0x3E, 0x7E, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x38, 0x6C, 0x38, 0x00, 0x3C, 0x3E, 0x0E,
+ 0x3E, 0x7E, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3A, 0x3F, 0x3F, 0x1A,
+ 0x7E, 0xFE, 0xD8, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0xFE,
+ 0xEE, 0xE0, 0xEE, 0xFE, 0x7C, 0x1C, 0x7E, 0x7C,
+ 0x00, 0x00, 0x38, 0x1C, 0x00, 0x3E, 0x7F, 0xEE,
+ 0xFE, 0xFE, 0xE0, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x1C, 0x38, 0x00, 0x3E, 0x7F, 0xEE,
+ 0xFE, 0xFE, 0xE0, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x1C, 0x3E, 0x77, 0x00, 0x3E, 0x7F, 0xEE,
+ 0xFE, 0xFE, 0xE0, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x77, 0x77, 0x00, 0x3E, 0x7F, 0xEE,
+ 0xFE, 0xFE, 0xE0, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x38, 0x1C, 0x00, 0x1C, 0x1C, 0x38,
+ 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0E, 0x1C, 0x00, 0x1C, 0x1C, 0x38,
+ 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x1C, 0x3E, 0x77, 0x00, 0x1C, 0x1C, 0x38,
+ 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x77, 0x77, 0x00, 0x1C, 0x1C, 0x38,
+ 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x76, 0x3E, 0x7C, 0x7E, 0x3F, 0x7E, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x3B, 0x7F, 0x6E, 0x00, 0x7E, 0x7F, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x70, 0x38, 0x00, 0x3C, 0x7E, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFC, 0x78, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x1C, 0x38, 0x00, 0x3C, 0x7E, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFC, 0x78, 0x00, 0x00, 0x00,
+ 0x00, 0x1C, 0x3E, 0x77, 0x00, 0x3C, 0x7E, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFC, 0x78, 0x00, 0x00, 0x00,
+ 0x00, 0x3B, 0x7F, 0x6E, 0x00, 0x3C, 0x7E, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFC, 0x78, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x77, 0x77, 0x00, 0x3C, 0x7E, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFC, 0x78, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x1C, 0x1C, 0x00, 0xFE,
+ 0xFE, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x3E, 0x7E, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x80, 0x00, 0x00,
+ 0x00, 0x00, 0x70, 0x38, 0x00, 0x77, 0x76, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x1C, 0x38, 0x00, 0x77, 0x76, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x1C, 0x3E, 0x77, 0x00, 0x77, 0x76, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x77, 0x77, 0x00, 0x77, 0x76, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0E, 0x1C, 0x00, 0x77, 0x76, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7E, 0x0E, 0xFE, 0xFC,
+ 0x00, 0x00, 0x70, 0x70, 0x7E, 0x7F, 0x76, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xEE, 0xFE, 0xFC, 0xE0, 0xE0,
+ 0x00, 0x00, 0x77, 0x77, 0x00, 0x77, 0x76, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xFE, 0x7E, 0x0E, 0xFE, 0xFC,
+};
+
+const struct fb_font_desc font_italic_bold = {
+ .name = "NetSurf Italic Bold",
+ .width = 8,
+ .height = 16,
+ .encoding = "CP1252",
+ .data = fontdata_italic_bold,
+};
+
+
+static const uint32_t fontdata_regular[FONTDATAMAX] = {
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0xE4, 0xAC, 0xA4, 0xA4, 0xEE, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0xEC, 0xA2, 0xA4, 0xA8, 0xEE, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0xEC, 0xA2, 0xAC, 0xA2, 0xEC, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0xEA, 0xAA, 0xAE, 0xA2, 0xE2, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0xEE, 0xA8, 0xAE, 0xA2, 0xEE, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0xE6, 0xA8, 0xAE, 0xAA, 0xEE, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0xEE, 0xA2, 0xA4, 0xA4, 0xE4, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0xEE, 0xAA, 0xAE, 0xAA, 0xEE, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0xEE, 0xAA, 0xAE, 0xA2, 0xE2, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0xE4, 0xAA, 0xAE, 0xAA, 0xEA, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0xEC, 0xAA, 0xAC, 0xAA, 0xEC, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0xE4, 0xAA, 0xA8, 0xAA, 0xE4, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0xEC, 0xAA, 0xAA, 0xAA, 0xEC, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0xEE, 0xA8, 0xAC, 0xA8, 0xEE, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0xEE, 0xA8, 0xAC, 0xA8, 0xE8, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0x4E, 0xCA, 0x4A, 0x4A, 0xEE, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0x44, 0xCC, 0x44, 0x44, 0xEE, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0x4C, 0xC2, 0x44, 0x48, 0xEE, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0x4C, 0xC2, 0x4C, 0x42, 0xEC, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0x4A, 0xCA, 0x4E, 0x42, 0xE2, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0x4E, 0xC8, 0x4E, 0x42, 0xEE, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0x46, 0xC8, 0x4E, 0x4A, 0xEE, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0x4E, 0xC2, 0x44, 0x44, 0xE4, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0x4E, 0xCA, 0x4E, 0x4A, 0xEE, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0x4E, 0xCA, 0x4E, 0x42, 0xE2, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0x44, 0xCA, 0x4E, 0x4A, 0xEA, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0x4C, 0xCA, 0x4C, 0x4A, 0xEC, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0x44, 0xCA, 0x48, 0x4A, 0xE4, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0x4C, 0xCA, 0x4A, 0x4A, 0xEC, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0x4E, 0xC8, 0x4C, 0x48, 0xEE, 0x00, 0xFE,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0x4E, 0xC8, 0x4C, 0x48, 0xE8, 0x00, 0xFE,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x6C, 0x6C, 0x6C, 0x6C, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x6C, 0x6C, 0x6C, 0xFE, 0xFE, 0x6C, 0x6C,
+ 0xFE, 0xFE, 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x7C, 0xFE, 0xD6, 0xD0, 0xF0, 0x7C,
+ 0x1E, 0x16, 0xD6, 0xFE, 0x7C, 0x10, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xCE, 0x1C,
+ 0x38, 0x70, 0xE6, 0xC6, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x70, 0xF8, 0xD8, 0xD8, 0xF8, 0x72, 0xFE,
+ 0xDE, 0xCC, 0xCC, 0xFE, 0x7A, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x06, 0x0E, 0x1C, 0x18, 0x38, 0x30, 0x30, 0x30,
+ 0x30, 0x38, 0x18, 0x1C, 0x0E, 0x06, 0x00, 0x00,
+ 0x60, 0x70, 0x38, 0x18, 0x1C, 0x0C, 0x0C, 0x0C,
+ 0x0C, 0x1C, 0x18, 0x38, 0x70, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x6C, 0x6C, 0x38, 0xFE,
+ 0xFE, 0x38, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, 0x7E,
+ 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x38, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0E, 0x1C,
+ 0x38, 0x70, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x7C, 0xFE, 0xC6, 0xCE, 0xCE, 0xD6, 0xD6,
+ 0xE6, 0xE6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x18, 0x38, 0x78, 0x78, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x7C, 0xFE, 0xC6, 0x06, 0x06, 0x3E, 0x7C,
+ 0xE0, 0xC0, 0xC0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x7C, 0xFE, 0xC6, 0x06, 0x06, 0x3C, 0x3C,
+ 0x06, 0x06, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x04, 0x0C, 0x1C, 0x3C, 0x7C, 0xEC, 0xFE,
+ 0xFE, 0x0C, 0x0C, 0x0C, 0x0C, 0x00, 0x00, 0x00,
+ 0x00, 0xFE, 0xFE, 0xC0, 0xC0, 0xC0, 0xFC, 0xFE,
+ 0x06, 0x06, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x3C, 0x7C, 0xE0, 0xC0, 0xC0, 0xFC, 0xFE,
+ 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0xFE, 0xFE, 0xC6, 0x0E, 0x0C, 0x1C, 0x18,
+ 0x38, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x7C, 0xFE, 0xC6, 0xC6, 0xC6, 0x7C, 0x7C,
+ 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x7C, 0xFE, 0xC6, 0xC6, 0xC6, 0xFE, 0x7E,
+ 0x06, 0x06, 0x0E, 0x7C, 0x78, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00,
+ 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00,
+ 0x00, 0x18, 0x18, 0x38, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x0E, 0x1C, 0x38, 0x70, 0x70,
+ 0x38, 0x1C, 0x0E, 0x06, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x00, 0x00,
+ 0x7E, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x60, 0x70, 0x38, 0x1C, 0x0E, 0x0E,
+ 0x1C, 0x38, 0x70, 0x60, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x7C, 0xFE, 0xC6, 0xC6, 0x06, 0x1E, 0x3C,
+ 0x30, 0x30, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x7C, 0xFE, 0xC6, 0xCE, 0xDE, 0xD6, 0xD6,
+ 0xDE, 0xCC, 0xC0, 0xFC, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x7C, 0xFE, 0xC6, 0xC6, 0xC6, 0xFE, 0xFE,
+ 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00,
+ 0x00, 0xFC, 0xFE, 0xC6, 0xC6, 0xC6, 0xFC, 0xFC,
+ 0xC6, 0xC6, 0xC6, 0xFE, 0xFC, 0x00, 0x00, 0x00,
+ 0x00, 0x7C, 0xFE, 0xC6, 0xC0, 0xC0, 0xC0, 0xC0,
+ 0xC0, 0xC0, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0xF8, 0xFC, 0xCE, 0xC6, 0xC6, 0xC6, 0xC6,
+ 0xC6, 0xC6, 0xCE, 0xFC, 0xF8, 0x00, 0x00, 0x00,
+ 0x00, 0xFE, 0xFE, 0xC0, 0xC0, 0xC0, 0xF8, 0xF8,
+ 0xC0, 0xC0, 0xC0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0xFE, 0xFE, 0xC0, 0xC0, 0xC0, 0xF8, 0xF8,
+ 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00,
+ 0x00, 0x7C, 0xFE, 0xC6, 0xC0, 0xC0, 0xDE, 0xDE,
+ 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xFE, 0xFE,
+ 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00,
+ 0x00, 0x7E, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x7E, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
+ 0x0C, 0x0C, 0xCC, 0xFC, 0x78, 0x00, 0x00, 0x00,
+ 0x00, 0xC0, 0xC6, 0xCE, 0xDC, 0xF8, 0xF0, 0xE0,
+ 0xF0, 0xF8, 0xDC, 0xCE, 0xC6, 0x00, 0x00, 0x00,
+ 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0,
+ 0xC0, 0xC0, 0xC0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0xC6, 0xC6, 0xEE, 0xFE, 0xFE, 0xFE, 0xD6,
+ 0xD6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00,
+ 0x00, 0xC6, 0xC6, 0xE6, 0xE6, 0xF6, 0xF6, 0xDE,
+ 0xDE, 0xCE, 0xCE, 0xC6, 0xC6, 0x00, 0x00, 0x00,
+ 0x00, 0x7C, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6,
+ 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0xFC, 0xFE, 0xC6, 0xC6, 0xC6, 0xFE, 0xFC,
+ 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00,
+ 0x00, 0x7C, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6,
+ 0xC6, 0xD6, 0xDE, 0xFE, 0x7C, 0x06, 0x00, 0x00,
+ 0x00, 0xFC, 0xFE, 0xC6, 0xC6, 0xC6, 0xFC, 0xFC,
+ 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00,
+ 0x00, 0x7C, 0xFE, 0xC6, 0xC0, 0xC0, 0xFC, 0x7E,
+ 0x06, 0x06, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x7E, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6,
+ 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xEE,
+ 0x6C, 0x7C, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xD6,
+ 0xD6, 0xFE, 0xFE, 0xEE, 0x44, 0x00, 0x00, 0x00,
+ 0x00, 0xC6, 0xC6, 0xC6, 0xEE, 0x7C, 0x38, 0x38,
+ 0x7C, 0xEE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00,
+ 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xEE, 0x7C, 0x38,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0xFE, 0xFE, 0x0E, 0x0C, 0x1C, 0x18, 0x38,
+ 0x30, 0x70, 0x60, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x3E, 0x3E, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x3E, 0x3E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE0, 0x70,
+ 0x38, 0x1C, 0x0E, 0x06, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x7C, 0x7C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
+ 0x0C, 0x0C, 0x0C, 0x7C, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x38, 0x7C, 0xEE, 0xC6, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00,
+ 0x00, 0x00, 0x30, 0x30, 0x18, 0x08, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x7E, 0x06,
+ 0x7E, 0xFE, 0xC6, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0xFC, 0xFE, 0xC6,
+ 0xC6, 0xC6, 0xC6, 0xFE, 0xFC, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xFE, 0xC6,
+ 0xC0, 0xC0, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x06, 0x06, 0x06, 0x06, 0x7E, 0xFE, 0xC6,
+ 0xC6, 0xC6, 0xC6, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xFE, 0xC6,
+ 0xFE, 0xFE, 0xC0, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x1E, 0x3E, 0x30, 0x30, 0x30, 0x78, 0x78,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xFE, 0xC6,
+ 0xC6, 0xC6, 0xC6, 0xFE, 0x7E, 0x06, 0x7E, 0x7C,
+ 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xDC, 0xFE, 0xE6,
+ 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x38, 0x18,
+ 0x18, 0x18, 0x18, 0x3C, 0x3C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0C, 0x0C, 0x00, 0x1C, 0x1C, 0x0C,
+ 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x7C, 0x78,
+ 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0xC6, 0xCE, 0xDC,
+ 0xF8, 0xF8, 0xDC, 0xCE, 0xC6, 0x00, 0x00, 0x00,
+ 0x00, 0x38, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0xFE, 0xFE,
+ 0xD6, 0xD6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0xFE, 0xE6,
+ 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xFE, 0xC6,
+ 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFE, 0xC6,
+ 0xC6, 0xC6, 0xC6, 0xFE, 0xFC, 0xC0, 0xC0, 0xC0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xFE, 0xC6,
+ 0xC6, 0xC6, 0xC6, 0xFE, 0x7E, 0x06, 0x07, 0x07,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xDE, 0xFE, 0xE0,
+ 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xFE, 0xC0,
+ 0xFC, 0x7C, 0x06, 0xFE, 0xFC, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x30, 0x30, 0x30, 0x7C, 0xFC, 0x30,
+ 0x30, 0x30, 0x30, 0x3E, 0x1E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6,
+ 0xC6, 0xC6, 0xCE, 0xFE, 0x76, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6,
+ 0xC6, 0xEE, 0x7C, 0x38, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6,
+ 0xD6, 0xD6, 0xFE, 0xFE, 0x6C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xEE,
+ 0x7C, 0x7C, 0xEE, 0xC6, 0xC6, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6,
+ 0xC6, 0xC6, 0xC6, 0xFE, 0x7E, 0x06, 0xFE, 0xFC,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x0E,
+ 0x3C, 0x78, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x0E, 0x1E, 0x18, 0x18, 0x18, 0x70, 0x70,
+ 0x18, 0x18, 0x18, 0x1E, 0x0E, 0x00, 0x00, 0x00,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00,
+ 0x00, 0x70, 0x78, 0x18, 0x18, 0x18, 0x0E, 0x0E,
+ 0x18, 0x18, 0x18, 0x78, 0x70, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x76, 0xFE, 0xDC, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
+ 0x00, 0xEE, 0x28, 0x4C, 0x48, 0x48, 0x00, 0xFE,
+ 0x00, 0x18, 0x3C, 0x66, 0x60, 0xFC, 0x60, 0xF8,
+ 0x60, 0x60, 0x66, 0x3C, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x38, 0x38, 0x6C, 0x54, 0xF6, 0xEE,
+ 0x6C, 0x7C, 0x28, 0x38, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x18, 0x08, 0x10, 0x00,
+ 0x00, 0x1E, 0x3E, 0x30, 0x30, 0x30, 0x78, 0x78,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0xF0, 0x60, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x66, 0x66, 0x22, 0x44, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xDB, 0xDB, 0x00, 0x00, 0x00,
+ 0x00, 0x18, 0x18, 0x18, 0x7E, 0x7E, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x18, 0x18, 0x18, 0x7E, 0x7E, 0x18, 0x7E,
+ 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x7C, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xC2, 0xC6, 0x0C,
+ 0x18, 0x30, 0x60, 0xDB, 0x9B, 0x00, 0x00, 0x00,
+ 0xC6, 0x7C, 0x00, 0x7C, 0xFE, 0xC6, 0xC0, 0xFC,
+ 0x7E, 0x06, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x1C,
+ 0x38, 0x30, 0x38, 0x1C, 0x0C, 0x00, 0x00, 0x00,
+ 0x00, 0x7F, 0xFF, 0xCC, 0xCC, 0xCC, 0xCF, 0xCF,
+ 0xCC, 0xCC, 0xCC, 0xFF, 0x7F, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x38, 0x38, 0x6C, 0x54, 0xF6, 0xEE,
+ 0x6C, 0x7C, 0x28, 0x38, 0x10, 0x00, 0x00, 0x00,
+ 0xC6, 0x7C, 0x00, 0xFE, 0xFE, 0x06, 0x0C, 0x18,
+ 0x30, 0x60, 0xC0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x38, 0x38, 0x6C, 0x54, 0xF6, 0xEE,
+ 0x6C, 0x7C, 0x28, 0x38, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x38, 0x38, 0x6C, 0x54, 0xF6, 0xEE,
+ 0x6C, 0x7C, 0x28, 0x38, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x10, 0x20, 0x30, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x30, 0x30, 0x10, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x24, 0x48, 0x6C, 0x6C, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x36, 0x36, 0x12, 0x24, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x7E,
+ 0x7E, 0x7E, 0x7E, 0x3C, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x32, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xF1, 0xFB, 0x5F, 0x55, 0x51, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xC6, 0x6C, 0x38, 0x00, 0x7E, 0xFE, 0xC0,
+ 0xFC, 0x7C, 0x06, 0xFE, 0xFC, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x38,
+ 0x1C, 0x0C, 0x1C, 0x38, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x6C, 0xFE, 0xDA,
+ 0xDE, 0xDE, 0xD8, 0xFE, 0x6E, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x38, 0x38, 0x6C, 0x54, 0xF6, 0xEE,
+ 0x6C, 0x7C, 0x28, 0x38, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0xC6, 0x6C, 0x38, 0x00, 0xFE, 0xFE, 0x0E,
+ 0x3C, 0x78, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x6C, 0x00, 0xC6, 0xC6, 0xC6, 0xEE, 0x7C,
+ 0x38, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x10, 0x7C, 0xFE, 0xD6,
+ 0xD0, 0xD0, 0xD6, 0xFE, 0x7C, 0x10, 0x10, 0x00,
+ 0x00, 0x3C, 0x7E, 0x66, 0x60, 0x60, 0xF8, 0xF8,
+ 0x60, 0x60, 0xE6, 0xFE, 0xDC, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x3C, 0x7E,
+ 0x66, 0x66, 0x7E, 0x3C, 0x66, 0x66, 0x00, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E,
+ 0x18, 0x7E, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00,
+ 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x3C, 0x7C, 0x60, 0x60, 0x3C, 0x7E, 0x66,
+ 0x7E, 0x3C, 0x06, 0x06, 0x3E, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x3C, 0x7E, 0xC3, 0x99, 0xBD, 0xA5, 0xA1,
+ 0xA5, 0xBD, 0x99, 0xC3, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x70, 0x08, 0x78, 0x88, 0x78, 0x00, 0xF8,
+ 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36,
+ 0x6C, 0xD8, 0xD8, 0x6C, 0x36, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x7E, 0x7E, 0x06, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x3C, 0x7E, 0xC3, 0xB9, 0xBD, 0xA5, 0xB9,
+ 0xB9, 0xA5, 0xA5, 0xC3, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x78, 0xFC, 0xCC, 0xFC, 0x78, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, 0x7E, 0x18,
+ 0x18, 0x00, 0x7E, 0x7E, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xF0, 0xF8, 0x18, 0x78, 0xF0, 0xC0,
+ 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xF0, 0xF8, 0x18, 0x30, 0x18, 0xF8,
+ 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x7E, 0x7C, 0x60, 0x60, 0xC0,
+ 0x00, 0x00, 0x00, 0x7F, 0xDB, 0xDB, 0xDB, 0x7B,
+ 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x18, 0x1C, 0x0C, 0x1C, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x60, 0xE0, 0x60, 0x60, 0x60, 0xF0,
+ 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x70, 0xF8, 0x88, 0xF8, 0x70, 0x00, 0xF8,
+ 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8,
+ 0x6C, 0x36, 0x36, 0x6C, 0xD8, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x40, 0xC0, 0x42, 0x46, 0xEC, 0x18,
+ 0x30, 0x64, 0xCC, 0x94, 0x3E, 0x04, 0x04, 0x00,
+ 0x00, 0x00, 0x40, 0xC0, 0x42, 0x46, 0xEC, 0x18,
+ 0x30, 0x60, 0xDC, 0x82, 0x0C, 0x10, 0x1E, 0x00,
+ 0x00, 0x00, 0xE0, 0x10, 0x62, 0x16, 0xEC, 0x18,
+ 0x30, 0x64, 0xCC, 0x96, 0x3E, 0x04, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18,
+ 0x78, 0xF0, 0xC0, 0xC6, 0xC6, 0xFE, 0x7C, 0x00,
+ 0x00, 0x60, 0x30, 0x00, 0x10, 0x38, 0x6C, 0xC6,
+ 0xFE, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00,
+ 0x00, 0x0C, 0x18, 0x00, 0x10, 0x38, 0x6C, 0xC6,
+ 0xFE, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00,
+ 0x00, 0x38, 0x6C, 0x44, 0x10, 0x38, 0x6C, 0xC6,
+ 0xFE, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00,
+ 0x00, 0x76, 0xDC, 0x00, 0x10, 0x38, 0x6C, 0xC6,
+ 0xFE, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00,
+ 0x6C, 0x6C, 0x00, 0x10, 0x38, 0x6C, 0xC6, 0xFE,
+ 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00,
+ 0x00, 0x38, 0x44, 0x38, 0x38, 0x6C, 0xC6, 0xFE,
+ 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00,
+ 0x00, 0x1F, 0x3F, 0x7C, 0xEC, 0xCC, 0xFE, 0xFE,
+ 0xCC, 0xCC, 0xCC, 0xCF, 0xCF, 0x00, 0x00, 0x00,
+ 0x00, 0x7C, 0xFE, 0xC6, 0xC0, 0xC0, 0xC0, 0xC0,
+ 0xC0, 0xC0, 0xC6, 0xFE, 0x7C, 0x0E, 0x66, 0x3C,
+ 0x00, 0x30, 0x18, 0x00, 0xFE, 0xFE, 0xC0, 0xF0,
+ 0xF0, 0xC0, 0xC0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x0C, 0x18, 0x00, 0xFE, 0xFE, 0xC0, 0xF0,
+ 0xF0, 0xC0, 0xC0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x38, 0x6C, 0x00, 0xFE, 0xFE, 0xC0, 0xF0,
+ 0xF0, 0xC0, 0xC0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x6C, 0x6C, 0x00, 0xFE, 0xFE, 0xC0, 0xC0, 0xF0,
+ 0xF0, 0xC0, 0xC0, 0xFE, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x30, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x0C, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x18, 0x24, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x66, 0x66, 0x00, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x78, 0x7C, 0x6E, 0x66, 0x66, 0xF6,
+ 0x66, 0x66, 0x6E, 0x7C, 0x78, 0x00, 0x00, 0x00,
+ 0x00, 0x76, 0xDC, 0x00, 0xC6, 0xC6, 0xE6, 0xF6,
+ 0xFE, 0xDE, 0xCE, 0xC6, 0xC6, 0x00, 0x00, 0x00,
+ 0x00, 0x30, 0x18, 0x00, 0x7C, 0xFE, 0xC6, 0xC6,
+ 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x0C, 0x18, 0x00, 0x7C, 0xFE, 0xC6, 0xC6,
+ 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x38, 0x6C, 0x00, 0x7C, 0xFE, 0xC6, 0xC6,
+ 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x76, 0xDC, 0x00, 0x7C, 0xFE, 0xC6, 0xC6,
+ 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x6C, 0x00, 0x7C, 0xFE, 0xC6, 0xC6, 0xC6,
+ 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xEE, 0x7C,
+ 0x38, 0x38, 0x7C, 0xEE, 0xC6, 0x00, 0x00, 0x00,
+ 0x00, 0x7E, 0xFE, 0xC6, 0xC6, 0xCE, 0xCE, 0xD6,
+ 0xD6, 0xE6, 0xE6, 0xFE, 0x7C, 0x80, 0x00, 0x00,
+ 0x00, 0x30, 0x18, 0x00, 0xC6, 0xC6, 0xC6, 0xC6,
+ 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x0C, 0x18, 0x00, 0xC6, 0xC6, 0xC6, 0xC6,
+ 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x38, 0x6C, 0x00, 0xC6, 0xC6, 0xC6, 0xC6,
+ 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x6C, 0x6C, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6,
+ 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x0C, 0x18, 0x00, 0x66, 0x66, 0x66, 0x7E,
+ 0x3C, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x60, 0x60, 0x7C, 0x7E, 0x66, 0x66,
+ 0x7E, 0x7C, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00,
+ 0x00, 0x3C, 0x7E, 0x66, 0x66, 0x66, 0x7E, 0x7C,
+ 0x66, 0x66, 0x66, 0x7E, 0x7C, 0xE0, 0xC0, 0x00,
+ 0x00, 0x00, 0x30, 0x18, 0x00, 0x7E, 0xFE, 0xC6,
+ 0xC6, 0xCE, 0xCE, 0xFE, 0x76, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x30, 0x00, 0x7E, 0xFE, 0xC6,
+ 0xC6, 0xC6, 0xCE, 0xFE, 0x76, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x38, 0x6C, 0x00, 0x7E, 0xFE, 0xC6,
+ 0xC6, 0xC6, 0xCE, 0xFE, 0x76, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x76, 0xDC, 0x00, 0x7E, 0xFE, 0xC6,
+ 0xC6, 0xC6, 0xCE, 0xFE, 0x76, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x6C, 0x6C, 0x00, 0x7E, 0xFE, 0xC6,
+ 0xC6, 0xC6, 0xCE, 0xFE, 0x76, 0x00, 0x00, 0x00,
+ 0x00, 0x38, 0x6C, 0x38, 0x00, 0x7E, 0xFE, 0xC6,
+ 0xC6, 0xC6, 0xCE, 0xFE, 0x76, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x7E, 0x1A,
+ 0x3E, 0x7E, 0xD8, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xFE,
+ 0xC6, 0xC0, 0xC6, 0xFE, 0x7C, 0x18, 0x7C, 0x78,
+ 0x00, 0x00, 0x30, 0x18, 0x00, 0x7C, 0xFE, 0xC6,
+ 0xFE, 0xFE, 0xC0, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x30, 0x00, 0x7C, 0xFE, 0xC6,
+ 0xFE, 0xFE, 0xC0, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x38, 0x6C, 0x00, 0x7C, 0xFE, 0xC6,
+ 0xFE, 0xFE, 0xC0, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x6C, 0x6C, 0x00, 0x7C, 0xFE, 0xC6,
+ 0xFE, 0xFE, 0xC0, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x30, 0x18, 0x00, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0C, 0x18, 0x00, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x18, 0x3C, 0x66, 0x00, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0x00, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x6C, 0x7C, 0xF8, 0xDC, 0x7C, 0xFE, 0xC6,
+ 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x76, 0xFE, 0xDC, 0x00, 0xFC, 0xFE, 0xC6,
+ 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x60, 0x30, 0x00, 0x7C, 0xFE, 0xC6,
+ 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x30, 0x00, 0x7C, 0xFE, 0xC6,
+ 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x38, 0x6C, 0x00, 0x7C, 0xFE, 0xC6,
+ 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x76, 0xFE, 0xDC, 0x00, 0x7C, 0xFE, 0xC6,
+ 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x6C, 0x6C, 0x00, 0x7C, 0xFE, 0xC6,
+ 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7E,
+ 0x7E, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x7C, 0xFE, 0xCE,
+ 0xD6, 0xD6, 0xE6, 0xFE, 0x7C, 0x80, 0x00, 0x00,
+ 0x00, 0x00, 0x60, 0x30, 0x00, 0xC6, 0xC6, 0xC6,
+ 0xC6, 0xC6, 0xC6, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x30, 0x00, 0xC6, 0xC6, 0xC6,
+ 0xC6, 0xC6, 0xC6, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x38, 0x6C, 0x00, 0xC6, 0xC6, 0xC6,
+ 0xC6, 0xC6, 0xC6, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x6C, 0x6C, 0x00, 0xC6, 0xC6, 0xC6,
+ 0xC6, 0xC6, 0xC6, 0xFE, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0C, 0x18, 0x00, 0xC6, 0xC6, 0xC6,
+ 0xC6, 0xC6, 0xC6, 0xFE, 0x7E, 0x06, 0xFC, 0xF8,
+ 0x00, 0x00, 0x60, 0x60, 0x60, 0x7C, 0x7E, 0x66,
+ 0x66, 0x66, 0x66, 0x7E, 0x7C, 0x60, 0x60, 0x60,
+ 0x00, 0x00, 0x6C, 0x6C, 0x00, 0xC6, 0xC6, 0xC6,
+ 0xC6, 0xC6, 0xC6, 0xFE, 0x7E, 0x06, 0xFE, 0xFC,
+};
+
+const struct fb_font_desc font_regular = {
+ .name = "NetSurf Regular",
+ .width = 8,
+ .height = 16,
+ .encoding = "CP1252",
+ .data = fontdata_regular,
+};
+
+#endif
diff --git a/frontends/atari/plot/font_internal.h b/frontends/atari/plot/font_internal.h
new file mode 100644
index 000000000..9bfbbedef
--- /dev/null
+++ b/frontends/atari/plot/font_internal.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2008 Vincent Sanders <vince@simtec.co.uk>
+ * Copyright 2011 Ole Loots <ole@monochrom.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/>.
+ */
+
+#ifdef WITH_INTERNAL_FONT_DRIVER
+#ifndef FONT_PLOTTER_INTERNAL
+#define FONT_PLOTTER_INTERNAL
+
+#include "atari/plot/plot.h"
+
+int ctor_font_plotter_internal( FONT_PLOTTER self );
+
+struct fb_font_desc {
+ const char *name;
+ int width, height;
+ const char *encoding;
+ const uint32_t *data;
+};
+
+
+#endif
+#endif
diff --git a/frontends/atari/plot/font_vdi.c b/frontends/atari/plot/font_vdi.c
new file mode 100644
index 000000000..ef5499207
--- /dev/null
+++ b/frontends/atari/plot/font_vdi.c
@@ -0,0 +1,310 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.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/>.
+ */
+
+#ifdef WITH_VDI_FONT_DRIVER
+
+#include <mt_gemx.h>
+
+#include "atari/plot/plot.h"
+#include "atari/plot/font_vdi.h"
+
+#include "utils/utf8.h"
+#include "utils/log.h"
+
+#include "atari/encoding.h"
+
+
+//static char * lstr = NULL;
+
+static int dtor( FONT_PLOTTER self );
+static int str_width( FONT_PLOTTER self,const plot_font_style_t *fstyle, const char * str, size_t length, int * width );
+static int str_split( FONT_PLOTTER self, const plot_font_style_t *fstyle,const char *string,
+ size_t length,int x, size_t *char_offset, int *actual_x );
+static int pixel_pos( FONT_PLOTTER self, const plot_font_style_t *fstyle,const char *string,
+ size_t length,int x, size_t *char_offset, int *actual_x );
+static int text( FONT_PLOTTER self, int x, int y, const char *text, size_t length, const plot_font_style_t *fstyle );
+
+static bool init = false;
+static int vdih;
+
+extern struct s_vdi_sysinfo vdi_sysinfo;
+
+static inline void atari_to_vdi_str(char *lstr, int length)
+{
+ int i, z;
+
+ for (i=z=0; i<length; ) {
+ if (((char)lstr[i]==(char)0xC2) && ((char)lstr[i+1] == (char)0xA0)) {
+ lstr[z] = ' ';
+ lstr[z+1] = ' ';
+ i=i+2;
+ z=z+2;
+ }
+ else {
+ lstr[z] = lstr[i];
+ i++;
+ z++;
+ }
+ }
+}
+
+int ctor_font_plotter_vdi( FONT_PLOTTER self )
+{
+ self->dtor = dtor;
+ self->str_width = str_width;
+ self->str_split = str_split;
+ self->pixel_pos = pixel_pos;
+ self->text = text;
+ LOG("%s: %s\n", (char *)__FILE__, __FUNCTION__);
+ if( !init ) {
+ vdih = self->vdi_handle;
+ }
+ init = true;
+ return( 1 );
+}
+
+static int dtor( FONT_PLOTTER self )
+{
+ return( 1 );
+}
+
+static int str_width( FONT_PLOTTER self,const plot_font_style_t *fstyle, const char * str,
+ size_t length, int * width )
+{
+ short cw, ch, cellw, cellh;
+ short pxsize;
+ short fx=0;
+ char * lstr = NULL;
+
+ utf8_to_local_encoding(str, length, &lstr);
+ assert( lstr != NULL );
+ int slen = strlen(lstr);
+
+
+ atari_to_vdi_str(lstr, slen);
+
+ if( fstyle->flags & FONTF_ITALIC )
+ fx |= 4;
+ if( fstyle->flags & FONTF_OBLIQUE )
+ fx |= 16;
+ if( fstyle->weight > 450 )
+ fx |= 1;
+ vst_effects( self->vdi_handle, fx );
+ /* TODO: replace 90 with global dpi setting */
+ //pxsize = ceil( (fstyle->size/FONT_SIZE_SCALE) * 90 / 72 );
+ //vst_height( self->vdi_handle, pxsize ,&cw, &ch, &cellw, &cellh);
+ pxsize = ceil( (fstyle->size/FONT_SIZE_SCALE) * 90 );
+ vst_point( self->vdi_handle, pxsize, &cw, &ch, &cellw, &cellh);
+/*
+ if(slen != utf8_bounded_length(str, length)){
+ printf("sl: %d, utl: %d\n ", slen, utf8_bounded_length(str, length));
+ printf("s: %s // %s\n", str, lstr );
+ }*/
+
+
+ *width = slen * cellw;
+ free((void*)lstr);
+ return( 0 );
+}
+
+static int str_split( FONT_PLOTTER self, const plot_font_style_t * fstyle, const char *string,
+ size_t length,int x, size_t *char_offset, int *actual_x )
+{
+ short cw, ch, cellw, cellh;
+ short pxsize;
+ short fx=0;
+ char *lstr = NULL;
+ size_t slen = 0;
+ int last_space_x = 0;
+ int last_space_idx = 0;
+ size_t nxtchr = 0;
+
+ utf8_to_local_encoding(string, length, &lstr );
+ assert( lstr != NULL );
+ slen = strlen(lstr);
+
+
+ atari_to_vdi_str(lstr, slen);
+
+ if( fstyle->flags & FONTF_ITALIC )
+ fx |= 4;
+ if( fstyle->flags & FONTF_OBLIQUE )
+ fx |= 16;
+ if( fstyle->weight > 450 )
+ fx |= 1;
+ vst_effects( self->vdi_handle, fx );
+ //pxsize = ceil( (fstyle->size/FONT_SIZE_SCALE) * 90 / 72 );
+ //vst_height( self->vdi_handle, pxsize ,&cw, &ch, &cellw, &cellh);
+
+ pxsize = ceil( (fstyle->size/FONT_SIZE_SCALE) * 90 );
+ vst_point( self->vdi_handle, pxsize, &cw, &ch, &cellw, &cellh);
+ *actual_x = 0;
+ //*char_offset = 0;
+ while (nxtchr < slen) {
+ if( lstr[nxtchr] == ' ' ) {
+ last_space_x = *actual_x;
+ last_space_idx = nxtchr;
+ }
+ *actual_x += cellw;
+ if (*actual_x > x && last_space_idx != 0) {
+ *actual_x = last_space_x;
+ *char_offset = last_space_idx;
+ //printf("at: %s\n", lstr);
+ return(0);
+ }
+
+ nxtchr++;
+ }
+ if(nxtchr >= length){
+ nxtchr = length-1;
+ }
+
+ *char_offset = nxtchr;
+
+// for( i=0; i<slen; i++) {
+// if( lstr[i] == ' ' ) {
+// last_space_x = *actual_x;
+// last_space_idx = cpos;
+// }
+// if( *actual_x > x ) {
+// *actual_x = last_space_x;
+// *char_offset = last_space_idx;
+// return true;
+// }
+// *actual_x += cellw;
+// cpos++;
+// }
+// *char_offset = cpos;
+ free( (void*)lstr );
+ return( 0 );
+}
+
+static int pixel_pos( FONT_PLOTTER self, const plot_font_style_t * fstyle,const char *string,
+ size_t length,int x, size_t *char_offset, int *actual_x )
+{
+ short cw, ch, cellw, cellh;
+ short pxsize=0;
+ short fx=0;
+
+ char *lstr = NULL;
+ int i=0;
+ utf8_to_local_encoding(string, length, &lstr );
+ assert( lstr != NULL );
+ int slen = strlen(lstr);
+
+ atari_to_vdi_str(lstr, slen);
+
+ if( fstyle->flags & FONTF_ITALIC )
+ fx |= 4;
+ if( fstyle->flags & FONTF_OBLIQUE )
+ fx |= 16;
+ if( fstyle->weight > 450 )
+ fx |= 1;
+ vst_effects(self->vdi_handle, fx);
+ pxsize = ceil( (fstyle->size/FONT_SIZE_SCALE) * 90 / 72 );
+ vst_height( self->vdi_handle, pxsize ,&cw, &ch, &cellw, &cellh);
+ *actual_x = 0;
+ *char_offset = 0;
+ for( i=0; i<slen; i++) {
+ *actual_x += cellw;
+ if( *actual_x > x) {
+ *actual_x -= cellw;
+ *char_offset = i;
+ break;
+ }
+ }
+ free((void*)lstr);
+ lstr = NULL;
+ return( 0 );
+}
+
+static inline void vst_rgbcolor( short vdih, uint32_t cin )
+{
+#ifdef WITH_8BPP_SUPPORT
+ if( vdi_sysinfo.scr_bpp > 8 ) {
+#endif
+ //unsigned short c[4];
+ RGB1000 c;
+
+ rgb_to_vdi1000( (unsigned char*)&cin, &c );
+ vs_color( vdih, OFFSET_CUSTOM_COLOR, (unsigned short*)&c);
+ vst_color( vdih, OFFSET_CUSTOM_COLOR );
+#ifdef WITH_8BPP_SUPPORT
+ } else {
+ if( vdi_sysinfo.scr_bpp >= 4 )
+ vst_color( vdih, RGB_TO_VDI(cin) );
+ else
+ vst_color( vdih, BLACK );
+ }
+#endif
+}
+
+static int text( FONT_PLOTTER self, int x, int y, const char *text, size_t length,
+ const plot_font_style_t *fstyle )
+{
+ /* todo: either limit the string to max 80 chars, or use v_ftext instead of v_gtext */
+ short cw, ch, cellw, cellh;
+ short pxsize=8;
+ short fx=0;
+ GRECT canvas;
+ char *lstr = NULL;
+ assert( utf8_to_local_encoding(text, length, &lstr) == NSERROR_OK);
+ assert( lstr != NULL );
+
+ int slen = strlen(lstr);
+ if(slen > 800){
+ lstr[800]=0;
+ }
+
+
+ atari_to_vdi_str(lstr, slen);
+
+ if( fstyle->flags & FONTF_ITALIC )
+ fx |= 4;
+ if( fstyle->flags & FONTF_OBLIQUE )
+ fx |= 4;
+ if( fstyle->weight > 450 )
+ fx |= 1;
+
+ /* TODO: netsurf uses 90 as default dpi ( somewhere defined in libcss),
+ use that value or pass it as arg, to reduce netsurf dependency */
+ //pxsize = ceil( (fstyle->size/FONT_SIZE_SCALE) * 90 / 72 );
+ pxsize = ceil( (fstyle->size/FONT_SIZE_SCALE) * 90 / 72 );
+
+ plot_get_dimensions(&canvas);
+ x += canvas.g_x;
+ y += canvas.g_y;
+ vst_effects( self->vdi_handle, fx );
+ vst_alignment(vdih, 0, 0, &cw, &ch );
+ vst_point( self->vdi_handle, pxsize, &cw, &ch, &cellw, &cellh);
+ //vst_height( self->vdi_handle, pxsize, &cw, &ch, &cellw, &cellh);
+ vswr_mode( self->vdi_handle, MD_TRANS );
+ vst_rgbcolor(self->vdi_handle, fstyle->foreground);
+
+ if( atari_sysinfo.gdos_FSMC ){
+ //printf("\nftext\n");
+ v_ftext( self->vdi_handle, x, y, (char*)lstr );
+ } else {
+ //printf("\ngtext\n");
+ v_gtext( self->vdi_handle, x, y, (char*)lstr );
+ }
+ free( lstr );
+ return( 0 );
+}
+
+#endif
diff --git a/frontends/atari/plot/font_vdi.h b/frontends/atari/plot/font_vdi.h
new file mode 100644
index 000000000..3a1fdb54b
--- /dev/null
+++ b/frontends/atari/plot/font_vdi.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.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/>.
+ */
+
+#ifdef WITH_VDI_FONT_DRIVER
+#ifndef FONT_PLOTTER_VDI
+#define FONT_PLOTTER_VDI
+
+int ctor_font_plotter_vdi( FONT_PLOTTER self );
+
+#endif
+#endif
diff --git a/frontends/atari/plot/fontplot.c b/frontends/atari/plot/fontplot.c
new file mode 100644
index 000000000..9f0edd9a4
--- /dev/null
+++ b/frontends/atari/plot/fontplot.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.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 <assert.h>
+#include <stdlib.h>
+#include <mt_gem.h>
+
+#include "desktop/mouse.h"
+#include "desktop/plot_style.h"
+
+#include "atari/bitmap.h"
+#include "atari/plot/fontplot.h"
+
+const struct s_font_driver_table_entry font_driver_table[] =
+{
+#ifdef WITH_VDI_FONT_DRIVER
+ {"vdi", ctor_font_plotter_vdi, 0},
+#endif
+#ifdef WITH_FREETYPE_FONT_DRIVER
+ {"freetype", ctor_font_plotter_freetype, 0},
+#endif
+#ifdef WITH_INTERNAL_FONT_DRIVER
+ {"internal", ctor_font_plotter_internal, 0},
+#endif
+ {(char*)NULL, NULL, 0}
+};
+
+void dump_font_drivers(void)
+{
+ int i = 0;
+ while( font_driver_table[i].name != NULL ) {
+ printf("%s -> flags: %d\n", font_driver_table[i].name,
+ font_driver_table[i].flags);
+ i++;
+ }
+}
+
+
+/**
+ * Create an new text plotter object.
+ *
+ * Available: "vdi", "freetype", "internal"
+ *
+ * \param vdihandle the vdi handle to act upon,
+ * \param name selector ID (string) of the font plotter.
+ * \param flags configration flags of the plotter, available flags:
+ * FONTPLOT_FLAG_MONOGLYPH - Enable 1 bit font plotting
+ * \param error set to != 0 when errors occur
+ * \return the new font plotter instance on success, or NULL on failure.
+ */
+FONT_PLOTTER new_font_plotter(int vdihandle, char * name, unsigned long flags,
+ int * error)
+{
+ int i=0;
+ int res = 0-ERR_PLOTTER_NOT_AVAILABLE;
+ FONT_PLOTTER fplotter = NULL;
+
+ /* set the default error code: */
+ *error = 0-ERR_PLOTTER_NOT_AVAILABLE;
+
+
+ /* Find the selector string in the font plotter table, */
+ /* and bail out when the font plotter is not available: */
+ for (i = 0; font_driver_table[i].name != NULL; i++) {
+
+ /* found selector in driver table? */
+ if (strcmp(name, font_driver_table[i].name) == 0) {
+
+ /* allocate the font plotter instance: */
+ fplotter = (FONT_PLOTTER)malloc(sizeof(struct s_font_plotter));
+ if (fplotter == NULL) {
+ *error = 0-ERR_NO_MEM;
+ return(NULL);
+ }
+
+ /* Initialize the font plotter with the requested settings: */
+ memset( fplotter, 0, sizeof(FONT_PLOTTER));
+ fplotter->vdi_handle = vdihandle;
+ fplotter->name = name;
+ fplotter->flags = 0;
+ fplotter->flags |= flags;
+
+ /* Execute the constructor: */
+ assert(font_driver_table[i].ctor);
+ res = font_driver_table[i].ctor(fplotter);
+
+ /* success? */
+ if (res < 0) {
+ /* NO success! */
+ free(fplotter);
+ *error = res;
+ return(NULL);
+ }
+ *error = 0;
+ break;
+ }
+ }
+
+ return(fplotter);
+}
+
+/*
+ Free an font plotter
+*/
+int delete_font_plotter(FONT_PLOTTER p)
+{
+ if (p) {
+ p->dtor(p);
+ free(p);
+ p = NULL;
+ }
+ else
+ return(-1);
+ return(0);
+}
+
diff --git a/frontends/atari/plot/fontplot.h b/frontends/atari/plot/fontplot.h
new file mode 100644
index 000000000..6690bff2c
--- /dev/null
+++ b/frontends/atari/plot/fontplot.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.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 FONT_PLOT_H
+#define FONT_PLOT_H
+
+typedef struct s_font_plotter * FONT_PLOTTER;
+
+struct s_font_driver_table_entry
+{
+ const char * name;
+ int (*ctor)( FONT_PLOTTER self );
+ int flags;
+};
+
+/* declaration of font plotter member functions: (_fpmf_ prefix) */
+typedef int (*_fpmf_str_width)( FONT_PLOTTER self, const plot_font_style_t *fstyle,
+ const char * str, size_t length, int * width);
+typedef int (*_fpmf_str_split)( FONT_PLOTTER self, const plot_font_style_t *fstyle,
+ const char *string, size_t length,
+ int x, size_t *char_offset, int *actual_x);
+typedef int (*_fpmf_pixel_pos)( FONT_PLOTTER self, const plot_font_style_t *fstyle,
+ const char *string, size_t length,
+ int x, size_t *char_offset, int *actual_x);
+typedef int (*_fpmf_text)( FONT_PLOTTER self, int x, int y, const char *text,
+ size_t length, const plot_font_style_t *fstyle);
+
+typedef void (*_fpmf_draw_glyph)(FONT_PLOTTER self, GRECT * clip, GRECT * loc,
+ uint8_t * pixdata, int pitch, uint32_t colour);
+typedef int (*_fpmf_dtor)( FONT_PLOTTER self );
+
+
+/* prototype of the font plotter "object" */
+struct s_font_plotter
+{
+ char * name;
+ int flags;
+ int vdi_handle;
+ void * priv_data;
+
+ _fpmf_str_width str_width;
+ _fpmf_str_split str_split;
+ _fpmf_pixel_pos pixel_pos;
+ _fpmf_text text;
+ _fpmf_draw_glyph draw_glyph;
+ _fpmf_dtor dtor;
+};
+
+
+FONT_PLOTTER plot_get_text_plotter(void);
+/* Set the font plotting engine.
+*/
+void plot_set_text_plotter(FONT_PLOTTER font_plotter);
+void dump_font_drivers(void);
+FONT_PLOTTER new_font_plotter( int vdihandle, char * name, unsigned long flags,
+ int * error);
+int delete_font_plotter( FONT_PLOTTER p );
+
+#ifdef WITH_VDI_FONT_DRIVER
+ #include "atari/plot/font_vdi.h"
+#endif
+#ifdef WITH_INTERNAL_FONT_DRIVER
+ #include "atari/plot/font_internal.h"
+#endif
+#ifdef WITH_FREETYPE_FONT_DRIVER
+ #include "atari/plot/font_freetype.h"
+#endif
+
+
+
+#endif
diff --git a/frontends/atari/plot/plot.c b/frontends/atari/plot/plot.c
new file mode 100644
index 000000000..45e4cead2
--- /dev/null
+++ b/frontends/atari/plot/plot.c
@@ -0,0 +1,2247 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.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 <sys/types.h>
+#include <stdint.h>
+#include <string.h>
+#include <limits.h>
+#include <math.h>
+#include <stdbool.h>
+#include <mt_gem.h>
+#include <mint/osbind.h>
+
+#include "utils/log.h"
+#include "utils/utf8.h"
+#include "utils/utils.h"
+#include "image/bitmap.h"
+#include "desktop/plotters.h"
+#include "desktop/mouse.h"
+
+#include "atari/gui.h"
+#include "atari/osspec.h"
+#include "atari/misc.h"
+#include "atari/bitmap.h"
+#include "utils/nsoption.h"
+#include "atari/plot/eddi.h"
+#include "atari/plot/fontplot.h"
+#include "atari/plot/plot.h"
+
+void vq_scrninfo(VdiHdl handle, short *work_out);
+
+struct s_view {
+ short x; /* drawing (screen) offset x */
+ short y; /* drawing (screen) offset y */
+ short w; /* width of buffer, not in sync with vis_w */
+ short h; /* height of buffer, not in sync with vis_w */
+ short vis_x; /* visible rectangle of the screen buffer */
+ short vis_y; /* coords are relative to plot location */
+ short vis_w; /* clipped to screen dimensions */
+ short vis_h; /* visible width */
+ struct rect abs_clipping; /* The toplevel clipping rectangle */
+ struct rect clipping; /* actual clipping rectangle */
+ float scale;
+};
+
+/*
+* Capture the screen at x,y location
+* param self instance
+* param x absolute screen coords
+* param y absolute screen coords
+* param w width
+* param h height
+*
+* This creates an snapshot in RGBA format (NetSurf's native format)
+*
+*/
+static struct bitmap * snapshot_create(int x, int y, int w, int h);
+
+/* Garbage collection of the snapshot routine */
+/* this should be called after you are done with the data returned by snapshot_create */
+/* don't access the screenshot after you called this function */
+static void snapshot_suspend(void);
+
+/* destroy memory used by screenshot */
+static void snapshot_destroy(void);
+
+#ifdef WITH_8BPP_SUPPORT
+static unsigned short sys_pal[256][3]; /*RGB*/
+static unsigned short pal[256][3]; /*RGB*/
+static char rgb_lookup[256][4];
+short web_std_colors[6] = {0, 51, 102, 153, 204, 255};
+
+unsigned short vdi_web_pal[216][3] = {
+ {0x000,0x000,0x000}, {0x0c8,0x000,0x000}, {0x190,0x000,0x000}, {0x258,0x000,0x000}, {0x320,0x000,0x000}, {0x3e8,0x000,0x000},
+ {0x000,0x0c8,0x000}, {0x0c8,0x0c8,0x000}, {0x190,0x0c8,0x000}, {0x258,0x0c8,0x000}, {0x320,0x0c8,0x000}, {0x3e8,0x0c8,0x000},
+ {0x000,0x190,0x000}, {0x0c8,0x190,0x000}, {0x190,0x190,0x000}, {0x258,0x190,0x000}, {0x320,0x190,0x000}, {0x3e8,0x190,0x000},
+ {0x000,0x258,0x000}, {0x0c8,0x258,0x000}, {0x190,0x258,0x000}, {0x258,0x258,0x000}, {0x320,0x258,0x000}, {0x3e8,0x258,0x000},
+ {0x000,0x320,0x000}, {0x0c8,0x320,0x000}, {0x190,0x320,0x000}, {0x258,0x320,0x000}, {0x320,0x320,0x000}, {0x3e8,0x320,0x000},
+ {0x000,0x3e8,0x000}, {0x0c8,0x3e8,0x000}, {0x190,0x3e8,0x000}, {0x258,0x3e8,0x000}, {0x320,0x3e8,0x000}, {0x3e8,0x3e8,0x000},
+ {0x000,0x000,0x0c8}, {0x0c8,0x000,0x0c8}, {0x190,0x000,0x0c8}, {0x258,0x000,0x0c8}, {0x320,0x000,0x0c8}, {0x3e8,0x000,0x0c8},
+ {0x000,0x0c8,0x0c8}, {0x0c8,0x0c8,0x0c8}, {0x190,0x0c8,0x0c8}, {0x258,0x0c8,0x0c8}, {0x320,0x0c8,0x0c8}, {0x3e8,0x0c8,0x0c8},
+ {0x000,0x190,0x0c8}, {0x0c8,0x190,0x0c8}, {0x190,0x190,0x0c8}, {0x258,0x190,0x0c8}, {0x320,0x190,0x0c8}, {0x3e8,0x190,0x0c8},
+ {0x000,0x258,0x0c8}, {0x0c8,0x258,0x0c8}, {0x190,0x258,0x0c8}, {0x258,0x258,0x0c8}, {0x320,0x258,0x0c8}, {0x3e8,0x258,0x0c8},
+ {0x000,0x320,0x0c8}, {0x0c8,0x320,0x0c8}, {0x190,0x320,0x0c8}, {0x258,0x320,0x0c8}, {0x320,0x320,0x0c8}, {0x3e8,0x320,0x0c8},
+ {0x000,0x3e8,0x0c8}, {0x0c8,0x3e8,0x0c8}, {0x190,0x3e8,0x0c8}, {0x258,0x3e8,0x0c8}, {0x320,0x3e8,0x0c8}, {0x3e8,0x3e8,0x0c8},
+ {0x000,0x000,0x190}, {0x0c8,0x000,0x190}, {0x190,0x000,0x190}, {0x258,0x000,0x190}, {0x320,0x000,0x190}, {0x3e8,0x000,0x190},
+ {0x000,0x0c8,0x190}, {0x0c8,0x0c8,0x190}, {0x190,0x0c8,0x190}, {0x258,0x0c8,0x190}, {0x320,0x0c8,0x190}, {0x3e8,0x0c8,0x190},
+ {0x000,0x190,0x190}, {0x0c8,0x190,0x190}, {0x190,0x190,0x190}, {0x258,0x190,0x190}, {0x320,0x190,0x190}, {0x3e8,0x190,0x190},
+ {0x000,0x258,0x190}, {0x0c8,0x258,0x190}, {0x190,0x258,0x190}, {0x258,0x258,0x190}, {0x320,0x258,0x190}, {0x3e8,0x258,0x190},
+ {0x000,0x320,0x190}, {0x0c8,0x320,0x190}, {0x190,0x320,0x190}, {0x258,0x320,0x190}, {0x320,0x320,0x190}, {0x3e8,0x320,0x190},
+ {0x000,0x3e8,0x190}, {0x0c8,0x3e8,0x190}, {0x190,0x3e8,0x190}, {0x258,0x3e8,0x190}, {0x320,0x3e8,0x190}, {0x3e8,0x3e8,0x190},
+ {0x000,0x000,0x258}, {0x0c8,0x000,0x258}, {0x190,0x000,0x258}, {0x258,0x000,0x258}, {0x320,0x000,0x258}, {0x3e8,0x000,0x258},
+ {0x000,0x0c8,0x258}, {0x0c8,0x0c8,0x258}, {0x190,0x0c8,0x258}, {0x258,0x0c8,0x258}, {0x320,0x0c8,0x258}, {0x3e8,0x0c8,0x258},
+ {0x000,0x190,0x258}, {0x0c8,0x190,0x258}, {0x190,0x190,0x258}, {0x258,0x190,0x258}, {0x320,0x190,0x258}, {0x3e8,0x190,0x258},
+ {0x000,0x258,0x258}, {0x0c8,0x258,0x258}, {0x190,0x258,0x258}, {0x258,0x258,0x258}, {0x320,0x258,0x258}, {0x3e8,0x258,0x258},
+ {0x000,0x320,0x258}, {0x0c8,0x320,0x258}, {0x190,0x320,0x258}, {0x258,0x320,0x258}, {0x320,0x320,0x258}, {0x3e8,0x320,0x258},
+ {0x000,0x3e8,0x258}, {0x0c8,0x3e8,0x258}, {0x190,0x3e8,0x258}, {0x258,0x3e8,0x258}, {0x320,0x3e8,0x258}, {0x3e8,0x3e8,0x258},
+ {0x000,0x000,0x320}, {0x0c8,0x000,0x320}, {0x190,0x000,0x320}, {0x258,0x000,0x320}, {0x320,0x000,0x320}, {0x3e8,0x000,0x320},
+ {0x000,0x0c8,0x320}, {0x0c8,0x0c8,0x320}, {0x190,0x0c8,0x320}, {0x258,0x0c8,0x320}, {0x320,0x0c8,0x320}, {0x3e8,0x0c8,0x320},
+ {0x000,0x190,0x320}, {0x0c8,0x190,0x320}, {0x190,0x190,0x320}, {0x258,0x190,0x320}, {0x320,0x190,0x320}, {0x3e8,0x190,0x320},
+ {0x000,0x258,0x320}, {0x0c8,0x258,0x320}, {0x190,0x258,0x320}, {0x258,0x258,0x320}, {0x320,0x258,0x320}, {0x3e8,0x258,0x320},
+ {0x000,0x320,0x320}, {0x0c8,0x320,0x320}, {0x190,0x320,0x320}, {0x258,0x320,0x320}, {0x320,0x320,0x320}, {0x3e8,0x320,0x320},
+ {0x000,0x3e8,0x320}, {0x0c8,0x3e8,0x320}, {0x190,0x3e8,0x320}, {0x258,0x3e8,0x320}, {0x320,0x3e8,0x320}, {0x3e8,0x3e8,0x320},
+ {0x000,0x000,0x3e8}, {0x0c8,0x000,0x3e8}, {0x190,0x000,0x3e8}, {0x258,0x000,0x3e8}, {0x320,0x000,0x3e8}, {0x3e8,0x000,0x3e8},
+ {0x000,0x0c8,0x3e8}, {0x0c8,0x0c8,0x3e8}, {0x190,0x0c8,0x3e8}, {0x258,0x0c8,0x3e8}, {0x320,0x0c8,0x3e8}, {0x3e8,0x0c8,0x3e8},
+ {0x000,0x190,0x3e8}, {0x0c8,0x190,0x3e8}, {0x190,0x190,0x3e8}, {0x258,0x190,0x3e8}, {0x320,0x190,0x3e8}, {0x3e8,0x190,0x3e8},
+ {0x000,0x258,0x3e8}, {0x0c8,0x258,0x3e8}, {0x190,0x258,0x3e8}, {0x258,0x258,0x3e8}, {0x320,0x258,0x3e8}, {0x3e8,0x258,0x3e8},
+ {0x000,0x320,0x3e8}, {0x0c8,0x320,0x3e8}, {0x190,0x320,0x3e8}, {0x258,0x320,0x3e8}, {0x320,0x320,0x3e8}, {0x3e8,0x320,0x3e8},
+ {0x000,0x3e8,0x3e8}, {0x0c8,0x3e8,0x3e8}, {0x190,0x3e8,0x3e8}, {0x258,0x3e8,0x3e8}, {0x320,0x3e8,0x3e8}, {0x3e8,0x3e8,0x3e8}
+};
+#endif
+
+/* Error code translations: */
+static const char * plot_error_codes[] = {
+ "None",
+ "ERR_BUFFERSIZE_EXCEEDS_SCREEN",
+ "ERR_NO_MEM",
+ "ERR_PLOTTER_NOT_AVAILABLE"
+};
+
+FONT_PLOTTER fplotter = NULL;
+
+extern short vdih;
+
+/* temp buffer for bitmap conversion: */
+static void * buf_packed;
+static int size_buf_packed;
+
+/* temp buffer for bitmap conversion: */
+void * buf_planar;
+int size_buf_planar;
+
+/* buffer for plot operations that require device format, */
+/* currently used for transparent mfdb blits and snapshots: */
+static MFDB buf_scr;
+static int size_buf_scr;
+
+/* buffer for std form, used during 8bpp snapshot */
+MFDB buf_std;
+int size_buf_std;
+
+struct bitmap * buf_scr_compat;
+
+/* intermediate bitmap format */
+static HermesFormat vfmt;
+
+/* no screen format here, hermes may not suitable for it */
+
+/* netsurf source bitmap format */
+static HermesFormat nsfmt;
+
+struct s_vdi_sysinfo vdi_sysinfo;
+/* bit depth of framebuffers: */
+static int atari_plot_bpp_virt;
+static struct s_view view;
+
+//static HermesHandle hermes_pal_h; /* hermes palette handle */
+static HermesHandle hermes_cnv_h; /* hermes converter instance handle */
+static HermesHandle hermes_res_h;
+
+//static short prev_vdi_clip[4];
+static struct bitmap snapshot;
+
+VdiHdl atari_plot_vdi_handle = -1;
+unsigned long atari_plot_flags;
+unsigned long atari_font_flags;
+
+typedef bool (*bitmap_convert_fnc)( struct bitmap * img, int x, int y,
+ GRECT * clip, uint32_t bg, uint32_t flags, MFDB *out );
+static bitmap_convert_fnc bitmap_convert;
+
+const char* plot_err_str(int i)
+{
+ return(plot_error_codes[abs(i)]);
+}
+
+/**
+ * Set line drawing color by passing netsurf XBGR "colour" type.
+ *
+ * \param vdih The vdi handle
+ * \param cin The netsurf colour value
+ */
+inline static void vsl_rgbcolor(short vdih, colour cin)
+{
+ #ifdef WITH_8BPP_SUPPORT
+ if( vdi_sysinfo.scr_bpp > 8 ) {
+ #endif
+ RGB1000 c; /* a struct with three (RGB) shorts */
+ rgb_to_vdi1000( (unsigned char*)&cin, &c);
+ vs_color(vdih, OFFSET_CUSTOM_COLOR, (short *)&c);
+ vsl_color(vdih, OFFSET_CUSTOM_COLOR);
+ #ifdef WITH_8BPP_SUPPORT
+ } else {
+ if( vdi_sysinfo.scr_bpp >= 4 ){
+ vsl_color(vdih, RGB_TO_VDI(cin));
+ }
+ else
+ vsl_color(vdih, BLACK);
+ }
+ #endif
+}
+
+/**
+ * Set fill color by passing netsurf XBGR "colour" type.
+ *
+ * \param vdih The vdi handle
+ * \param cin The netsurf colour value
+ */
+inline static void vsf_rgbcolor(short vdih, colour cin)
+{
+ #ifdef WITH_8BPP_SUPPORT
+ if( vdi_sysinfo.scr_bpp > 8 ) {
+ #endif
+ RGB1000 c; /* a struct with three (RGB) shorts */
+ rgb_to_vdi1000( (unsigned char*)&cin, &c);
+ vs_color( vdih, OFFSET_CUSTOM_COLOR, (short *)&c);
+ vsf_color( vdih, OFFSET_CUSTOM_COLOR );
+ #ifdef WITH_8BPP_SUPPORT
+ } else {
+ if( vdi_sysinfo.scr_bpp >= 4 ){
+ vsf_color( vdih, RGB_TO_VDI(cin) );
+ }
+ else
+ vsf_color( vdih, WHITE );
+ }
+ #endif
+}
+
+
+
+/**
+ * Get current visible coords
+ */
+inline static void plot_get_visible_grect(GRECT * out)
+{
+ out->g_x = view.vis_x;
+ out->g_y = view.vis_y;
+ out->g_w = view.vis_w;
+ out->g_h = view.vis_h;
+}
+
+
+
+/* calculate visible area of framebuffer in coords relative to framebuffer */
+/* position */
+/* result: */
+/* this function should calculates an rectangle relative to the plot origin*/
+/* and size. */
+/* If the ploter coords do not fall within the screen region, */
+/* all values of the region are set to zero. */
+inline static void update_visible_rect(void)
+{
+ GRECT screen; // dimensions of the screen
+ GRECT frame; // dimensions of the drawing area
+ GRECT common; // dimensions of intersection of both
+
+ screen.g_x = 0;
+ screen.g_y = 0;
+ screen.g_w = vdi_sysinfo.scr_w;
+ screen.g_h = vdi_sysinfo.scr_h;
+
+ common.g_x = frame.g_x = view.x;
+ common.g_y = frame.g_y = view.y;
+ common.g_w = frame.g_w = view.w;
+ common.g_h = frame.g_h = view.h;
+
+ if (rc_intersect(&screen, &common)) {
+ view.vis_w = common.g_w;
+ view.vis_h = common.g_h;
+ if (view.x < screen.g_x)
+ view.vis_x = frame.g_w - common.g_w;
+ else
+ view.vis_x = 0;
+ if (view.y <screen.g_y)
+ view.vis_y = frame.g_h - common.g_h;
+ else
+ view.vis_y = 0;
+ } else {
+ view.vis_w = view.vis_h = 0;
+ view.vis_x = view.vis_y = 0;
+ }
+}
+
+/* Returns the visible parts of the box (relative coords within framebuffer),*/
+/* relative to screen coords (normally starting at 0,0 ) */
+inline static bool fbrect_to_screen(GRECT box, GRECT * ret)
+{
+ GRECT out, vis, screen;
+
+ screen.g_x = 0;
+ screen.g_y = 0;
+ screen.g_w = vdi_sysinfo.scr_w;
+ screen.g_h = vdi_sysinfo.scr_h;
+
+ /* get visible region: */
+ vis.g_x = view.x;
+ vis.g_y = view.y;
+ vis.g_w = view.w;
+ vis.g_h = view.h;
+
+ if ( !rc_intersect( &screen, &vis ) ) {
+ return( false );
+ }
+ vis.g_x = view.w - vis.g_w;
+ vis.g_y = view.h - vis.g_h;
+
+ /* clip box to visible region: */
+ if( !rc_intersect(&vis, &box) ) {
+ return( false );
+ }
+ out.g_x = box.g_x + view.x;
+ out.g_y = box.g_y + view.y;
+ out.g_w = box.g_w;
+ out.g_h = box.g_h;
+ *ret = out;
+ return ( true );
+}
+
+/* copy an rectangle from the plot buffer to screen */
+/* because this is an on-screen plotter, this is an screen to screen copy. */
+bool plot_copy_rect(GRECT src, GRECT dst)
+{
+ MFDB devmf;
+ MFDB scrmf;
+ short pxy[8];
+ GRECT vis;
+
+ /* clip to visible rect, only needed for onscreen renderer: */
+ plot_get_visible_grect(&vis );
+
+ if( !rc_intersect(&vis, &src) )
+ return(true);
+ if( !rc_intersect(&vis, &dst) )
+ return(true);
+
+ src.g_x = view.x + src.g_x;
+ src.g_y = view.y + src.g_y;
+ dst.g_x = view.x + dst.g_x;
+ dst.g_y = view.y + dst.g_y;
+
+ devmf.fd_addr = NULL;
+ devmf.fd_w = src.g_w;
+ devmf.fd_h = src.g_h;
+ devmf.fd_wdwidth = 0;
+ devmf.fd_stand = 0;
+ devmf.fd_nplanes = 0;
+ devmf.fd_r1 = devmf.fd_r2 = devmf.fd_r3 = 0;
+
+ scrmf.fd_addr = NULL;
+ scrmf.fd_w = dst.g_w;
+ scrmf.fd_h = dst.g_h;
+ scrmf.fd_wdwidth = 0 ;
+ scrmf.fd_stand = 0;
+ scrmf.fd_nplanes = 0;
+ scrmf.fd_r1 = scrmf.fd_r2 = scrmf.fd_r3 = 0;
+
+ pxy[0] = src.g_x;
+ pxy[1] = src.g_y;
+ pxy[2] = pxy[0] + src.g_w-1;
+ pxy[3] = pxy[1] + src.g_h-1;
+ pxy[4] = dst.g_x;
+ pxy[5] = dst.g_y;
+ pxy[6] = pxy[4] + dst.g_w-1;
+ pxy[7] = pxy[5] + dst.g_h-1;
+ plot_lock();
+ vro_cpyfm( atari_plot_vdi_handle, S_ONLY, (short*)&pxy, &devmf, &scrmf);
+ plot_unlock();
+
+ return(true);
+}
+
+/**
+ * Fill the screen info structure.
+ *
+ * \param vdhi The handle
+ * \param[out] info The infor structure to fill.
+ */
+static void read_vdi_sysinfo(short vdih, struct s_vdi_sysinfo * info) {
+
+ unsigned long cookie_EdDI=0; /** \todo this long is being cast to a pointer */
+ short out[300];
+ memset( info, 0, sizeof(struct s_vdi_sysinfo) );
+
+ info->vdi_handle = vdih;
+ if ( tos_getcookie(C_EdDI, (long *)&cookie_EdDI) == C_NOTFOUND ) {
+ info->EdDiVersion = 0;
+ } else {
+ info->EdDiVersion = EdDI_version( (void *)cookie_EdDI );
+ }
+
+ memset( &out, 0, sizeof(short)*300 );
+ vq_extnd( vdih, 0, (short*)&out );
+ info->scr_w = out[0]+1;
+ info->scr_h = out[1]+1;
+ if( out[39] == 2 ) {
+ info->scr_bpp = 1;
+ info->colors = out[39];
+ } else {
+ info->colors = out[39];
+ }
+
+ memset( &out, 0, sizeof(short)*300 );
+ vq_extnd( vdih, 1, (short*)&out );
+ info->scr_bpp = out[4];
+ info->maxpolycoords = out[14];
+ info->maxintin = out[15];
+ if( out[30] & 1 ) {
+ info->rasterscale = true;
+ } else {
+ info->rasterscale = false;
+ }
+
+ switch( info->scr_bpp ) {
+ case 8:
+ info->pixelsize=1;
+ break;
+ case 15:
+ case 16:
+ info->pixelsize=2;
+ break;
+ case 24:
+ info->pixelsize=3;
+ break;
+ case 32:
+ info->pixelsize=4;
+ break;
+ case 64:
+ info->pixelsize=8;
+ break;
+ default:
+ info->pixelsize=1;
+ break;
+
+ }
+ info->pitch = info->scr_w * info->pixelsize;
+ info->vdiformat = ( (info->scr_bpp <= 8) ? VDI_FORMAT_INTER : VDI_FORMAT_PACK);
+ info->screensize = ( info->scr_w * info->pixelsize ) * info->scr_h;
+
+ if( info->EdDiVersion >= EDDI_10 ) {
+ memset( &out, 0, sizeof(short)*300 );
+ vq_scrninfo(vdih, (short*)&out);
+ info->vdiformat = out[0];
+ info->clut = out[1];
+ info->scr_bpp = out[2];
+ info->hicolors = *((unsigned long*) &out[3]);
+ if( info->EdDiVersion >= EDDI_11 ) {
+ info->pitch = out[5];
+ info->screen = (void *) *((unsigned long *) &out[6]);
+ }
+
+ switch( info->clut ) {
+
+ case VDI_CLUT_HARDWARE: {
+
+ }
+ break;
+
+ case VDI_CLUT_SOFTWARE: {
+ int component; /* red, green, blue, alpha, overlay */
+ int num_bit;
+ unsigned short *tmp_p;
+
+ /* We can build masks with info here */
+ tmp_p = (unsigned short *) &out[16];
+ for (component=0; component<5; component++) {
+ for (num_bit=0; num_bit<16; num_bit++) {
+ unsigned short val;
+
+ val = *tmp_p++;
+
+ if (val == 0xffff) {
+ continue;
+ }
+
+ switch(component) {
+ case 0:
+ info->mask_r |= 1<< val;
+ break;
+ case 1:
+ info->mask_g |= 1<< val;
+ break;
+ case 2:
+ info->mask_b |= 1<< val;
+ break;
+ case 3:
+ info->mask_a |= 1<< val;
+ break;
+ }
+ }
+ }
+ }
+
+ /* Remove lower green bits for Intel endian screen */
+ if ((info->mask_g == ((7<<13)|3)) || (info->mask_g == ((7<<13)|7))) {
+ info->mask_g &= ~(7<<13);
+ }
+ break;
+
+ case VDI_CLUT_NONE:
+ break;
+ }
+ }
+}
+
+
+/*
+ Convert an RGB color to an VDI Color
+*/
+inline void rgb_to_vdi1000(unsigned char * in, RGB1000 *out)
+{
+ double r = ((double)in[3]/255); /* prozentsatz red */
+ double g = ((double)in[2]/255); /* prozentsatz green */
+ double b = ((double)in[1]/255); /* prozentsatz blue */
+ out->red = 1000 * r + 0.5;
+ out->green = 1000 * g + 0.5;
+ out->blue = 1000 * b + 0.5;
+ return;
+}
+
+inline void vdi1000_to_rgb(unsigned short * in, unsigned char * out)
+{
+ double r = ((double)in[0]/1000); /* prozentsatz red */
+ double g = ((double)in[1]/1000); /* prozentsatz green */
+ double b = ((double)in[2]/1000); /* prozentsatz blue */
+ out[2] = 255 * r + 0.5;
+ out[1] = 255 * g + 0.5;
+ out[0] = 255 * b + 0.5;
+ return;
+}
+
+
+#ifdef WITH_8BPP_SUPPORT
+/**
+ * Set pixel within an 8 bit VDI standard bitmap.
+ */
+inline static void set_stdpx( MFDB * dst, int wdplanesz, int x, int y, unsigned char val )
+{
+ short * buf;
+ short whichbit = (1<<(15-(x%16)));
+
+ buf = dst->fd_addr;
+ buf += ((dst->fd_wdwidth*(y))+(x>>4));
+
+ *buf = (val&1) ? ((*buf)|(whichbit)) : ((*buf)&~(whichbit));
+
+ buf += wdplanesz;
+ *buf = (val&(1<<1)) ? ((*buf)|(whichbit)) : ((*buf)&~(whichbit));
+
+ buf += wdplanesz;
+ *buf = (val&(1<<2)) ? ((*buf)|(whichbit)) : ((*buf)&~(whichbit));
+
+ buf += wdplanesz;
+ *buf = (val&(1<<3)) ? ((*buf)|(whichbit)) : ((*buf)&~(whichbit));
+
+ buf += wdplanesz;
+ *buf = (val&(1<<4)) ? ((*buf)|(whichbit)) : ((*buf)&~(whichbit));
+
+ buf += wdplanesz;
+ *buf = (val&(1<<5)) ? ((*buf)|(whichbit)) : ((*buf)&~(whichbit));
+
+ buf += wdplanesz;
+ *buf = (val&(1<<6)) ? ((*buf)|(whichbit)) : ((*buf)&~(whichbit));
+
+ buf += wdplanesz;
+ *buf = (val&(1<<7)) ? ((*buf)|(whichbit)) : ((*buf)&~(whichbit));
+}
+
+/**
+ * Read pixel from an 8 bit VDI standard bitmap.
+ */
+inline static unsigned char get_stdpx(MFDB * dst, int wdplanesz, int x, int y)
+{
+ unsigned char ret=0;
+ short * buf;
+ short whichbit = (1<<(15-(x%16)));
+
+ buf = dst->fd_addr;
+ buf += ((dst->fd_wdwidth*(y))+(x>>4));
+
+ if( *buf & whichbit )
+ ret |= 1;
+
+ buf += wdplanesz;
+ if( *buf & whichbit )
+ ret |= 2;
+
+ buf += wdplanesz;
+ if( *buf & whichbit )
+ ret |= 4;
+
+ buf += wdplanesz;
+ if( *buf & whichbit )
+ ret |= 8;
+
+ buf += wdplanesz;
+ if( *buf & whichbit )
+ ret |= 16;
+
+ buf += wdplanesz;
+ if( *buf & whichbit )
+ ret |= 32;
+
+ buf += wdplanesz;
+ if( *buf & whichbit )
+ ret |= 64;
+
+ buf += wdplanesz;
+ if( *buf & whichbit )
+ ret |= 128;
+
+ return( ret );
+}
+
+/*
+ Convert an RGB color into an index into the 216 colors web pallette
+*/
+inline short rgb_to_666_index(unsigned char r, unsigned char g, unsigned char b)
+{
+ short i;
+ unsigned char rgb[3] = {r,g,b};
+ unsigned char tval[3];
+
+ int diff_a, diff_b, diff_c;
+ diff_a = abs(r-g);
+ diff_b = abs(r-b);
+ diff_c = abs(r-b);
+ if( diff_a < 2 && diff_b < 2 && diff_c < 2 ) {
+ if( (r!=0XFF) && (g!=0XFF) && (b!=0XFF) ) {
+ if( ((r&0xF0)>>4) != 0 )
+ //printf("conv gray: %x -> %d\n", ((r&0xF0)>>4) , (OFFSET_CUST_PAL) + ((r&0xF0)>>4) );
+ return( (OFFSET_CUST_PAL - OFFSET_WEB_PAL) + ((r&0xF0)>>4) );
+ }
+ }
+
+ /* convert each 8bit color to 6bit web color: */
+ for( i=0; i<3; i++) {
+ if(0 == rgb[i] % web_std_colors[1] ) {
+ tval[i] = rgb[i] / web_std_colors[1];
+ } else {
+ int pos = ((short)rgb[i] / web_std_colors[1]);
+ if( abs(rgb[i] - web_std_colors[pos]) > abs(rgb[i] - web_std_colors[pos+1]) )
+ tval[i] = pos+1;
+ else
+ tval[i] = pos;
+ }
+ }
+ return(tval[2]*36+tval[1]*6+tval[0]);
+}
+#endif
+
+
+static void dump_vdi_info(short vdih)
+{
+ struct s_vdi_sysinfo temp;
+ read_vdi_sysinfo( vdih, &temp );
+ printf("struct s_vdi_sysinfo {\n");
+ printf(" short vdi_handle: %d\n", temp.vdi_handle);
+ printf(" short scr_w: %d \n", temp.scr_w);
+ printf(" short scr_h: %d\n", temp.scr_h);
+ printf(" short scr_bpp: %d\n", temp.scr_bpp);
+ printf(" int colors: %d\n", temp.colors);
+ printf(" ulong hicolors: %lu\n", temp.hicolors);
+ printf(" short pixelsize: %d\n", temp.pixelsize);
+ printf(" unsigned short pitch: %d\n", temp.pitch);
+ printf(" unsigned short vdiformat: %d\n", temp.vdiformat);
+ printf(" unsigned short clut: %d\n", temp.clut);
+ printf(" void * screen: 0x0%p\n", temp.screen);
+ printf(" unsigned long screensize: %lu\n", temp.screensize);
+ printf(" unsigned long mask_r: 0x0%08lx\n", temp.mask_r);
+ printf(" unsigned long mask_g: 0x0%08lx\n", temp.mask_g);
+ printf(" unsigned long mask_b: 0x0%08lx\n", temp.mask_b);
+ printf(" unsigned long mask_a: 0x0%08lx\n", temp.mask_a);
+ printf(" short maxintin: %d\n", temp.maxintin);
+ printf(" short maxpolycoords: %d\n", temp.maxpolycoords);
+ printf(" unsigned long EdDiVersion: 0x0%03lx\n", temp.EdDiVersion);
+ printf(" unsigned short rasterscale: 0x%2x\n", temp.rasterscale);
+ printf("};\n");
+}
+
+/**
+ * Create an snapshot of the screen image in device format.
+ */
+static MFDB * snapshot_create_native_mfdb(int x, int y, int w, int h)
+{
+ MFDB scr;
+ short pxy[8];
+
+ /* allocate memory for the snapshot */
+ {
+ int scr_stride = MFDB_STRIDE( w );
+ int scr_size = ( ((scr_stride >> 3) * h) * vdi_sysinfo.scr_bpp );
+ if(size_buf_scr == 0 ){
+ /* init screen mfdb */
+ buf_scr.fd_addr = malloc( scr_size );
+ size_buf_scr = scr_size;
+ } else {
+ if( scr_size >size_buf_scr ) {
+ buf_scr.fd_addr = realloc(
+ buf_scr.fd_addr, scr_size
+ );
+ size_buf_scr = scr_size;
+ }
+ }
+ if(buf_scr.fd_addr == NULL ) {
+ size_buf_scr = 0;
+ return( NULL );
+ }
+ buf_scr.fd_nplanes = vdi_sysinfo.scr_bpp;
+ buf_scr.fd_w = scr_stride;
+ buf_scr.fd_h = h;
+ buf_scr.fd_wdwidth = scr_stride >> 4;
+ assert(buf_scr.fd_addr != NULL );
+ }
+ init_mfdb( 0, w, h, 0, &scr );
+ pxy[0] = x;
+ pxy[1] = y;
+ pxy[2] = pxy[0] + w-1;
+ pxy[3] = pxy[1] + h-1;
+ pxy[4] = 0;
+ pxy[5] = 0;
+ pxy[6] = w-1;
+ pxy[7] = h-1;
+ vro_cpyfm(
+ atari_plot_vdi_handle, S_ONLY, (short*)&pxy,
+ &scr, &buf_scr
+ );
+
+ return( &buf_scr );
+}
+
+/**
+ * Create an snapshot of the screen image in VDI standard format (8 bit).
+ */
+static MFDB * snapshot_create_std_mfdb(int x, int y, int w, int h)
+{
+ /* allocate memory for the snapshot */
+ {
+ int scr_stride = MFDB_STRIDE( w );
+ int scr_size = ( ((scr_stride >> 3) * h) * vdi_sysinfo.scr_bpp );
+ if(size_buf_std == 0 ){
+ /* init screen mfdb */
+ buf_std.fd_addr = malloc( scr_size );
+ size_buf_std = scr_size;
+ } else {
+ if( scr_size >size_buf_std ) {
+ buf_std.fd_addr = realloc(
+ buf_std.fd_addr, scr_size
+ );
+ size_buf_std = scr_size;
+ }
+ }
+ if(buf_std.fd_addr == NULL ) {
+ size_buf_std = 0;
+ return( NULL );
+ }
+ buf_std.fd_nplanes = 8;
+ buf_std.fd_w = scr_stride;
+ buf_std.fd_h = h;
+ buf_std.fd_stand = 1;
+ buf_std.fd_wdwidth = scr_stride >> 4;
+ assert(buf_std.fd_addr != NULL );
+ }
+ MFDB * native = snapshot_create_native_mfdb(x,y,w,h );
+ assert( native );
+
+ vr_trnfm(atari_plot_vdi_handle, native, &buf_std);
+ return( &buf_std );
+}
+
+/*
+ * Create an snapshot of the screen in netsurf ABGR format
+ */
+static struct bitmap * snapshot_create(int x, int y, int w, int h)
+{
+ int err;
+ MFDB * native;
+ // uint32_t start = clock();
+
+ // FIXME: This can be optimized a lot.
+ // 1. do not copy the snapshot to the bitmap buffer
+ // when the format of screen and bitmap equals.
+ // just point the bitmap to the native mfdb.
+ // 2. if we have eddi 1.1, we could optimize that further
+ // make snapshot_create_native_mfdb just returning a pointer
+ // to the screen.
+
+ native = snapshot_create_native_mfdb(x, y, w, h );
+
+ if(vfmt.bits == 32 )
+ goto no_copy;
+
+ /* allocate buffer for result bitmap: */
+ if(buf_scr_compat == NULL ) {
+ buf_scr_compat = atari_bitmap_create(w, h, 0);
+ } else {
+ buf_scr_compat = atari_bitmap_realloc( w, h,
+ buf_scr_compat->bpp,
+ w *buf_scr_compat->bpp,
+ BITMAP_GROW,
+ buf_scr_compat );
+ }
+
+ /* convert screen buffer to ns format: */
+ err = Hermes_ConverterRequest( hermes_cnv_h,
+ &vfmt,
+ &nsfmt
+ );
+ assert( err != 0 );
+ err = Hermes_ConverterCopy( hermes_cnv_h,
+ native->fd_addr,
+ 0, /* x src coord of top left in pixel coords */
+ 0, /* y src coord of top left in pixel coords */
+ w, h,
+ native->fd_w * vdi_sysinfo.pixelsize, /* stride as bytes */
+ buf_scr_compat->pixdata,
+ 0, /* x dst coord of top left in pixel coords */
+ 0, /* y dst coord of top left in pixel coords */
+ w, h,
+ atari_bitmap_get_rowstride(buf_scr_compat) /* stride as bytes */
+ );
+ assert( err != 0 );
+ return( (struct bitmap * )buf_scr_compat );
+
+no_copy:
+
+ snapshot.width = w;
+ snapshot.height = h;
+ snapshot.pixdata = native->fd_addr;
+ snapshot.native = *native;
+ snapshot.rowstride = MFDB_STRIDE( w )*4;
+
+ uint32_t row, col;
+ for (row = 0; row<(uint32_t)h; row++) {
+ // fd_w matches stride!
+ uint32_t *rowptr = ((uint32_t*)native->fd_addr + ((row*native->fd_w)));
+ for (col=0; col<(uint32_t)w; col++) {
+ *(rowptr+col) = (*(rowptr+col)<<8);
+ }
+ }
+ return( &snapshot );
+}
+
+/**
+ * Notify the snapshot interface that the last snapshot is no longer in use.
+ */
+static void snapshot_suspend(void)
+{
+ if(size_buf_scr > CONV_KEEP_LIMIT ) {
+ buf_scr.fd_addr = realloc(
+ buf_scr.fd_addr, CONV_KEEP_LIMIT
+ );
+ if(buf_scr.fd_addr != NULL ) {
+ size_buf_scr = CONV_KEEP_LIMIT;
+ } else {
+ size_buf_scr = 0;
+ }
+ }
+
+#ifdef WITH_8BPP_SUPPORT
+ if(size_buf_std > CONV_KEEP_LIMIT ) {
+ buf_std.fd_addr = realloc(
+ buf_std.fd_addr, CONV_KEEP_LIMIT
+ );
+ if(buf_std.fd_addr != NULL ) {
+ size_buf_std = CONV_KEEP_LIMIT;
+ } else {
+ size_buf_std = 0;
+ }
+ }
+#endif
+
+ if(buf_scr_compat != NULL ) {
+ size_t bs = atari_bitmap_buffer_size(buf_scr_compat );
+ if( bs > CONV_KEEP_LIMIT ) {
+ int w = 0;
+ int h = 1;
+ w = (CONV_KEEP_LIMIT /buf_scr_compat->bpp);
+ assert( CONV_KEEP_LIMIT == w*buf_scr_compat->bpp );
+ buf_scr_compat = atari_bitmap_realloc( w, h,
+ buf_scr_compat->bpp,
+ CONV_KEEP_LIMIT, BITMAP_SHRINK,buf_scr_compat
+ );
+ }
+ }
+}
+
+/**
+ * Shut down the snapshot interface.
+ */
+static void snapshot_destroy(void)
+{
+
+ free(buf_scr.fd_addr);
+ if( buf_scr_compat != NULL) {
+ atari_bitmap_destroy(buf_scr_compat);
+ }
+
+ buf_scr.fd_addr = NULL;
+ buf_scr_compat = NULL;
+
+#ifdef WITH_8BPP_SUPPORT
+ free(buf_std.fd_addr);
+ buf_std.fd_addr = NULL;
+#endif
+}
+
+
+inline static uint32_t ablend(uint32_t pixel, uint32_t scrpixel)
+{
+ int opacity = pixel & 0xFF;
+ int transp = 0x100 - opacity;
+ uint32_t rb, g;
+ pixel >>= 8;
+ scrpixel >>= 8;
+ rb = ((pixel & 0xFF00FF) * opacity +
+ (scrpixel & 0xFF00FF) * transp) >> 8;
+ g = ((pixel & 0x00FF00) * opacity +
+ (scrpixel & 0x00FF00) * transp) >> 8;
+
+ return ((rb & 0xFF00FF) | (g & 0xFF00)) << 8;
+}
+
+/*
+ Alpha blends an image, using one pixel as the background.
+ The bitmap receives the result.
+*/
+inline static bool ablend_pixel(struct bitmap * img, uint32_t bg, GRECT * clip)
+{
+ uint32_t * imgrow;
+ int img_x, img_y, img_stride;
+
+ img_stride= atari_bitmap_get_rowstride(img);
+
+ for( img_y = 0; img_y < clip->g_h; img_y++) {
+ imgrow = (uint32_t *)(img->pixdata + (img_stride * img_y));
+ for( img_x = 0; img_x < clip->g_w; img_x++ ) {
+ imgrow[img_x] = ablend( imgrow[img_x], bg );
+ }
+ }
+ return(true);
+}
+
+
+/*
+ Aplha blends the foreground image (img) onto the
+ background images (bg). The background receives the blended
+ image pixels.
+*/
+inline static bool ablend_bitmap( struct bitmap * img, struct bitmap * bg,
+ GRECT * img_clip, GRECT * bg_clip )
+{
+ uint32_t * imgrow;
+ uint32_t * screenrow;
+ int img_x, img_y, bg_x, bg_y, img_stride, bg_stride;
+
+ bg_clip = bg_clip;
+ img_stride = atari_bitmap_get_rowstride(img);
+ bg_stride = atari_bitmap_get_rowstride(bg);
+
+ for( img_y = img_clip->g_y, bg_y = 0; bg_y < img_clip->g_h; bg_y++, img_y++) {
+ imgrow = (uint32_t *)(img->pixdata + (img_stride * img_y));
+ screenrow = (uint32_t *)(bg->pixdata + (bg_stride * bg_y));
+ for( img_x = img_clip->g_x, bg_x = 0; bg_x < img_clip->g_w; bg_x++, img_x++ ) {
+
+ // when the pixel isn't fully transparent,...:
+ if( (imgrow[img_x] & 0x0FF) != 0 ){
+ screenrow[bg_x] = ablend( imgrow[img_x], screenrow[bg_x]);
+ }
+
+ // FIXME, maybe this loop would be faster??:
+ // ---
+ //if( (imgrow[img_x] & 0x0FF) != 0xFF ){
+ // imgrow[bg_x] = ablend( imgrow[img_x], screenrow[bg_x]);
+ //}
+
+ // or maybe even this???
+ // ---
+ //if( (imgrow[img_x] & 0x0FF) == 0xFF ){
+ // screenrow[bg_x] = imgrow[img_x];
+ //} else if( (imgrow[img_x] & 0x0FF) != 0x00 ) {
+ // screenrow[bg_x] = ablend( imgrow[img_x], screenrow[bg_x]);
+ //}
+ }
+ }
+ return(false);
+}
+
+
+#ifdef WITH_8BPP_SUPPORT
+/**
+ * Convert an bitmap to an 8 bit device dependant MFDB
+ * \param img the bitmap (only tested with 32bit bitmaps)
+ * \param x screen coord of the background
+ * \param y screen coord of the background
+ * \param clip the region of the image that get's converted
+ * \param bg the background used for cheap transparency
+ * \param flags
+ * \param out receives the converted bitmap (still owned by the plot API)
+ *
+ */
+static bool bitmap_convert_8(struct bitmap * img, int x,
+ int y, GRECT * clip, uint32_t bg, uint32_t flags,
+ MFDB *out )
+{
+ MFDB native;
+ MFDB stdform;
+ int dststride; /* stride of dest. image */
+ int dstsize; /* size of dest. in byte */
+ int bw, bh;
+ struct bitmap * scrbuf = NULL;
+ bool cache = ( flags & BITMAPF_BUFFER_NATIVE );
+ bool opaque = atari_bitmap_get_opaque( img );
+
+ if( opaque == false ){
+ if( ( (atari_plot_flags & PLOT_FLAG_TRANS) == 0)
+ &&
+ ((flags & (BITMAPF_MONOGLYPH|BITMAPF_BUFFER_NATIVE))==0) ){
+ opaque = true;
+ }
+ }
+
+ assert( clip->g_h > 0 );
+ assert( clip->g_w > 0 );
+
+ bw = atari_bitmap_get_width( img );
+ bh = atari_bitmap_get_height( img );
+
+ // The converted bitmap can be saved for subsequent blits, when
+ // the bitmap is fully opaque
+
+ if( (opaque == true) || (flags & BITMAPF_BUFFER_NATIVE ) ){
+ if( img->converted == true ){
+ *out = img->native;
+ return( 0 );
+ }
+ if( ( flags & BITMAPF_MONOGLYPH ) == 0 ){
+ cache = true;
+ }
+ }
+ if( ( flags & BITMAPF_MONOGLYPH ) != 0 ){
+ assert(cache == false);
+ }
+
+ /* (re)allocate buffer for out image: */
+ /* altough the buffer is named "buf_packed" on 8bit systems */
+ /* it's not... */
+ if( cache == false ){
+ // the size of the output will match the size of the clipping:
+ dststride = MFDB_STRIDE( clip->g_w );
+ dstsize = ( ((dststride >> 3) * clip->g_h) * atari_plot_bpp_virt);
+ if( dstsize > size_buf_packed) {
+ int blocks = (dstsize / (CONV_BLOCK_SIZE-1))+1;
+ if( buf_packed == NULL )
+ buf_packed =(void*)malloc( blocks * CONV_BLOCK_SIZE);
+ else
+ buf_packed =(void*)realloc(buf_packed,blocks * CONV_BLOCK_SIZE);
+ assert( buf_packed );
+ if( buf_packed == NULL ) {
+ return( 0-ERR_NO_MEM );
+ }
+ size_buf_packed = blocks * CONV_BLOCK_SIZE;
+ }
+ native.fd_addr = buf_packed;
+ }
+ else {
+ // the output image will be completly saved, so size of the output
+ // image will match the input image size.
+ dststride = MFDB_STRIDE( bw );
+ dstsize = ( ((dststride >> 3) * bh) * atari_plot_bpp_virt);
+ assert( out->fd_addr == NULL );
+ native.fd_addr = (void*)malloc( dstsize );
+ if (native.fd_addr == NULL){
+ if (scrbuf != NULL)
+ atari_bitmap_destroy(scrbuf);
+ return( 0-ERR_NO_MEM );
+ }
+ }
+
+
+ /*
+ on 8 bit systems we must convert the TC (ABGR) image
+ to vdi standard format. ( only tested for 256 colors )
+ and then convert it to native format with v_trnfm()
+ */
+ // realloc mem for stdform
+ if( opaque == false ){
+ // point image to snapshot buffer, otherwise allocate mem
+ MFDB * bg = snapshot_create_std_mfdb(x, y, clip->g_w, clip->g_h);
+ stdform.fd_addr = bg->fd_addr;
+ bh = clip->g_h;
+ } else {
+ if( dstsize > size_buf_planar) {
+ int blocks = (dstsize / (CONV_BLOCK_SIZE-1))+1;
+ if( buf_planar == NULL )
+ buf_planar =(void*)malloc( blocks * CONV_BLOCK_SIZE );
+ else
+ buf_planar =(void*)realloc(buf_planar, blocks * CONV_BLOCK_SIZE);
+ assert(buf_planar);
+ if( buf_planar == NULL ) {
+ return( 0-ERR_NO_MEM );
+ }
+ size_buf_planar = blocks * CONV_BLOCK_SIZE;
+ }
+ stdform.fd_addr = buf_planar;
+ }
+ stdform.fd_w = dststride;
+ stdform.fd_h = bh;
+ stdform.fd_wdwidth = dststride >> 4;
+ stdform.fd_stand = 1;
+ stdform.fd_nplanes = (short)atari_plot_bpp_virt;
+ stdform.fd_r1 = stdform.fd_r2 = stdform.fd_r3 = 0;
+
+ int img_stride = atari_bitmap_get_rowstride(img);
+ uint32_t prev_pixel = 0x12345678; //TODO: check for collision in first pixel
+ unsigned long col = 0;
+ unsigned char val = 0;
+ uint32_t * row;
+ uint32_t pixel;
+ int wdplanesize = stdform.fd_wdwidth*stdform.fd_h;
+
+ if( opaque == false ){
+ // apply transparency and convert to vdi std format
+ unsigned long bgcol = 0;
+ unsigned char prev_col = 0;
+ for( y=0; y<clip->g_h; y++ ){
+ row = (uint32_t *)(img->pixdata + (img_stride * (y+clip->g_y)));
+ for( x=0; x<clip->g_w; x++ ){
+ pixel = row[x+clip->g_x];
+ if( (pixel&0xFF) == 0 ){
+ continue;
+ }
+ if( (pixel&0xFF) < 0xF0 ){
+ col = get_stdpx( &stdform, wdplanesize,x,y );
+ if( (col != prev_col) || (y == 0) )
+ bgcol = (((rgb_lookup[col][2] << 16) | (rgb_lookup[col][1] << 8) | (rgb_lookup[col][0]))<<8);
+ if( prev_col != col || prev_pixel != pixel ){
+ prev_col = col;
+ pixel = ablend( pixel, bgcol );
+ prev_pixel = pixel;
+ pixel = pixel >> 8;
+ /* convert pixel value to vdi color index: */
+ col = ( ((pixel&0xFF)<<16)
+ | (pixel&0xFF00)
+ | ((pixel&0xFF0000)>>16) );
+ val = RGB_TO_VDI( col );
+ }
+ set_stdpx( &stdform, wdplanesize, x, y, val );
+ } else {
+ if( pixel != prev_pixel ){
+ /* convert pixel value to vdi color index: */
+ pixel = pixel >> 8;
+ col = ( ((pixel&0xFF)<<16)
+ | (pixel&0xFF00)
+ | ((pixel&0xFF0000)>>16) );
+ val = RGB_TO_VDI( col );
+ prev_pixel = pixel;
+ }
+ set_stdpx( &stdform, wdplanesize, x, y, val );
+ }
+ }
+ }
+ // adjust output position:
+ clip->g_x = 0;
+ clip->g_y = 0;
+ } else {
+ // convert the whole image data to vdi std format.
+ for( y=0; y < bh; y++ ){
+ row = (uint32_t *)(img->pixdata + (img_stride * y));
+ for( x=0; x < bw; x++ ){
+ pixel = row[x];
+ if( pixel != prev_pixel ){
+ /* convert pixel value to vdi color index: */
+ pixel = pixel >> 8;
+ col = ( ((pixel&0xFF)<<16)
+ | (pixel&0xFF00)
+ | ((pixel&0xFF0000)>>16) );
+ val = RGB_TO_VDI( col );
+ prev_pixel = pixel;
+ }
+ set_stdpx( &stdform, wdplanesize, x, y, val );
+ }
+ }
+ }
+
+ // convert into native format:
+ native.fd_w = stdform.fd_w;
+ native.fd_h = stdform.fd_h;
+ native.fd_wdwidth = stdform.fd_wdwidth;
+ native.fd_stand = 0;
+ native.fd_nplanes = (short)atari_plot_bpp_virt;
+ native.fd_r1 = native.fd_r2 = native.fd_r3 = 0;
+ vr_trnfm(atari_plot_vdi_handle, &stdform, &native );
+ *out = native;
+ if( cache == true ){
+ img->native = native;
+ img->converted = true;
+ }
+
+ return(0);
+}
+#endif
+
+
+/*
+*
+* Convert bitmap to the native screen format
+* img: the bitmap
+* x: coordinate where the bitmap REGION (described in clip)
+* shall be drawn (screen coords)
+* y: coordinate where the bitmap REGION (described in clip)
+* shall be drawn (screen coords)
+* clip: which area of the bitmap shall be drawn
+* bg: background color
+* flags: blit flags
+* out: the result MFDB
+*/
+static bool bitmap_convert_tc(struct bitmap * img, int x, int y,
+ GRECT * clip, uint32_t bg, uint32_t flags, MFDB *out )
+{
+ int dststride; /* stride of dest. image */
+ int dstsize; /* size of dest. in byte */
+ int err;
+ int bw, bh;
+ struct bitmap * scrbuf = NULL;
+ struct bitmap * source = NULL;
+ bool cache = ( flags & BITMAPF_BUFFER_NATIVE );
+ bool opaque = atari_bitmap_get_opaque( img );
+
+ if( opaque == false ){
+ if( ( (atari_plot_flags & PLOT_FLAG_TRANS) == 0)
+ &&
+ ((flags & (BITMAPF_MONOGLYPH|BITMAPF_BUFFER_NATIVE))==0) ){
+ opaque = true;
+ }
+ }
+
+
+ assert( clip->g_h > 0 );
+ assert( clip->g_w > 0 );
+
+ bw = atari_bitmap_get_width( img );
+ bh = atari_bitmap_get_height( img );
+
+ // The converted bitmap can be saved for subsequent blits, WHEN:
+ // A.) the bitmap is fully opaque OR
+ // B.) the bitmap is completly inside the window
+ // the latter one is important for alpha blits,
+ // because we must get the window background to apply transparency
+ // If the image is not completly within the window,
+ // we can't get the whole background for the image.
+ // this only works if the image isn't used at several different places.
+ // In fact in case of alpha bitmap caching it is only used for the
+ // toolbar buttons right now.
+
+ if( (opaque == true) || (flags & BITMAPF_BUFFER_NATIVE ) ){
+ if( img->converted == true ){
+ *out = img->native;
+ return( 0 );
+ }
+ if( ( flags & BITMAPF_MONOGLYPH ) == 0 ){
+ cache = true;
+ }
+ }
+
+ /* rem. if eddi xy is installed, we could directly access the screen! */
+ /* apply transparency to the image: */
+ if (( opaque == false )) {
+ /* copy the screen to an temp buffer: */
+ if ((flags & BITMAPF_BUFFER_NATIVE) == 0) {
+ scrbuf = snapshot_create(x, y, clip->g_w, clip->g_h);
+ if( scrbuf != NULL ) {
+
+ assert( clip->g_w <= bw );
+ assert( clip->g_h <= bh );
+
+ // copy blended pixels to the screen buffer:
+ ablend_bitmap( img, scrbuf, clip, NULL );
+ /* adjust size which gets converted: */
+ bw = clip->g_w;
+ bh = clip->g_h;
+ /* adjust output position: */
+ clip->g_x = 0;
+ clip->g_y = 0;
+ /* set the source of conversion: */
+ source = scrbuf;
+ }
+ } else {
+ /*
+ The whole bitmap can be transformed to an mfdb
+ (and get's cached)
+ */
+ GRECT region = { 0, 0, bw, bh };
+ ablend_pixel( img, bg, &region );
+ source = img;
+ }
+ } else {
+ source = img;
+ }
+ /* (re)allocate buffer for converted image: */
+ dststride = MFDB_STRIDE(bw);
+ dstsize = ( ((dststride >> 3) * bh) * atari_plot_bpp_virt );
+ if (cache == false) {
+ if (dstsize > size_buf_packed) {
+ int blocks = (dstsize / (CONV_BLOCK_SIZE-1))+1;
+ if( buf_packed == NULL )
+ buf_packed =(void*)malloc( blocks * CONV_BLOCK_SIZE );
+ else
+ buf_packed =(void*)realloc(buf_packed,
+ blocks * CONV_BLOCK_SIZE);
+ assert( buf_packed );
+ if( buf_packed == NULL ) {
+ if( scrbuf != NULL )
+ atari_bitmap_destroy( scrbuf );
+ return( 0-ERR_NO_MEM );
+ }
+ size_buf_packed = blocks * CONV_BLOCK_SIZE;
+ }
+ out->fd_addr = buf_packed;
+ } else {
+ assert( out->fd_addr == NULL );
+ out->fd_addr = (void*)malloc( dstsize );
+ if( out->fd_addr == NULL ){
+ if( scrbuf != NULL )
+ atari_bitmap_destroy( scrbuf );
+ return( 0-ERR_NO_MEM );
+ }
+ }
+
+ out->fd_w = dststride;
+ out->fd_h = bh;
+ out->fd_wdwidth = dststride >> 4;
+ out->fd_stand = 0;
+ out->fd_nplanes = (short)atari_plot_bpp_virt;
+ out->fd_r1 = out->fd_r2 = out->fd_r3 = 0;
+
+ err = Hermes_ConverterRequest(
+ hermes_cnv_h,
+ &nsfmt,
+ &vfmt
+ );
+ assert( err != 0 );
+
+ // FIXME: here we can use the same optimization which is used for
+ // the snapshot creation.
+
+ /* convert image to virtual format: */
+ err = Hermes_ConverterCopy( hermes_cnv_h,
+ source->pixdata,
+ 0, /* x src coord of top left in pixel coords */
+ 0, /* y src coord of top left in pixel coords */
+ bw, bh,
+ source->rowstride, /* stride as bytes */
+ out->fd_addr,
+ 0, /* x dst coord of top left in pixel coords */
+ 0, /* y dst coord of top left in pixel coords */
+ bw, bh,
+ (dststride >> 3) * atari_plot_bpp_virt /* stride as bytes */
+ );
+ assert( err != 0 );
+
+ if( cache == true ){
+ img->native = *out;
+ img->converted = true;
+ }
+ return( 0 );
+
+}
+
+ inline static void convert_bitmap_done(void)
+{
+ if (size_buf_packed > CONV_KEEP_LIMIT) {
+ /* free the mem if it was an large allocation ... */
+ buf_packed = realloc(buf_packed, CONV_KEEP_LIMIT);
+ size_buf_packed = CONV_KEEP_LIMIT;
+ }
+}
+
+
+bool plot_blit_bitmap(struct bitmap * bmp, int x, int y,
+ unsigned long bg, unsigned long flags )
+{
+ MFDB src_mf;
+ MFDB scrmf;
+ short pxy[8];
+ GRECT off, clip, vis;
+ int screen_x, screen_y;
+
+ src_mf.fd_addr = NULL;
+ scrmf.fd_addr = NULL;
+
+ off.g_x = x;
+ off.g_y = y;
+ off.g_h = bmp->height;
+ off.g_w = bmp->width;
+
+ // clip plotter clip rectangle:
+ clip.g_x = view.clipping.x0;
+ clip.g_y = view.clipping.y0;
+ clip.g_w = view.clipping.x1 - view.clipping.x0;
+ clip.g_h = view.clipping.y1 - view.clipping.y0;
+
+ if( !rc_intersect( &clip, &off) ) {
+ return(true);
+ }
+
+ // clip the visible rectangle of the plot area
+ // this is the area of the plotter which falls into
+ // screen region:
+ plot_get_visible_grect(&vis);
+ if( !rc_intersect( &vis, &off) ) {
+ return(true);
+ }
+
+ screen_x = view.x + off.g_x;
+ screen_y = view.y + off.g_y;
+
+ // convert the clipping relative to bitmap:
+ off.g_x = off.g_x - x;
+ off.g_y = off.g_y - y;
+ assert( (off.g_x >= 0) && (off.g_y >= 0) );
+
+ /* Convert the Bitmap to native screen format - ready for output. */
+ /* This includes blending transparent pixels: */
+ if (bitmap_convert(bmp, screen_x, screen_y, &off, bg, flags, &src_mf)
+ != 0 ) {
+ return(true);
+ }
+
+ // setup the src region:
+ pxy[0] = off.g_x;
+ pxy[1] = off.g_y;
+ pxy[2] = off.g_x + off.g_w-1;
+ pxy[3] = off.g_y + off.g_h-1;
+
+ // setup the target region:
+ pxy[4] = screen_x;
+ pxy[5] = screen_y;
+ pxy[6] = screen_x + off.g_w-1;
+ pxy[7] = screen_y + off.g_h-1;
+
+ vro_cpyfm(atari_plot_vdi_handle, S_ONLY, (short*)&pxy, &src_mf, &scrmf);
+ convert_bitmap_done();
+ snapshot_suspend();
+ return(true);
+}
+
+bool plot_blit_mfdb(GRECT * loc, MFDB * insrc, short fgcolor,
+ uint32_t flags)
+{
+ MFDB screen;
+// MFDB tran;
+ MFDB * src;
+ short pxy[8];
+ short c[2] = {fgcolor, 0};
+ GRECT off;
+
+ plot_get_clip_grect(&off);
+ if( rc_intersect(loc, &off) == 0 ){
+ return( 1 );
+ }
+
+ init_mfdb( 0, loc->g_w, loc->g_h, 0, &screen );
+//
+// if( insrc->fd_stand){
+// printf("st\n");
+// int size = init_mfdb( insrc->fd_nplanes, loc->g_w, loc->g_h,
+// MFDB_FLAG_NOALLOC,
+// &tran
+// );
+// if( size_buf_scr == 0 ){
+// buf_scr.fd_addr = malloc( size );
+// size_buf_scr = size;
+// } else {
+// if( size > size_buf_scr ) {
+// buf_scr.fd_addr = realloc(
+// buf_scr.fd_addr, size
+// );
+// size_buf_scr = size;
+// }
+// }
+// tran.fd_addr = buf_scr.fd_addr;
+// vr_trnfm(atari_plot_vdi_handle, insrc, &tran );
+// src = &tran;
+// } else {
+ src = insrc;
+// }
+
+ pxy[0] = off.g_x - loc->g_x;
+ pxy[1] = off.g_y - loc->g_y;
+ pxy[2] = pxy[0] + off.g_w - 1;
+ pxy[3] = pxy[1] + off.g_h - 1;
+ pxy[4] = view.x + off.g_x;
+ pxy[5] = view.y + off.g_y;
+ pxy[6] = pxy[4] + off.g_w-1;
+ pxy[7] = pxy[5] + off.g_h-1;
+
+
+ if( flags & PLOT_FLAG_TRANS && src->fd_nplanes == 1){
+ vrt_cpyfm(atari_plot_vdi_handle, MD_REPLACE/*MD_TRANS*/, (short*)pxy, src, &screen, (short*)&c);
+ } else {
+ /* this method only plots transparent bitmaps, right now... */
+ }
+ return( 1 );
+}
+
+/*
+Init screen and font driver objects.
+Returns non-zero value > -1 when the objects could be succesfully created.
+Returns value < 0 to indicate an error
+*/
+
+int plot_init(char * fdrvrname)
+{
+
+ GRECT loc_pos= {0,0,360,400};
+ int err=0;
+
+ if( nsoption_int(atari_dither) == 1)
+ atari_plot_flags |= PLOT_FLAG_DITHER;
+ if( nsoption_int(atari_transparency) == 1 )
+ atari_plot_flags |= PLOT_FLAG_TRANS;
+ if( nsoption_int(atari_font_monochrom) == 1 )
+ atari_font_flags |= FONTPLOT_FLAG_MONOGLYPH;
+
+ if(atari_plot_vdi_handle == -1) {
+
+ short dummy;
+ short work_in[12] = {Getrez()+2,1,1,1,1,1,1,1,1,1,2,1};
+ short work_out[57];
+ atari_plot_vdi_handle=graf_handle(&dummy, &dummy, &dummy, &dummy);
+ v_opnvwk(work_in, &atari_plot_vdi_handle, work_out);
+ LOG("Plot VDI handle: %d", atari_plot_vdi_handle);
+ }
+ read_vdi_sysinfo(atari_plot_vdi_handle, &vdi_sysinfo);
+ if(verbose_log) {
+ dump_vdi_info(atari_plot_vdi_handle) ;
+ dump_font_drivers();
+ }
+
+ fplotter = new_font_plotter(atari_plot_vdi_handle, fdrvrname,
+ atari_font_flags, &err);
+ if(err) {
+ const char * desc = plot_err_str(err);
+ die(("Unable to load font plotter %s -> %s", fdrvrname, desc ));
+ }
+
+ memset(&view, 0, sizeof(struct s_view));
+ atari_plot_bpp_virt = vdi_sysinfo.scr_bpp;
+ view.x = loc_pos.g_x;
+ view.y = loc_pos.g_y;
+ view.w = loc_pos.g_w;
+ view.h = loc_pos.g_h;
+ size_buf_packed = 0;
+ size_buf_planar = 0;
+ buf_packed = NULL;
+ buf_planar = NULL;
+ if( vdi_sysinfo.vdiformat == VDI_FORMAT_PACK ) {
+ atari_plot_bpp_virt = vdi_sysinfo.scr_bpp;
+ } else {
+ atari_plot_bpp_virt = 8;
+ }
+
+ plot_set_scale(1.0);
+ update_visible_rect();
+
+ struct rect clip;
+ clip.x0 = 0;
+ clip.y0 = 0;
+ clip.x1 = view.w;
+ clip.y1 = view.h;
+ plot_clip(&clip);
+
+ assert(Hermes_Init());
+
+#ifdef WITH_8BPP_SUPPORT
+ bitmap_convert = (vdi_sysinfo.scr_bpp > 8) ? bitmap_convert_tc : bitmap_convert_8;
+
+ /* Setup color lookup tables and palette */
+ unsigned char rgbcol[4];
+ if( vdi_sysinfo.scr_bpp <= 8 ){
+ unsigned char graytone=0;
+ int i;
+ for( i=0; i<=255; i++ ) {
+
+ // get the current color and save it for restore:
+ vq_color(atari_plot_vdi_handle, i, 1, (unsigned short*)&sys_pal[i][0] );
+ if( i<OFFSET_WEB_PAL ) {
+ pal[i][0] = sys_pal[i][0];
+ pal[i][1] = sys_pal[i][1];
+ pal[i][2] = sys_pal[i][2];
+ } else if( vdi_sysinfo.scr_bpp >= 8 ) {
+ if ( i < OFFSET_CUST_PAL ){
+ pal[i][0] = vdi_web_pal[i-OFFSET_WEB_PAL][0];
+ pal[i][1] = vdi_web_pal[i-OFFSET_WEB_PAL][1];
+ pal[i][2] = vdi_web_pal[i-OFFSET_WEB_PAL][2];
+ //set the new palette color to websafe value:
+ vs_color(atari_plot_vdi_handle, i, &pal[i][0]);
+ }
+ if( i >= OFFSET_CUST_PAL && i<OFFSET_CUST_PAL+16 ) {
+ /* here we define 20 additional gray colors... */
+ rgbcol[1] = rgbcol[2] = rgbcol[3] = ((graytone&0x0F) << 4);
+ rgb_to_vdi1000( &rgbcol[0], &pal[i][0] );
+ vs_color(atari_plot_vdi_handle, i, &pal[i][0]);
+ graytone++;
+ }
+
+ }
+ vdi1000_to_rgb( &pal[i][0], &rgb_lookup[i][0] );
+ }
+
+ } else {
+ /* no need to change the palette - its application specific */
+ }
+#else
+ bitmap_convert = bitmap_convert_tc;
+#endif
+
+ /* Setup Hermes conversion handles */
+ unsigned long hermesflags = (atari_plot_flags & PLOT_FLAG_DITHER) ? HERMES_CONVERT_DITHER : 0;
+ hermes_cnv_h = Hermes_ConverterInstance(hermesflags);
+ assert( hermes_cnv_h );
+ hermes_res_h = Hermes_ConverterInstance(hermesflags);
+ assert( hermes_res_h );
+
+ /* set up the src & dst format: */
+ /* netsurf uses RGBA ... */
+ nsfmt.a = 0xFFUL;
+ nsfmt.b = 0x0FF00UL;
+ nsfmt.g = 0x0FF0000UL;
+ nsfmt.r = 0x0FF000000UL;
+ nsfmt.bits = 32;
+ nsfmt.indexed = false;
+ nsfmt.has_colorkey = false;
+
+ vfmt.r = vdi_sysinfo.mask_r;
+ vfmt.g = vdi_sysinfo.mask_g;
+ vfmt.b = vdi_sysinfo.mask_b;
+ vfmt.a = vdi_sysinfo.mask_a;
+ vfmt.bits = atari_plot_bpp_virt;
+ vfmt.indexed = (atari_plot_bpp_virt <= 8) ? 1 : 0;
+ vfmt.has_colorkey = 0;
+
+ return( err );
+}
+
+int plot_finalise( void )
+{
+
+ delete_font_plotter(fplotter);
+
+#ifdef WITH_8BPP_SUPPORT
+ if (vfmt.indexed) {
+ int i;
+ for (i=OFFSET_WEB_PAL; i<OFFSET_CUST_PAL+16; i++) {
+ vs_color(atari_plot_vdi_handle, i, &sys_pal[i][0]);
+ }
+ }
+#endif
+
+ /* close Hermes stuff: */
+ Hermes_ConverterReturn(hermes_cnv_h);
+ Hermes_Done();
+
+ /* free up temporary buffers */
+ free(buf_packed );
+ free(buf_planar);
+ snapshot_destroy();
+
+ return 0;
+}
+
+bool plot_lock(void)
+{
+ if ((atari_plot_flags & PLOT_FLAG_LOCKED) != 0)
+ return(true);
+ if( !wind_update(BEG_UPDATE|0x100) )
+ return(false);
+ if( !wind_update(BEG_MCTRL|0x100) ){
+ wind_update(END_UPDATE);
+ return(false);
+ }
+ atari_plot_flags |= PLOT_FLAG_LOCKED;
+ graf_mouse(M_OFF, NULL);
+ return(true);
+}
+
+bool plot_unlock(void)
+{
+ if( (atari_plot_flags & PLOT_FLAG_LOCKED) == 0 )
+ return(true);
+ wind_update(END_MCTRL);
+ wind_update(END_UPDATE);
+ graf_mouse(M_ON, NULL);
+ vs_clip_off(atari_plot_vdi_handle);
+ atari_plot_flags &= ~PLOT_FLAG_LOCKED;
+ return(false);
+}
+
+bool plot_rectangle(int x0, int y0, int x1, int y1,
+ const plot_style_t *pstyle )
+{
+ short pxy[4];
+ GRECT r, rclip, sclip;
+ int sw = pstyle->stroke_width;
+ uint32_t lt;
+
+ /* current canvas clip: */
+ rclip.g_x = view.clipping.x0;
+ rclip.g_y = view.clipping.y0;
+ rclip.g_w = view.clipping.x1 - view.clipping.x0;
+ rclip.g_h = view.clipping.y1 - view.clipping.y0;
+
+ /* physical clipping: */
+ sclip.g_x = rclip.g_x;
+ sclip.g_y = rclip.g_y;
+ sclip.g_w = view.vis_w;
+ sclip.g_h = view.vis_h;
+
+ rc_intersect(&sclip, &rclip);
+ r.g_x = x0;
+ r.g_y = y0;
+ r.g_w = x1 - x0;
+ r.g_h = y1 - y0;
+
+ if (!rc_intersect( &rclip, &r )) {
+ return(true);
+ }
+ if (pstyle->stroke_type != PLOT_OP_TYPE_NONE) {
+ /*
+ manually draw the line, because we do not need vdi clipping
+ for vertical / horizontal line draws.
+ */
+ if( sw == 0)
+ sw = 1;
+
+ NSLT2VDI(lt, pstyle);
+ vsl_type(atari_plot_vdi_handle, (lt&0x0F));
+ /*
+ if the line style is not available within VDI system,
+ define own style:
+ */
+ if( (lt&0x0F) == 7 ){
+ vsl_udsty(atari_plot_vdi_handle, ((lt&0xFFFF00) >> 8));
+ }
+ vsl_width(atari_plot_vdi_handle, (short)sw );
+ vsl_rgbcolor(atari_plot_vdi_handle, pstyle->stroke_colour);
+ /* top border: */
+ if( r.g_y == y0){
+ pxy[0] = view.x + r.g_x;
+ pxy[1] = view.y + r.g_y ;
+ pxy[2] = view.x + r.g_x + r.g_w;
+ pxy[3] = view.y + r.g_y;
+ v_pline(atari_plot_vdi_handle, 2, (short *)&pxy);
+ }
+
+ /* right border: */
+ if( r.g_x + r.g_w == x1 ){
+ pxy[0] = view.x + r.g_x + r.g_w;
+ pxy[1] = view.y + r.g_y;
+ pxy[2] = view.x + r.g_x + r.g_w;
+ pxy[3] = view.y + r.g_y + r.g_h;
+ v_pline(atari_plot_vdi_handle, 2, (short *)&pxy);
+ }
+
+ /* bottom border: */
+ if( r.g_y+r.g_h == y1 ){
+ pxy[0] = view.x + r.g_x;
+ pxy[1] = view.y + r.g_y+r.g_h;
+ pxy[2] = view.x + r.g_x+r.g_w;
+ pxy[3] = view.y + r.g_y+r.g_h;
+ v_pline(atari_plot_vdi_handle, 2, (short *)&pxy);
+ }
+
+ /* left border: */
+ if( r.g_x == x0 ){
+ pxy[0] = view.x + r.g_x;
+ pxy[1] = view.y + r.g_y;
+ pxy[2] = view.x + r.g_x;
+ pxy[3] = view.y + r.g_y + r.g_h;
+ v_pline(atari_plot_vdi_handle, 2, (short *)&pxy);
+ }
+ }
+
+ if( pstyle->fill_type != PLOT_OP_TYPE_NONE ){
+ short stroke_width = (short)(pstyle->stroke_type != PLOT_OP_TYPE_NONE) ?
+ pstyle->stroke_width : 0;
+
+ vsf_rgbcolor(atari_plot_vdi_handle, pstyle->fill_colour);
+ vsf_perimeter(atari_plot_vdi_handle, 0);
+ vsf_interior(atari_plot_vdi_handle, FIS_SOLID);
+
+
+ pxy[0] = view.x + r.g_x + stroke_width;
+ pxy[1] = view.y + r.g_y + stroke_width;
+ pxy[2] = view.x + r.g_x + r.g_w -1 - stroke_width;
+ pxy[3] = view.y + r.g_y + r.g_h -1 - stroke_width;
+
+ vsf_style(atari_plot_vdi_handle, 1);
+ v_bar(atari_plot_vdi_handle, (short*)&pxy);
+ }
+ return (true);
+}
+
+bool plot_line(int x0, int y0, int x1, int y1,
+ const plot_style_t *pstyle )
+{
+ short pxy[4];
+ uint32_t lt;
+ int sw = pstyle->stroke_width;
+
+ if((x0 < 0 && x1 < 0) || (y0 < 0 && y1 < 0)){
+ return(true);
+ }
+
+ pxy[0] = view.x + MAX(0,x0);
+ pxy[1] = view.y + MAX(0,y0);
+ pxy[2] = view.x + MAX(0,x1);
+ pxy[3] = view.y + MAX(0,y1);
+
+ if((y0 > view.h-1) && (y1 > view.h-1))
+ return(true);
+
+ //printf("view: %d,%d,%d,%d\n", view.x, view.y, view.w, view.h);
+ //printf("line: %d,%d,%d,%d\n", x0, y0, x1, y1);
+
+
+ //plot_vdi_clip(true);
+ if( sw == 0)
+ sw = 1;
+ NSLT2VDI(lt, pstyle)
+ vsl_type(atari_plot_vdi_handle, (lt&0x0F));
+ /* if the line style is not available within VDI system,define own style: */
+ if( (lt&0x0F) == 7 ){
+ vsl_udsty(atari_plot_vdi_handle, ((lt&0xFFFF00) >> 8));
+ }
+ vsl_width(atari_plot_vdi_handle, (short)sw);
+ vsl_rgbcolor(atari_plot_vdi_handle, pstyle->stroke_colour);
+ v_pline(atari_plot_vdi_handle, 2, (short *)&pxy );
+ //plot_vdi_clip(false);
+ return (true);
+}
+
+static bool plot_polygon(const int *p, unsigned int n,
+ const plot_style_t *pstyle)
+{
+ short pxy[n*2];
+ unsigned int i=0;
+ if (vdi_sysinfo.maxpolycoords > 0)
+ assert( (signed int)n < vdi_sysinfo.maxpolycoords);
+
+ vsf_interior(atari_plot_vdi_handle, FIS_SOLID);
+ vsf_style(atari_plot_vdi_handle, 1);
+ for (i = 0; i<n*2; i=i+2) {
+ pxy[i] = (short)view.x+p[i];
+ pxy[i+1] = (short)view.y+p[i+1];
+ }
+ if (pstyle->fill_type == PLOT_OP_TYPE_SOLID) {
+ vsf_rgbcolor(atari_plot_vdi_handle, pstyle->fill_colour);
+ v_fillarea(atari_plot_vdi_handle, n, (short*)&pxy);
+ } else {
+ pxy[n*2]=pxy[0];
+ pxy[n*2+1]=pxy[1];
+ vsl_rgbcolor(atari_plot_vdi_handle, pstyle->stroke_colour);
+ v_pline(atari_plot_vdi_handle, n+1, (short *)&pxy);
+ }
+
+ return ( true );
+}
+
+/***
+ * Set plot origin and canvas size
+ * \param x the x origin
+ * \param y the y origin
+ * \param w the width of the plot area
+ * \param h the height of the plot area
+ */
+bool plot_set_dimensions(int x, int y, int w, int h)
+{
+ bool doupdate = false;
+ struct rect newclip = {0, 0, w, h};
+ GRECT absclip = {x, y, w, h};
+
+ if (!(w == view.w && h == view.h)) {
+ view.w = (short)w;
+ view.h = (short)h;
+ doupdate = true;
+ }
+ if (!(x == view.x && y == view.y)) {
+ view.x = (short)x;
+ view.y = (short)y;
+ doupdate = true;
+ }
+ if (doupdate==true)
+ update_visible_rect();
+
+ //dbg_rect("plot_set_dimensions", &newclip);
+
+ plot_set_abs_clipping(&absclip);
+ plot_clip(&newclip);
+ return(true);
+}
+
+/***
+ * Get current canvas size
+ * \param dst the GRECT * which receives the canvas size
+ *
+ */
+bool plot_get_dimensions(GRECT *dst)
+{
+ dst->g_x = view.x;
+ dst->g_y = view.y;
+ dst->g_w = view.w;
+ dst->g_h = view.h;
+ return(true);
+}
+
+/**
+ * set scale of plotter.
+ * \param scale the new scale value
+ * \return the old scale value
+ */
+
+float plot_set_scale(float scale)
+{
+ float ret = view.scale;
+
+ view.scale = scale;
+
+ return(ret);
+}
+
+float plot_get_scale(void)
+{
+ return(view.scale);
+}
+
+
+/**
+ *
+ * Subsequent calls to plot_clip will be clipped by the absolute clip.
+ * \param area the maximum clipping rectangle (absolute screen coords)
+ *
+*/
+void plot_set_abs_clipping(const GRECT *area)
+{
+ GRECT canvas;
+
+ plot_get_dimensions(&canvas);
+
+ if(!rc_intersect(area, &canvas)){
+ view.abs_clipping.x0 = 0;
+ view.abs_clipping.x1 = 0;
+ view.abs_clipping.y0 = 0;
+ view.abs_clipping.y1 = 0;
+ }
+ else {
+ view.abs_clipping.x0 = area->g_x;
+ view.abs_clipping.x1 = area->g_x + area->g_w;
+ view.abs_clipping.y0 = area->g_y;
+ view.abs_clipping.y1 = area->g_y + area->g_h;
+ }
+}
+
+
+/***
+ * Get the maximum clip extent, in absolute screen coords
+ * \param dst the structure that receives the absolute clipping
+ */
+void plot_get_abs_clipping(struct rect *dst)
+{
+ *dst = view.abs_clipping;
+}
+
+
+/***
+ * Get the maximum clip extent, in absolute screen coords
+ * \param dst the structure that receives the absolute clipping
+ */
+void plot_get_abs_clipping_grect(GRECT *dst)
+{
+ dst->g_x = view.abs_clipping.x0;
+ dst->g_w = view.abs_clipping.x1 - view.abs_clipping.x0;
+ dst->g_y = view.abs_clipping.y0;
+ dst->g_h = view.abs_clipping.y1 - view.abs_clipping.y0;
+}
+
+bool plot_clip(const struct rect *clip)
+{
+ GRECT canvas, screen, gclip, maxclip;
+ short pxy[4];
+
+ screen.g_x = 0;
+ screen.g_y = 0;
+ screen.g_w = vdi_sysinfo.scr_w;
+ screen.g_h = vdi_sysinfo.scr_h;
+
+ plot_get_dimensions(&canvas);
+
+ view.clipping.y0 = clip->y0;
+ view.clipping.y1 = clip->y1;
+ view.clipping.x0 = clip->x0;
+ view.clipping.x1 = clip->x1;
+
+ plot_get_clip_grect(&gclip);
+
+ gclip.g_x += canvas.g_x;
+ gclip.g_y += canvas.g_y;
+
+ rc_intersect(&canvas, &gclip);
+
+ if(gclip.g_h < 0){
+ gclip.g_h = 0;
+ }
+
+ if (!rc_intersect(&screen, &gclip)) {
+ //dbg_rect("cliprect: ", &view.clipping);
+ //dbg_grect("screen: ", &canvas);
+ //dbg_grect("canvas clipped: ", &gclip);
+ //assert(1 == 0);
+ }
+
+ // When setting VDI clipping, obey to maximum cliping rectangle:
+ plot_get_abs_clipping_grect(&maxclip);
+ rc_intersect(&maxclip, &gclip);
+
+ //dbg_grect("canvas clipped to screen", &gclip);
+
+ pxy[0] = gclip.g_x;
+ pxy[1] = gclip.g_y;
+ pxy[2] = pxy[0] + gclip.g_w;
+ pxy[3] = pxy[1] + gclip.g_h;
+
+ vs_clip(atari_plot_vdi_handle, 1, (short*)&pxy);
+
+ return ( true );
+}
+
+VdiHdl plot_get_vdi_handle(void)
+{
+ return(atari_plot_vdi_handle);
+}
+
+long plot_get_flags(void)
+{
+ return(atari_plot_flags);
+}
+
+
+bool plot_get_clip(struct rect * out)
+{
+ out->x0 = view.clipping.x0;
+ out->y0 = view.clipping.y0;
+ out->x1 = view.clipping.x1;
+ out->y1 = view.clipping.y1;
+ return( true );
+}
+
+void plot_get_clip_grect(GRECT * out)
+{
+ struct rect clip={0,0,0,0};
+
+ plot_get_clip(&clip);
+
+ out->g_x = clip.x0;
+ out->g_y = clip.y0;
+ out->g_w = clip.x1 - clip.x0;
+ out->g_h = clip.y1 - clip.y0;
+}
+
+FONT_PLOTTER plot_get_text_plotter()
+{
+ return(fplotter);
+}
+
+void plot_set_text_plotter(FONT_PLOTTER font_plotter)
+{
+ fplotter = font_plotter;
+}
+
+static bool plot_text(int x, int y, const char *text, size_t length, const plot_font_style_t *fstyle )
+{
+ if (view.scale != 1.0) {
+ plot_font_style_t newstyle = *fstyle;
+ newstyle.size = (int)((float)fstyle->size*view.scale);
+ fplotter->text(fplotter, x, y, text, length, &newstyle);
+ } else {
+ fplotter->text(fplotter, x, y, text, length, fstyle);
+ }
+
+ return ( true );
+}
+
+static bool plot_disc(int x, int y, int radius, const plot_style_t *pstyle)
+{
+ if (pstyle->fill_type != PLOT_OP_TYPE_SOLID) {
+ vsf_rgbcolor(atari_plot_vdi_handle, pstyle->stroke_colour);
+ vsf_perimeter(atari_plot_vdi_handle, 1);
+ vsf_interior(atari_plot_vdi_handle, 0);
+ v_circle(atari_plot_vdi_handle, view.x + x, view.y + y, radius);
+ } else {
+ vsf_rgbcolor(atari_plot_vdi_handle, pstyle->fill_colour);
+ vsf_perimeter(atari_plot_vdi_handle, 0);
+ vsf_interior(atari_plot_vdi_handle, FIS_SOLID);
+ v_circle(atari_plot_vdi_handle, view.x + x, view.y + y, radius);
+ }
+
+ return(true);
+}
+
+static bool plot_arc(int x, int y, int radius, int angle1, int angle2,
+ const plot_style_t *pstyle)
+{
+
+ vswr_mode(atari_plot_vdi_handle, MD_REPLACE );
+ if (pstyle->fill_type == PLOT_OP_TYPE_NONE)
+ return(true);
+ if ( pstyle->fill_type != PLOT_OP_TYPE_SOLID) {
+ vsl_rgbcolor(atari_plot_vdi_handle, pstyle->stroke_colour);
+ vsf_perimeter(atari_plot_vdi_handle, 1);
+ vsf_interior(atari_plot_vdi_handle, 1 );
+ v_arc(atari_plot_vdi_handle, view.x + x, view.y + y, radius, angle1*10, angle2*10);
+ } else {
+ vsf_rgbcolor(atari_plot_vdi_handle, pstyle->fill_colour);
+ vsl_width(atari_plot_vdi_handle, 1 );
+ vsf_perimeter(atari_plot_vdi_handle, 1);
+ v_arc(atari_plot_vdi_handle, view.x + x, view.y + y, radius, angle1*10, angle2*10);
+ }
+
+ return (true);
+}
+
+static bool plot_bitmap(int x, int y, int width, int height,
+ struct bitmap *bitmap, colour bg,
+ bitmap_flags_t flags)
+{
+ struct bitmap * bm = NULL;
+ bool repeat_x = (flags & BITMAPF_REPEAT_X);
+ bool repeat_y = (flags & BITMAPF_REPEAT_Y);
+ int bmpw,bmph;
+ struct rect clip = {0,0,0,0};
+
+ bmpw = atari_bitmap_get_width(bitmap);
+ bmph = atari_bitmap_get_height(bitmap);
+
+ if(view.scale != 1.0){
+ width = (int)(((float)width)*view.scale);
+ height = (int)(((float)height)*view.scale);
+ }
+
+ if ( repeat_x || repeat_y ) {
+ plot_get_clip(&clip);
+ if( repeat_x && width == 1 && repeat_y && height == 1 ) {
+ width = MAX( width, clip.x1 - x );
+ height = MAX( height, clip.y1 - y );
+ } else if( repeat_x && width == 1 ) {
+ width = MAX( width, clip.x1 - x);
+ } else if( repeat_y && height == 1) {
+ height = MAX( height, clip.y1 - y );
+ }
+ }
+
+ if( width != bmpw || height != bmph ) {
+ atari_bitmap_resize(bitmap, hermes_res_h, &nsfmt, width, height );
+ if( bitmap->resized )
+ bm = bitmap->resized;
+ else
+ bm = bitmap;
+ } else {
+ bm = bitmap;
+ }
+
+ /* out of memory? */
+ if( bm == NULL ) {
+ printf("plot: out of memory! bmp: %p, bmpres: %p\n", bitmap, bitmap->resized );
+ return( true );
+ }
+
+ if (!(repeat_x || repeat_y) ) {
+ plot_blit_bitmap(bm, x, y, bg, flags );
+ } else {
+ int xf,yf;
+ int xoff = x;
+ int yoff = y;
+
+ if (yoff > clip.y0 )
+ yoff = (clip.y0 - height) + ((yoff - clip.y0) % height);
+ if (xoff > clip.x0 )
+ xoff = (clip.x0 - width) + ((xoff - clip.x0) % width);
+ /* for now, repeating just works in the rigth / down direction */
+ /*
+ if( repeat_x == true )
+ xoff = clip.x0;
+ if(repeat_y == true )
+ yoff = clip.y0;
+ */
+
+ for( xf = xoff; xf < clip.x1; xf += width ) {
+ for( yf = yoff; yf < clip.y1; yf += height ) {
+ plot_blit_bitmap(bm, xf, yf, bg, flags );
+ if (!repeat_y)
+ break;
+ }
+ if (!repeat_x)
+ break;
+ }
+ }
+ return ( true );
+}
+
+static bool plot_path(const float *p, unsigned int n, colour fill, float width,
+ colour c, const float transform[6])
+{
+ return ( true );
+}
+
+
+
+const struct plotter_table atari_plotters = {
+ .rectangle = plot_rectangle,
+ .line = plot_line,
+ .polygon = plot_polygon,
+ .clip = plot_clip,
+ .text = plot_text,
+ .disc = plot_disc,
+ .arc = plot_arc,
+ .bitmap = plot_bitmap,
+ .path = plot_path,
+ .flush = NULL,
+ .group_start = NULL,
+ .group_end = NULL,
+ .option_knockout = true
+};
diff --git a/frontends/atari/plot/plot.h b/frontends/atari/plot/plot.h
new file mode 100644
index 000000000..22f8781c2
--- /dev/null
+++ b/frontends/atari/plot/plot.h
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.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 NS_ATARI_PLOT_H
+#define NS_ATARI_PLOT_H
+
+/** how much memory should be kept allocated for temp. conversion bitmaps: */
+#define CONV_KEEP_LIMIT 512000
+
+/** how much memory to allocate if some is needed: */
+#define CONV_BLOCK_SIZE 32000
+
+/* Plotter Option Flags: */
+#define PLOT_FLAG_DITHER 0x04 /**< set if the plotter shall dither images */
+#define PLOT_FLAG_TRANS 0x08 /**< set if the plotter supports transparent operations */
+
+/* Plotter "feature" flags */
+#define PLOT_FLAG_HAS_DITHER 0x0400
+#define PLOT_FLAG_HAS_ALPHA 0x0800
+#define PLOT_FLAG_OFFSCREEN 0x1000 /**< offscreen plotter should set this flag */
+
+/* Plotter "internal" flags */
+#define PLOT_FLAG_LOCKED 0x08000 /**< plotter should set this flag during screen updates */
+
+/* Font Plotter flags: */
+#define FONTPLOT_FLAG_MONOGLYPH 0x01
+
+/* Flags for init_mfdb function: */
+#define MFDB_FLAG_STAND 0x01
+#define MFDB_FLAG_ZEROMEM 0x02
+#define MFDB_FLAG_NOALLOC 0x04
+
+/* Flags for blit functions: */
+#define BITMAPF_MONOGLYPH 4096 /**< The bitmap is an character bitmap */
+#define BITMAPF_BUFFER_NATIVE 8192 /**< Bitmap shall be kept converted */
+
+/* Error codes: */
+#define ERR_BUFFERSIZE_EXCEEDS_SCREEN 1 /* The buffer allocated is larger than the screen */
+#define ERR_NO_MEM 2 /* Not enough memory for requested operation */
+#define ERR_PLOTTER_NOT_AVAILABLE 3 /* invalid plotter driver name passed */
+
+struct s_vdi_sysinfo {
+ short vdi_handle; /**< vdi handle */
+ short scr_w; /**< resolution horz. */
+ short scr_h; /**< resolution vert. */
+ short scr_bpp; /**< bits per pixel */
+ int colors; /**< 0=hiclor, 2=mono */
+ unsigned long hicolors; /**< if colors = 0 */
+ short pixelsize; /**< bytes per pixel */
+ unsigned short pitch; /**< row pitch */
+ unsigned short vdiformat; /**< pixel format */
+ unsigned short clut; /**< type of clut support */
+ void *screen; /**< pointer to screen, or NULL */
+ unsigned long screensize; /**< size of screen (in bytes) */
+ unsigned long mask_r; /**< red color mask */
+ unsigned long mask_g; /**< green color mask */
+ unsigned long mask_b; /**< blue color mask */
+ unsigned long mask_a; /**< alpha color mask */
+ short maxintin; /* maximum pxy items */
+ short maxpolycoords; /* max coords for p_line etc. */
+ unsigned long EdDiVersion; /* EdDi Version or 0 */
+ bool rasterscale; /* raster scaling support */
+};
+
+struct rect;
+
+extern const struct plotter_table atari_plotters;
+
+int plot_init(char *);
+int plot_finalise(void);
+
+/**
+ * translate an error number
+ */
+const char* plot_err_str(int i) ;
+
+bool plot_lock(void);
+bool plot_unlock(void);
+bool plot_set_dimensions( int x, int y, int w, int h );
+bool plot_get_dimensions(GRECT *dst);
+float plot_get_scale(void);
+float plot_set_scale(float);
+void plot_set_abs_clipping(const GRECT *area);
+void plot_get_abs_clipping(struct rect *dst);
+void plot_get_abs_clipping_grect(GRECT *dst);
+bool plot_get_clip(struct rect * out);
+/* Get clipping for current framebuffer as GRECT */
+void plot_get_clip_grect(GRECT * out);
+bool plot_clip(const struct rect *clip);
+VdiHdl plot_get_vdi_handle(void);
+long plot_get_flags(void);
+bool plot_rectangle( int x0, int y0, int x1, int y1,const plot_style_t *style );
+bool plot_line( int x0, int y0, int x1, int y1, const plot_style_t *style );
+bool plot_blit_bitmap(struct bitmap * bmp, int x, int y,
+ unsigned long bg, unsigned long flags);
+bool plot_blit_mfdb(GRECT * loc, MFDB * insrc, short fgcolor, uint32_t flags);
+bool plot_copy_rect(GRECT src, GRECT dst);
+
+/* convert an vdi color to bgra */
+void vdi1000_to_rgb( unsigned short * in, unsigned char * out );
+
+/* convert an bgra color to vdi1000 color */
+void rgb_to_vdi1000( unsigned char * in, RGB1000 *out);
+
+/* convert an rgb color to an index into the web palette */
+short rgb_to_666_index(unsigned char r, unsigned char g, unsigned char b);
+
+/* assign vdi line style to dst ( netsurf type ) */
+#define NSLT2VDI(dst, src) \
+ dst = 0; \
+ switch( src->stroke_type ) { \
+ case PLOT_OP_TYPE_DOT: \
+ dst = (0xAAAA00 | 7); \
+ break; \
+ case PLOT_OP_TYPE_DASH: \
+ dst = 3; \
+ break; \
+ case PLOT_OP_TYPE_SOLID: \
+ case PLOT_OP_TYPE_NONE: \
+ default: \
+ dst = 1; \
+ break; \
+ }
+
+
+#ifdef WITH_8BPP_SUPPORT
+/* some Well known indexes into the VDI palette */
+/* common indexes into the VDI palette */
+/* (only used when running with 256 colors or less ) */
+#define OFFSET_WEB_PAL 16
+#define OFFSET_CUST_PAL 232
+#define RGB_TO_VDI(c) rgb_to_666_index( (c&0xFF),(c&0xFF00)>>8,(c&0xFF0000)>>16)+OFFSET_WEB_PAL
+#endif /* WITH_8BPP_SUPPORT*/
+
+/* the name of this macro is crap - it should be named bgr_to_rgba ... or so */
+#define ABGR_TO_RGB(c) ( ((c&0xFF)<<16) | (c&0xFF00) | ((c&0xFF0000)>>16) ) << 8
+
+/* this index into the palette is used by the TC renderer to set
+ * current draw color.
+ */
+#define OFFSET_CUSTOM_COLOR 255
+
+#endif
diff --git a/frontends/atari/redrawslots.c b/frontends/atari/redrawslots.c
new file mode 100644
index 000000000..f5351866a
--- /dev/null
+++ b/frontends/atari/redrawslots.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2011 Ole Loots <ole@monochrom.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/utils.h"
+
+#include "atari/redrawslots.h"
+#include "atari/gemtk/gemtk.h"
+
+void redraw_slots_init(struct s_redrw_slots * slots, short size)
+{
+ // TODO: allocate slots dynamically!
+ slots->size = MIN( MAX_REDRW_SLOTS , size);
+ slots->areas_used = 0;
+}
+
+void redraw_slots_free(struct s_redrw_slots * slots)
+{
+ // TOOD: free areas...
+}
+
+
+static inline bool rect_intersect( struct rect * box1, struct rect * box2 )
+{
+ if (box2->x1 < box1->x0)
+ return false;
+
+ if (box2->y1 < box1->y0)
+ return false;
+
+ if (box2->x0 > box1->x1)
+ return false;
+
+ if (box2->y0 > box1->y1)
+ return false;
+
+ return true;
+}
+
+
+void redraw_slot_schedule_grect(struct s_redrw_slots * slots, GRECT *area,
+ bool force)
+{
+ redraw_slot_schedule(slots, area->g_x, area->g_y,
+ area->g_x + area->g_w, area->g_y + area->g_h, force);
+}
+
+/*
+ schedule redraw coords.
+*/
+void redraw_slot_schedule(struct s_redrw_slots * slots, short x0, short y0,
+ short x1, short y1, bool force)
+{
+ int i = 0;
+ struct rect area;
+
+ area.x0 = x0;
+ area.y0 = y0;
+ area.x1 = x1;
+ area.y1 = y1;
+
+ if (force == false) {
+ for (i=0; i<slots->areas_used; i++) {
+ if (slots->areas[i].x0 <= x0
+ && slots->areas[i].x1 >= x1
+ && slots->areas[i].y0 <= y0
+ && slots->areas[i].y1 >= y1) {
+ /* the area is already queued for redraw */
+ return;
+ } else {
+ if (rect_intersect(&slots->areas[i], &area )) {
+ slots->areas[i].x0 = MIN(slots->areas[i].x0, x0);
+ slots->areas[i].y0 = MIN(slots->areas[i].y0, y0);
+ slots->areas[i].x1 = MAX(slots->areas[i].x1, x1);
+ slots->areas[i].y1 = MAX(slots->areas[i].y1, y1);
+ return;
+ }
+ }
+ }
+ }
+
+ if (slots->areas_used < slots->size) {
+ slots->areas[slots->areas_used].x0 = x0;
+ slots->areas[slots->areas_used].x1 = x1;
+ slots->areas[slots->areas_used].y0 = y0;
+ slots->areas[slots->areas_used].y1 = y1;
+ slots->areas_used++;
+ } else {
+ /*
+ we are out of available slots, merge box with last slot
+ this is dumb... but also a very rare case.
+ */
+ slots->areas[slots->size-1].x0 = MIN(slots->areas[i].x0, x0);
+ slots->areas[slots->size-1].y0 = MIN(slots->areas[i].y0, y0);
+ slots->areas[slots->size-1].x1 = MAX(slots->areas[i].x1, x1);
+ slots->areas[slots->size-1].y1 = MAX(slots->areas[i].y1, y1);
+ }
+
+ return;
+}
+
+void redraw_slots_remove_area(struct s_redrw_slots * slots, int i)
+{
+ int x;
+ for (x = i+1; i<slots->areas_used; x++) {
+ slots->areas[x-1] = slots->areas[x];
+ }
+ slots->areas_used--;
+}
diff --git a/frontends/atari/redrawslots.h b/frontends/atari/redrawslots.h
new file mode 100644
index 000000000..ca72a0172
--- /dev/null
+++ b/frontends/atari/redrawslots.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2012 Ole Loots <ole@monochrom.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 ATARI_REDRAW_SLOTS_H
+#define ATARI_REDRAW_SLOTS_H
+
+#include <mt_gem.h>
+
+#include "utils/utils.h"
+
+/**
+ * This is the number of redraw requests that the slotlist can store.
+ * If a redraw is scheduled and all slots are used, the rectangle will
+ * be merged to one of the existing slots.
+ */
+#define MAX_REDRW_SLOTS 32
+
+struct rect;
+
+/**
+ * This struct holds scheduled redraw requests.
+ */
+struct s_redrw_slots
+{
+ struct rect areas[MAX_REDRW_SLOTS];
+ short size;
+ short volatile areas_used;
+};
+
+void redraw_slots_init(struct s_redrw_slots * slots, short size);
+void redraw_slot_schedule(struct s_redrw_slots * slots, short x0, short y0,
+ short x1, short y1, bool force);
+void redraw_slot_schedule_grect(struct s_redrw_slots * slots, GRECT *area,
+ bool force);
+void redraw_slots_remove_area(struct s_redrw_slots * slots, int i);
+void redraw_slots_free(struct s_redrw_slots * slots);
+
+#endif
diff --git a/frontends/atari/res/blank b/frontends/atari/res/blank
new file mode 100644
index 000000000..f21f228a1
--- /dev/null
+++ b/frontends/atari/res/blank
@@ -0,0 +1,39 @@
+<html>
+ <head>
+ <title>Blankpage</title>
+ </head>
+ <body>
+ <h1>Welcome to NetSurf!</h1>
+ </body>
+</html>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ \ No newline at end of file
diff --git a/frontends/atari/res/favicon.ico b/frontends/atari/res/favicon.ico
new file mode 100644
index 000000000..8b26a278f
--- /dev/null
+++ b/frontends/atari/res/favicon.ico
Binary files differ
diff --git a/frontends/atari/res/icons/toolbar/atfact/main.png b/frontends/atari/res/icons/toolbar/atfact/main.png
new file mode 100644
index 000000000..64cf3bc54
--- /dev/null
+++ b/frontends/atari/res/icons/toolbar/atfact/main.png
Binary files differ
diff --git a/frontends/atari/res/icons/toolbar/atfact/throbber.png b/frontends/atari/res/icons/toolbar/atfact/throbber.png
new file mode 100644
index 000000000..44d949a1c
--- /dev/null
+++ b/frontends/atari/res/icons/toolbar/atfact/throbber.png
Binary files differ
diff --git a/frontends/atari/res/icons/toolbar/default/main.png b/frontends/atari/res/icons/toolbar/default/main.png
new file mode 100644
index 000000000..964218076
--- /dev/null
+++ b/frontends/atari/res/icons/toolbar/default/main.png
Binary files differ
diff --git a/frontends/atari/res/icons/toolbar/default/main.xcf b/frontends/atari/res/icons/toolbar/default/main.xcf
new file mode 100644
index 000000000..48d6d168c
--- /dev/null
+++ b/frontends/atari/res/icons/toolbar/default/main.xcf
Binary files differ
diff --git a/frontends/atari/res/icons/toolbar/default/throbber.png b/frontends/atari/res/icons/toolbar/default/throbber.png
new file mode 100644
index 000000000..be3bf9949
--- /dev/null
+++ b/frontends/atari/res/icons/toolbar/default/throbber.png
Binary files differ
diff --git a/frontends/atari/res/icons/toolbar/default/throbber.xcf b/frontends/atari/res/icons/toolbar/default/throbber.xcf
new file mode 100644
index 000000000..18646c9c9
--- /dev/null
+++ b/frontends/atari/res/icons/toolbar/default/throbber.xcf
Binary files differ
diff --git a/frontends/atari/res/languages b/frontends/atari/res/languages
new file mode 100644
index 000000000..4927e03a0
--- /dev/null
+++ b/frontends/atari/res/languages
@@ -0,0 +1,261 @@
+aa
+ab
+ae
+af
+ak
+am
+an
+ar
+ar-ae
+ar-bh
+ar-dz
+ar-eg
+ar-iq
+ar-jo
+ar-kw
+ar-lb
+ar-ly
+ar-ma
+ar-om
+ar-qa
+ar-sa
+ar-sy
+ar-tn
+ar-ye
+as
+ast
+av
+az
+ba
+be
+bg
+bh
+bi
+bm
+bn
+bo
+br
+bs
+ca
+ce
+ch
+co
+cr
+cs
+cu
+cv
+cy
+da
+de
+de-at
+de-ch
+de-de
+de-li
+de-lu
+dv
+dz
+ee
+el
+en
+en-au
+en-bz
+en-ca
+en-gb
+en-ie
+en-jm
+en-nz
+en-ph
+en-tt
+en-us
+en-za
+en-zw
+eo
+es
+es-ar
+es-bo
+es-cl
+es-co
+es-cr
+es-do
+es-ec
+es-es
+es-gt
+es-hn
+es-mx
+es-ni
+es-pa
+es-pe
+es-pr
+es-py
+es-sv
+es-uy
+es-ve
+et
+eu
+fa
+fa-ir
+ff
+fi
+fj
+fo
+fr
+fr-be
+fr-ca
+fr-ch
+fr-fr
+fr-lu
+fr-mc
+fur
+fy
+ga
+gd
+gl
+gn
+gu
+gv
+ha
+he
+hi
+ho
+hsb
+hr
+ht
+hu
+hy
+hz
+ia
+id
+ie
+ig
+ii
+ik
+io
+is
+it
+it-ch
+iu
+ja
+jv
+ka
+kg
+ki
+kk
+kl
+km
+kn
+ko
+ko-kp
+ko-kr
+kok
+kr
+ks
+ku
+kv
+kw
+ky
+la
+lb
+lg
+li
+ln
+lo
+lt
+lu
+lv
+mg
+mh
+mi
+mk
+mk-mk
+ml
+mn
+mo
+mr
+ms
+mt
+my
+na
+nb
+nd
+ne
+ng
+nl
+nl-be
+nn
+no
+nr
+nso
+nv
+ny
+oc
+oj
+om
+or
+os
+pa
+pa-in
+pa-pk
+pi
+pl
+ps
+pt
+pt-br
+qu
+rm
+rn
+ro
+ro-mo
+ru
+ru-mo
+sa
+sc
+sd
+sg
+si
+sk
+sl
+so
+sq
+sr
+ss
+st
+su
+sv
+sv-fi
+sv-se
+sw
+ta
+te
+tg
+th
+ti
+tig
+tk
+tl
+tlh
+tn
+to
+tr
+ts
+tt
+tw
+ty
+ug
+uk
+ur
+uz
+ve
+vi
+vo
+wa
+wo
+xh
+yi
+yo
+za
+zh
+zh-cn
+zh-hk
+zh-sg
+zh-tw
+zu
diff --git a/frontends/atari/res/netsurf.rsc b/frontends/atari/res/netsurf.rsc
new file mode 100755
index 000000000..9c7d8dd74
--- /dev/null
+++ b/frontends/atari/res/netsurf.rsc
Binary files differ
diff --git a/frontends/atari/res/netsurf.rsh b/frontends/atari/res/netsurf.rsh
new file mode 100755
index 000000000..c856501ae
--- /dev/null
+++ b/frontends/atari/res/netsurf.rsh
@@ -0,0 +1,241 @@
+ /* Resource C-Header-File v1.97 fr ResourceMaster ab v2.06 by ARDISOFT */
+
+#define TOOLBAR 0 /* form/dial */
+#define TOOLBAR_AREA_SEARCH 1 /* BOX in tree TOOLBAR */
+#define TOOLBAR_BT_SEARCH_FWD 2 /* BUTTON in tree TOOLBAR */
+#define TOOLBAR_BT_SEARCH_BACK 3 /* BUTTON in tree TOOLBAR */
+#define TOOLBAR_CB_CASESENSE 5 /* BUTTON in tree TOOLBAR */
+#define TOOLBAR_CB_SHOWALL 6 /* BUTTON in tree TOOLBAR */
+#define TOOLBAR_TB_SRCH 7 /* FTEXT in tree TOOLBAR */
+#define TOOLBAR_SEARCH_ALIGN_RIGHT 8 /* IBOX in tree TOOLBAR */
+#define TOOLBAR_BT_CLOSE_SEARCH 9 /* BUTTON in tree TOOLBAR */
+#define TOOLBAR_AREA_NAVIGATION 10 /* BOX in tree TOOLBAR */
+#define TOOLBAR_AREA_URL 11 /* USERDEF in tree TOOLBAR */
+#define TOOLBAR_AREA_RIGHT 12 /* IBOX in tree TOOLBAR */
+#define TOOLBAR_THROBBER_AREA 13 /* IBOX in tree TOOLBAR */
+#define TOOLBAR_AREA_LEFT 14 /* IBOX in tree TOOLBAR */
+#define TOOLBAR_BT_BACK 15 /* CICON in tree TOOLBAR */
+#define TOOLBAR_BT_HOME 16 /* CICON in tree TOOLBAR */
+#define TOOLBAR_BT_FORWARD 17 /* CICON in tree TOOLBAR */
+#define TOOLBAR_BT_STOP 18 /* CICON in tree TOOLBAR */
+#define TOOLBAR_BT_RELOAD 19 /* CICON in tree TOOLBAR */
+
+#define ICONIFY 1 /* form/dial */
+#define ICONIFY_GLOBE 1 /* CICON in tree ICONIFY */
+
+#define FAVICON 2 /* form/dial */
+
+#define CURSOR 3 /* form/dial */
+#define CURSOR_HELP 1 /* ICON in tree CURSOR */
+#define CURSOR_NODROP 2 /* ICON in tree CURSOR */
+#define CURSOR_APPSTART 3 /* ICON in tree CURSOR */
+#define CURSOR_DENY 4 /* ICON in tree CURSOR */
+#define CURSOR_SIZEWE 5 /* ICON in tree CURSOR */
+#define CURSOR_SIZENS 6 /* ICON in tree CURSOR */
+#define CURSOR_MENU 7 /* ICON in tree CURSOR */
+
+#define LOGIN 4 /* form/dial */
+#define LOGIN_TB_USER 2 /* FTEXT in tree LOGIN */
+#define LOGIN_TB_PASSWORD 4 /* FTEXT in tree LOGIN */
+#define LOGIN_BT_LOGIN 5 /* BUTTON in tree LOGIN */
+#define LOGIN_BT_ABORT 6 /* BUTTON in tree LOGIN */
+
+#define THROBBER 5 /* form/dial */
+
+#define TOOLBAR_HOTLIST 6 /* form/dial */
+#define TOOLBAR_HOTLIST_ADD 1 /* CICON in tree TOOLBAR_HOTLIST */
+#define TOOLBAR_HOTLIST_CREATE_FOLDER 2 /* CICON in tree TOOLBAR_HOTLIST */
+#define TOOLBAR_HOTLIST_DELETE 3 /* CICON in tree TOOLBAR_HOTLIST */
+#define TOOLBAR_HOTLIST_EDIT 4 /* CICON in tree TOOLBAR_HOTLIST */
+
+#define SEARCH 7 /* form/dial */
+#define SEARCH_BT_SEARCH 1 /* BUTTON in tree SEARCH */
+#define SEARCH_CB_FWD 2 /* BUTTON in tree SEARCH */
+#define SEARCH_BT_SEARCH_BACK 3 /* BUTTON in tree SEARCH */
+#define SEARCH_CB_CASESENSE 5 /* BOXCHAR in tree SEARCH */
+#define SEARCH_CB_SHOWALL 6 /* BOXCHAR in tree SEARCH */
+#define SEARCH_LBL_SHOWALL 7 /* STRING in tree SEARCH */
+#define SEARCH_LBL_CASESENSE 8 /* TEXT in tree SEARCH */
+#define SEARCH_TB_SRCH 9 /* FTEXT in tree SEARCH */
+
+#define DOWNLOAD 8 /* form/dial */
+/* Width ist 400, code depends on that! If you change it, change it in download.c */
+#define DOWNLOAD_PROGRESS 1 /* BOX in tree DOWNLOAD */
+#define DOWNLOAD_PROGRESS_DONE 2 /* BOX in tree DOWNLOAD */
+#define DOWNLOAD_FILENAME 3 /* TEXT in tree DOWNLOAD */
+#define DOWNLOAD_BT_ABORT 4 /* BUTTON in tree DOWNLOAD */
+#define DOWNLOAD_LBL_CLOSE_RDY 5 /* STRING in tree DOWNLOAD */
+#define DOWNLOAD_LBL_BYTES 6 /* TEXT in tree DOWNLOAD */
+#define DOWNLOAD_LBL_PERCENT 7 /* TEXT in tree DOWNLOAD */
+#define DOWNLOAD_LBL_SPEED 8 /* TEXT in tree DOWNLOAD */
+#define DOWNLOAD_CB_CLOSE_RDY 9 /* BOXCHAR in tree DOWNLOAD */
+
+#define ABOUT 9 /* form/dial */
+#define ABOUT_LBL_VERSION 1 /* TEXT in tree ABOUT */
+#define ABOUT_OK 4 /* BUTTON in tree ABOUT */
+#define ABOUT_CONTENT 6 /* USERDEF in tree ABOUT */
+#define ABOUT_CREDITS 7 /* BUTTON in tree ABOUT */
+#define ABOUT_LICENSE 8 /* BUTTON in tree ABOUT */
+
+#define POP_CTX 10 /* form/dial */
+#define POP_CTX_CUT_SEL 1 /* TEXT in tree POP_CTX */
+#define POP_CTX_COPY_SEL 2 /* TEXT in tree POP_CTX */
+#define POP_CTX_PASTE_SEL 3 /* TEXT in tree POP_CTX */
+#define POP_CTX_SELECT_ALL 4 /* TEXT in tree POP_CTX */
+#define POP_CTX_OPEN_NEW 6 /* TEXT in tree POP_CTX */
+#define POP_CTX_COPY_LINK 7 /* TEXT in tree POP_CTX */
+#define POP_CTX_COPY_URL 8 /* TEXT in tree POP_CTX */
+#define POP_CTX_SAVE_AS 9 /* TEXT in tree POP_CTX */
+#define POP_CTX_VIEW_SOURCE 10 /* TEXT in tree POP_CTX */
+#define POP_CTX_SAVE_LINK_AS 11 /* TEXT in tree POP_CTX */
+
+#define VSCROLLER 11 /* form/dial */
+#define VSCROLLER_AREA 1 /* BOX in tree VSCROLLER */
+#define VSCROLLER_SLIDER_AREA 2 /* BUTTON in tree VSCROLLER */
+#define VSCROLLER_SLIDER 3 /* BUTTON in tree VSCROLLER */
+#define VSCROLLER_BT_DOWN 7 /* IBOX in tree VSCROLLER */
+#define VSCROLLER_BT_DOWN_PIC 5 /* CICON in tree VSCROLLER */
+#define VSCROLLER_BT_UP 6 /* IBOX in tree VSCROLLER */
+#define VSCROLLER_BT_UP_PIC 4 /* CICON in tree VSCROLLER */
+
+#define POP_LANGUAGE 12 /* form/dial */
+#define POP_LANGUAGE_CS 1 /* STRING in tree POP_LANGUAGE */
+#define POP_LANGUAGE_DE 2 /* STRING in tree POP_LANGUAGE */
+#define POP_LANGUAGE_EN 3 /* STRING in tree POP_LANGUAGE */
+#define POP_LANGUAGE_EN_GB 4 /* STRING in tree POP_LANGUAGE */
+#define POP_LANGUAGE_DE_DE 5 /* STRING in tree POP_LANGUAGE */
+#define POP_LANGUAGE_EN_US 6 /* STRING in tree POP_LANGUAGE */
+#define POP_LANGUAGE_ES 7 /* STRING in tree POP_LANGUAGE */
+#define POP_LANGUAGE_FR 8 /* STRING in tree POP_LANGUAGE */
+#define POP_LANGUAGE_IT 9 /* STRING in tree POP_LANGUAGE */
+#define POP_LANGUAGE_NL 10 /* STRING in tree POP_LANGUAGE */
+#define POP_LANGUAGE_NO 11 /* STRING in tree POP_LANGUAGE */
+#define POP_LANGUAGE_PL 12 /* STRING in tree POP_LANGUAGE */
+#define POP_LANGUAGE_RU 13 /* STRING in tree POP_LANGUAGE */
+#define POP_LANGUAGE_SK 14 /* STRING in tree POP_LANGUAGE */
+#define POP_LANGUAGE_SV 15 /* STRING in tree POP_LANGUAGE */
+
+#define POP_FONT_RENDERER 13 /* form/dial */
+#define POP_FONT_RENDERER_INTERNAL 1 /* STRING in tree POP_FONT_RENDERER */
+#define POP_FONT_RENDERER_FREETYPE 2 /* STRING in tree POP_FONT_RENDERER */
+
+#define TOOLBAR_COOKIES 14 /* form/dial */
+
+#define TOOLBAR_HISTORY 15 /* form/dial */
+
+#define TOOLBAR_SSL_CERT 16 /* form/dial */
+#define TOOLBAR_SSL_CERT_TRUSTED 1 /* BUTTON in tree TOOLBAR_SSL_CERT */
+
+#define SETTINGS 17 /* form/dial */
+#define SETTINGS_EDIT_DOWNLOAD_PATH 3 /* FTEXT in tree SETTINGS */
+#define SETTINGS_EDIT_HOTLIST_FILE 4 /* FTEXT in tree SETTINGS */
+#define SETTINGS_EDIT_CA_BUNDLE 5 /* FTEXT in tree SETTINGS */
+#define SETTINGS_EDIT_CA_CERTS_PATH 6 /* FTEXT in tree SETTINGS */
+#define SETTINGS_EDIT_EDITOR 7 /* FTEXT in tree SETTINGS */
+#define SETTINGS_BT_SEL_DOWNLOAD_DIR 12 /* BUTTON in tree SETTINGS */
+#define SETTINGS_BT_SEL_HOTLIST 13 /* BUTTON in tree SETTINGS */
+#define SETTINGS_BT_SEL_CA_BUNDLE 14 /* BUTTON in tree SETTINGS */
+#define SETTINGS_BT_SEL_CA_CERTS 15 /* BUTTON in tree SETTINGS */
+#define SETTINGS_BT_SEL_EDITOR 16 /* BUTTON in tree SETTINGS */
+/* Make sure that initial value is large enough! */
+#define SETTINGS_BT_SEL_FONT_RENDERER 19 /* BUTTON in tree SETTINGS */
+#define SETTINGS_CB_ANTI_ALIASING 20 /* BUTTON in tree SETTINGS */
+#define SETTINGS_CB_TRANSPARENCY 21 /* BUTTON in tree SETTINGS */
+#define SETTINGS_EDIT_DEF_FONT_SIZE 24 /* FTEXT in tree SETTINGS */
+#define SETTINGS_DEC_DEF_FONT_SIZE 25 /* BOXCHAR in tree SETTINGS */
+#define SETTINGS_INC_DEF_FONT_SIZE 26 /* BOXCHAR in tree SETTINGS */
+#define SETTINGS_EDIT_MIN_FONT_SIZE 28 /* FTEXT in tree SETTINGS */
+#define SETTINGS_DEC_MIN_FONT_SIZE 29 /* BOXCHAR in tree SETTINGS */
+#define SETTINGS_INC_MIN_FONT_SIZE 30 /* BOXCHAR in tree SETTINGS */
+#define SETTINGS_EDIT_MIN_GIF_DELAY 35 /* FTEXT in tree SETTINGS */
+#define SETTINGS_INC_GIF_DELAY 36 /* BOXCHAR in tree SETTINGS */
+#define SETTINGS_DEC_GIF_DELAY 37 /* BOXCHAR in tree SETTINGS */
+#define SETTINGS_CB_ENABLE_ANIMATION 40 /* BUTTON in tree SETTINGS */
+#define SETTINGS_CB_BG_IMAGES 42 /* BUTTON in tree SETTINGS */
+#define SETTINGS_CB_FG_IMAGES 44 /* BUTTON in tree SETTINGS */
+#define SETTINGS_EDIT_MIN_REFLOW_PERIOD 47 /* FTEXT in tree SETTINGS */
+#define SETTINGS_DEC_INCREMENTAL_REFLOW 48 /* BOXCHAR in tree SETTINGS */
+#define SETTINGS_INC_INCREMENTAL_REFLOW 49 /* BOXCHAR in tree SETTINGS */
+#define SETTINGS_CB_USE_PROXY 51 /* BUTTON in tree SETTINGS */
+#define SETTINGS_EDIT_PROXY_HOST 52 /* FTEXT in tree SETTINGS */
+#define SETTINGS_EDIT_PROXY_PORT 54 /* FTEXT in tree SETTINGS */
+#define SETTINGS_CB_PROXY_AUTH 55 /* BUTTON in tree SETTINGS */
+#define SETTINGS_EDIT_PROXY_USERNAME 56 /* FTEXT in tree SETTINGS */
+#define SETTINGS_EDIT_PROXY_PASSWORD 57 /* FTEXT in tree SETTINGS */
+#define SETTINGS_EDIT_MAX_FETCHERS 62 /* FTEXT in tree SETTINGS */
+#define SETTINGS_INC_MAX_FETCHERS 63 /* BOXCHAR in tree SETTINGS */
+#define SETTINGS_DEC_MAX_FETCHERS 64 /* BOXCHAR in tree SETTINGS */
+#define SETTINGS_DEC_MAX_FETCHERS_PER_HOST 66 /* BOXCHAR in tree SETTINGS */
+#define SETTINGS_EDIT_MAX_FETCHERS_PER_HOST 67 /* FTEXT in tree SETTINGS */
+#define SETTINGS_INC_MAX_FETCHERS_PER_HOST 68 /* BOXCHAR in tree SETTINGS */
+#define SETTINGS_DEC_CACHED_CONNECTIONS 70 /* BOXCHAR in tree SETTINGS */
+#define SETTINGS_EDIT_MAX_CACHED_CONNECTIONS 71 /* FTEXT in tree SETTINGS */
+#define SETTINGS_INC_CACHED_CONNECTIONS 72 /* BOXCHAR in tree SETTINGS */
+#define SETTINGS_EDIT_HOMEPAGE 74 /* FTEXT in tree SETTINGS */
+#define SETTINGS_CB_HIDE_ADVERTISEMENT 75 /* BUTTON in tree SETTINGS */
+#define SETTINGS_CB_DISABLE_POPUP_WINDOWS 76 /* BUTTON in tree SETTINGS */
+#define SETTINGS_CB_SEND_HTTP_REFERRER 77 /* BUTTON in tree SETTINGS */
+#define SETTINGS_CB_SEND_DO_NOT_TRACK 78 /* BUTTON in tree SETTINGS */
+#define SETTINGS_BT_CLEAR_HISTORY 80 /* BUTTON in tree SETTINGS */
+#define SETTINGS_BT_SEL_LOCALE 82 /* BUTTON in tree SETTINGS */
+#define SETTINGS_BT_GUI_LANG 84 /* BUTTON in tree SETTINGS */
+#define SETTINGS_INC_MEM_CACHE 87 /* BOXCHAR in tree SETTINGS */
+#define SETTINGS_DEC_MEM_CACHE 88 /* BOXCHAR in tree SETTINGS */
+#define SETTINGS_STR_MAX_MEM_CACHE 89 /* FTEXT in tree SETTINGS */
+#define SETTINGS_DEC_HISTORY_AGE 92 /* BOXCHAR in tree SETTINGS */
+#define SETTINGS_EDIT_HISTORY_AGE 93 /* FTEXT in tree SETTINGS */
+#define SETTINGS_INC_HISTORY_AGE 94 /* BOXCHAR in tree SETTINGS */
+#define SETTINGS_BT_GUI_TOUT 97 /* BUTTON in tree SETTINGS */
+#define SETTINGS_INC_DISC_CACHE 101 /* BOXCHAR in tree SETTINGS */
+#define SETTINGS_DEC_DISC_CACHE 102 /* BOXCHAR in tree SETTINGS */
+#define SETTINGS_STR_MAX_DISC_CACHE 103 /* FTEXT in tree SETTINGS */
+#define SETTINGS_BT_CLEAR_CACHE 105 /* BUTTON in tree SETTINGS */
+#define SETTINGS_INC_CACHE_AGE 107 /* BOXCHAR in tree SETTINGS */
+#define SETTINGS_DEC_CACHE_AGE 108 /* BOXCHAR in tree SETTINGS */
+#define SETTINGS_EDIT_CACHE_AGE 110 /* FTEXT in tree SETTINGS */
+
+#define MAINMENU 18 /* menu */
+#define MAINMENU_T_FILE 4 /* TITLE in tree MAINMENU */
+#define MAINMENU_T_EDIT 5 /* TITLE in tree MAINMENU */
+#define MAINMENU_T_VIEW 6 /* TITLE in tree MAINMENU */
+#define MAINMENU_T_NAVIGATE 7 /* TITLE in tree MAINMENU */
+#define MAINMENU_T_UTIL 8 /* TITLE in tree MAINMENU */
+#define MAINMENU_T_HELP 9 /* TITLE in tree MAINMENU */
+#define MAINMENU_M_ABOUT 12 /* STRING in tree MAINMENU */
+#define MAINMENU_M_NEWWIN 21 /* STRING in tree MAINMENU */
+#define MAINMENU_M_OPENFILE 22 /* STRING in tree MAINMENU */
+#define MAINMENU_M_OPENURL 23 /* STRING in tree MAINMENU */
+#define MAINMENU_M_CLOSEWIN 24 /* STRING in tree MAINMENU */
+#define MAINMENU_SEP0 25 /* STRING in tree MAINMENU */
+#define MAINMENU_M_SAVEPAGE 26 /* STRING in tree MAINMENU */
+#define MAINMENU_SEP1 27 /* STRING in tree MAINMENU */
+#define MAINMENU_M_QUIT 28 /* STRING in tree MAINMENU */
+#define MAINMENU_M_CUT 30 /* STRING in tree MAINMENU */
+#define MAINMENU_M_COPY 31 /* STRING in tree MAINMENU */
+#define MAINMENU_M_PASTE 32 /* STRING in tree MAINMENU */
+#define MAINMENU_SEP3 33 /* STRING in tree MAINMENU */
+#define MAINMENU_M_FIND 34 /* STRING in tree MAINMENU */
+#define MAINMENU_M_STOP 36 /* STRING in tree MAINMENU */
+#define MAINMENU_M_RELOAD 37 /* STRING in tree MAINMENU */
+#define MAINMENU_INC_SCALE 39 /* STRING in tree MAINMENU */
+#define MAINMENU_DEC_SCALE 40 /* STRING in tree MAINMENU */
+#define MAINMENU_M_TOOLBARS 42 /* STRING in tree MAINMENU */
+#define MAINMENU_M_SAVEWIN 44 /* STRING in tree MAINMENU */
+#define MAINMENU_M_DEBUG_RENDER 45 /* STRING in tree MAINMENU */
+#define MAINMENU_M_BG_IMAGES 46 /* STRING in tree MAINMENU */
+#define MAINMENU_M_FG_IMAGES 47 /* STRING in tree MAINMENU */
+#define MAINMENU_M_BACK 49 /* STRING in tree MAINMENU */
+#define MAINMENU_M_FORWARD 50 /* STRING in tree MAINMENU */
+#define MAINMENU_M_HOME 51 /* STRING in tree MAINMENU */
+#define MAINMENU_M_LHISTORY 53 /* STRING in tree MAINMENU */
+#define MAINMENU_M_GHISTORY 54 /* STRING in tree MAINMENU */
+#define MAINMENU_M_ADD_BOOKMARK 56 /* STRING in tree MAINMENU */
+#define MAINMENU_M_BOOKMARKS 57 /* STRING in tree MAINMENU */
+#define MAINMENU_M_COOKIES 59 /* STRING in tree MAINMENU */
+#define MAINMENU_M_CHOICES 61 /* STRING in tree MAINMENU */
+#define MAINMENU_M_VLOG 62 /* STRING in tree MAINMENU */
+#define MAINMENU_M_HELP_CONTENT 64 /* STRING in tree MAINMENU */
+
+#define TOOLBAR_SETTINGS 19 /* form/dial */
+#define TOOLBAR_SETTINGS_ABORT 1 /* BOXTEXT in tree TOOLBAR_SETTINGS */
+#define TOOLBAR_SETTINGS_SAVE 2 /* BOXTEXT in tree TOOLBAR_SETTINGS */
diff --git a/frontends/atari/res/netsurf.rsm b/frontends/atari/res/netsurf.rsm
new file mode 100755
index 000000000..6c240d371
--- /dev/null
+++ b/frontends/atari/res/netsurf.rsm
@@ -0,0 +1,225 @@
+ResourceMaster v3.651
+#C 20@0@0@0@
+#N 99@32@AZAaza___ _@AZAaza090___ _@@_@
+#FoC-Header@rsm2out@C-Header@rsh@@@[C-Header@0@
+#R 0@0@1@1@2@1@
+#M 11110100@0@7728@671@
+#T 0@2@TOOLBAR@@20@@
+#O 1@20@AREA_SEARCH@@
+#O 2@26@BT_SEARCH_FWD@@
+#O 3@26@BT_SEARCH_BACK@@
+#O 5@26@CB_CASESENSE@@
+#O 6@26@CB_SHOWALL@@
+#O 7@29@TB_SRCH@@
+#O 8@25@SEARCH_ALIGN_RIGHT@@
+#O 9@26@BT_CLOSE_SEARCH@@
+#O 10@20@AREA_NAVIGATION@@
+#O 11@24@AREA_URL@@
+#O 12@25@AREA_RIGHT@@
+#O 13@25@THROBBER_AREA@@
+#O 14@25@AREA_LEFT@@
+#O 15@33@BT_BACK@@
+#O 16@33@BT_HOME@@
+#O 17@33@BT_FORWARD@@
+#O 18@33@BT_STOP@@
+#O 19@33@BT_RELOAD@@
+#T 1@2@ICONIFY@@3@@
+#O 1@33@GLOBE@@
+#T 2@2@FAVICON@@2@@
+#T 3@2@CURSOR@@8@@
+#O 1@31@HELP@@
+#O 2@31@NODROP@@
+#O 3@31@APPSTART@@
+#O 4@31@DENY@@
+#O 5@31@SIZEWE@@
+#O 6@31@SIZENS@@
+#O 7@31@MENU@@
+#T 4@2@LOGIN@@7@@
+#O 2@29@TB_USER@@
+#O 4@29@TB_PASSWORD@@
+#O 5@26@BT_LOGIN@@
+#O 6@26@BT_ABORT@@
+#T 5@2@THROBBER@@14@@
+#T 6@2@TOOLBAR_HOTLIST@@5@@
+#O 1@33@ADD@@
+#O 2@33@CREATE_FOLDER@@
+#O 3@33@DELETE@@
+#O 4@33@EDIT@@
+#T 7@2@SEARCH@@10@@
+#O 1@26@BT_SEARCH@@
+#O 2@26@CB_FWD@@
+#O 3@26@BT_SEARCH_BACK@@
+#O 5@27@CB_CASESENSE@@
+#O 6@27@CB_SHOWALL@@
+#O 7@28@LBL_SHOWALL@@
+#O 8@21@LBL_CASESENSE@@
+#O 9@29@TB_SRCH@@
+#T 8@2@DOWNLOAD@@10@@
+#O 1@20@PROGRESS@Width ist 400, code depends on that! If you change it, change it in download.c@
+#O 2@20@PROGRESS_DONE@@
+#O 3@21@FILENAME@@
+#O 4@26@BT_ABORT@@
+#O 5@28@LBL_CLOSE_RDY@@
+#O 6@21@LBL_BYTES@@
+#O 7@21@LBL_PERCENT@@
+#O 8@21@LBL_SPEED@@
+#O 9@27@CB_CLOSE_RDY@@
+#T 9@2@ABOUT@@9@@
+#O 1@21@LBL_VERSION@@
+#O 4@26@OK@@
+#O 6@24@CONTENT@@
+#O 7@26@CREDITS@@
+#O 8@26@LICENSE@@
+#T 10@2@POP_CTX@@12@@
+#O 1@21@CUT_SEL@@
+#O 2@21@COPY_SEL@@
+#O 3@21@PASTE_SEL@@
+#O 4@21@SELECT_ALL@@
+#O 6@21@OPEN_NEW@@
+#O 7@21@COPY_LINK@@
+#O 8@21@COPY_URL@@
+#O 9@21@SAVE_AS@@
+#O 10@21@VIEW_SOURCE@@
+#O 11@21@SAVE_LINK_AS@@
+#T 11@2@VSCROLLER@@8@@
+#O 1@20@AREA@@
+#O 2@26@SLIDER_AREA@@
+#O 3@26@SLIDER@@
+#O 7@25@BT_DOWN@@
+#O 5@33@BT_DOWN_PIC@@
+#O 6@25@BT_UP@@
+#O 4@33@BT_UP_PIC@@
+#T 12@2@POP_LANGUAGE@@16@@
+#O 1@28@CS@@
+#O 2@28@DE@@
+#O 3@28@EN@@
+#O 4@28@EN_GB@@
+#O 5@28@DE_DE@@
+#O 6@28@EN_US@@
+#O 7@28@ES@@
+#O 8@28@FR@@
+#O 9@28@IT@@
+#O 10@28@NL@@
+#O 11@28@NO@@
+#O 12@28@PL@@
+#O 13@28@RU@@
+#O 14@28@SK@@
+#O 15@28@SV@@
+#T 13@2@POP_FONT_RENDERER@@3@@
+#O 1@28@INTERNAL@@
+#O 2@28@FREETYPE@@
+#T 14@2@TOOLBAR_COOKIES@@1@@
+#T 15@2@TOOLBAR_HISTORY@@1@@
+#T 16@2@TOOLBAR_SSL_CERT@@2@@
+#O 1@26@TRUSTED@@
+#T 17@2@SETTINGS@@112@@
+#O 3@29@EDIT_DOWNLOAD_PATH@@
+#O 4@29@EDIT_HOTLIST_FILE@@
+#O 5@29@EDIT_CA_BUNDLE@@
+#O 6@29@EDIT_CA_CERTS_PATH@@
+#O 7@29@EDIT_EDITOR@@
+#O 12@26@BT_SEL_DOWNLOAD_DIR@@
+#O 13@26@BT_SEL_HOTLIST@@
+#O 14@26@BT_SEL_CA_BUNDLE@@
+#O 15@26@BT_SEL_CA_CERTS@@
+#O 16@26@BT_SEL_EDITOR@@
+#O 19@26@BT_SEL_FONT_RENDERER@Make sure that initial value is large enough!@
+#O 20@26@CB_ANTI_ALIASING@@
+#O 21@26@CB_TRANSPARENCY@@
+#O 24@29@EDIT_DEF_FONT_SIZE@@
+#O 25@27@DEC_DEF_FONT_SIZE@@
+#O 26@27@INC_DEF_FONT_SIZE@@
+#O 28@29@EDIT_MIN_FONT_SIZE@@
+#O 29@27@DEC_MIN_FONT_SIZE@@
+#O 30@27@INC_MIN_FONT_SIZE@@
+#O 35@29@EDIT_MIN_GIF_DELAY@@
+#O 36@27@INC_GIF_DELAY@@
+#O 37@27@DEC_GIF_DELAY@@
+#O 40@26@CB_ENABLE_ANIMATION@@
+#O 42@26@CB_BG_IMAGES@@
+#O 44@26@CB_FG_IMAGES@@
+#O 47@29@EDIT_MIN_REFLOW_PERIOD@@
+#O 48@27@DEC_INCREMENTAL_REFLOW@@
+#O 49@27@INC_INCREMENTAL_REFLOW@@
+#O 51@26@CB_USE_PROXY@@
+#O 52@29@EDIT_PROXY_HOST@@
+#O 54@29@EDIT_PROXY_PORT@@
+#O 55@26@CB_PROXY_AUTH@@
+#O 56@29@EDIT_PROXY_USERNAME@@
+#O 57@29@EDIT_PROXY_PASSWORD@@
+#O 62@29@EDIT_MAX_FETCHERS@@
+#O 63@27@INC_MAX_FETCHERS@@
+#O 64@27@DEC_MAX_FETCHERS@@
+#O 66@27@DEC_MAX_FETCHERS_PER_HOST@@
+#O 67@29@EDIT_MAX_FETCHERS_PER_HOST@@
+#O 68@27@INC_MAX_FETCHERS_PER_HOST@@
+#O 70@27@DEC_CACHED_CONNECTIONS@@
+#O 71@29@EDIT_MAX_CACHED_CONNECTIONS@@
+#O 72@27@INC_CACHED_CONNECTIONS@@
+#O 74@29@EDIT_HOMEPAGE@@
+#O 75@26@CB_HIDE_ADVERTISEMENT@@
+#O 76@26@CB_DISABLE_POPUP_WINDOWS@@
+#O 77@26@CB_SEND_HTTP_REFERRER@@
+#O 78@26@CB_SEND_DO_NOT_TRACK@@
+#O 80@26@BT_CLEAR_HISTORY@@
+#O 82@26@BT_SEL_LOCALE@@
+#O 84@26@BT_GUI_LANG@@
+#O 87@27@INC_MEM_CACHE@@
+#O 88@27@DEC_MEM_CACHE@@
+#O 89@29@STR_MAX_MEM_CACHE@@
+#O 92@27@DEC_HISTORY_AGE@@
+#O 93@29@EDIT_HISTORY_AGE@@
+#O 94@27@INC_HISTORY_AGE@@
+#O 97@26@BT_GUI_TOUT@@
+#O 101@27@INC_DISC_CACHE@@
+#O 102@27@DEC_DISC_CACHE@@
+#O 103@29@STR_MAX_DISC_CACHE@@
+#O 105@26@BT_CLEAR_CACHE@@
+#O 107@27@INC_CACHE_AGE@@
+#O 108@27@DEC_CACHE_AGE@@
+#O 110@29@EDIT_CACHE_AGE@@
+#T 18@1@MAINMENU@@65@@
+#O 4@32@T_FILE@@
+#O 5@32@T_EDIT@@
+#O 6@32@T_VIEW@@
+#O 7@32@T_NAVIGATE@@
+#O 8@32@T_UTIL@@
+#O 9@32@T_HELP@@
+#O 12@28@M_ABOUT@@
+#O 21@28@M_NEWWIN@@
+#O 22@28@M_OPENFILE@@
+#O 23@28@M_OPENURL@@
+#O 24@28@M_CLOSEWIN@@
+#O 25@28@SEP0@@
+#O 26@28@M_SAVEPAGE@@
+#O 27@28@SEP1@@
+#O 28@28@M_QUIT@@
+#O 30@28@M_CUT@@
+#O 31@28@M_COPY@@
+#O 32@28@M_PASTE@@
+#O 33@28@SEP3@@
+#O 34@28@M_FIND@@
+#O 36@28@M_STOP@@
+#O 37@28@M_RELOAD@@
+#O 39@28@INC_SCALE@@
+#O 40@28@DEC_SCALE@@
+#O 42@28@M_TOOLBARS@@
+#O 44@28@M_SAVEWIN@@
+#O 45@28@M_DEBUG_RENDER@@
+#O 46@28@M_BG_IMAGES@@
+#O 47@28@M_FG_IMAGES@@
+#O 49@28@M_BACK@@
+#O 50@28@M_FORWARD@@
+#O 51@28@M_HOME@@
+#O 53@28@M_LHISTORY@@
+#O 54@28@M_GHISTORY@@
+#O 56@28@M_ADD_BOOKMARK@@
+#O 57@28@M_BOOKMARKS@@
+#O 59@28@M_COOKIES@@
+#O 61@28@M_CHOICES@@
+#O 62@28@M_VLOG@@
+#O 64@28@M_HELP_CONTENT@@
+#T 19@2@TOOLBAR_SETTINGS@@3@@
+#O 1@22@ABORT@@
+#O 2@22@SAVE@@
+#c 10775@
diff --git a/frontends/atari/rootwin.c b/frontends/atari/rootwin.c
new file mode 100644
index 000000000..605ce45ae
--- /dev/null
+++ b/frontends/atari/rootwin.c
@@ -0,0 +1,1540 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.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/>.
+ *
+ * Module Description:
+ *
+ * This File implements the NetSurf Browser window, or passed functionality to
+ * the appropriate widget's.
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <math.h>
+#include <osbind.h>
+
+#include <mt_gem.h>
+
+#include "utils/log.h"
+#include "desktop/browser.h"
+#include "desktop/mouse.h"
+#include "desktop/plotters.h"
+#include "desktop/textinput.h"
+#include "content/content.h"
+#include "content/hlcache.h"
+#include "content/urldb.h"
+
+#include "atari/res/netsurf.rsh"
+#include "atari/gemtk/gemtk.h"
+#include "atari/ctxmenu.h"
+#include "atari/gui.h"
+#include "atari/rootwin.h"
+#include "atari/misc.h"
+#include "atari/plot/plot.h"
+#include "atari/toolbar.h"
+#include "atari/statusbar.h"
+#include "atari/search.h"
+#include "atari/osspec.h"
+#include "atari/encoding.h"
+#include "atari/redrawslots.h"
+#include "atari/toolbar.h"
+#include "atari/findfile.h"
+#include "atari/bitmap.h"
+
+extern struct gui_window *input_window;
+extern EVMULT_OUT aes_event_out;
+extern GRECT desk_area;
+
+struct rootwin_data_s {
+ struct s_gui_win_root *rootwin;
+};
+
+/* -------------------------------------------------------------------------- */
+/* Static module event handlers */
+/* -------------------------------------------------------------------------- */
+static void on_redraw(ROOTWIN *rootwin, short msg[8]);
+static void on_resized(ROOTWIN *rootwin);
+static void on_file_dropped(ROOTWIN *rootwin, short msg[8]);
+static short on_window_key_input(ROOTWIN * rootwin, unsigned short nkc);
+static void on_content_mouse_click(ROOTWIN *rootwin);
+static void on_content_mouse_move(ROOTWIN *rootwin, GRECT *content_area);
+static void toolbar_redraw_cb(GUIWIN *win, uint16_t msg, GRECT *clip);
+
+bool gui_window_get_scroll(struct gui_window *w, int *sx, int *sy);
+
+static bool redraw_active = false;
+
+static const struct redraw_context rootwin_rdrw_ctx = {
+ .interactive = true,
+ .background_images = true,
+ .plot = &atari_plotters
+};
+
+static short handle_event(GUIWIN *win, EVMULT_OUT *ev_out, short msg[8])
+{
+ short retval = 0;
+ GRECT area;
+ static bool prev_url = false;
+ struct rootwin_data_s * data = gemtk_wm_get_user_data(win);
+ struct gui_window *tmp;
+
+
+ if ((ev_out->emo_events & MU_MESAG) != 0) {
+ // handle message
+ //printf("root win msg: %d\n", msg[0]);
+ switch (msg[0]) {
+
+ case WM_REDRAW:
+ LOG("WM_REDRAW");
+ on_redraw(data->rootwin, msg);
+ break;
+
+ case WM_REPOSED:
+ case WM_SIZED:
+ case WM_MOVED:
+ case WM_FULLED:
+ LOG("WM_SIZED");
+ on_resized(data->rootwin);
+ break;
+
+ case WM_ICONIFY:
+ // TODO: find next active gui window and schedule redraw for that.
+ tmp = window_list;
+ while(tmp != NULL){
+ if(tmp->root != data->rootwin){
+ gemtk_wm_send_msg(tmp->root->win, WM_TOPPED, 0, 0, 0, 0);
+ break;
+ }
+ tmp = tmp->next;
+ }
+ break;
+
+ case WM_TOPPED:
+ case WM_NEWTOP:
+ case WM_UNICONIFY:
+ LOG("WM_TOPPED");
+ gui_set_input_gui_window(data->rootwin->active_gui_window);
+ //window_restore_active_gui_window(data->rootwin);
+ // TODO: use something like "restore_active_gui_window_state()"
+
+ break;
+
+ case WM_CLOSED:
+ // TODO: this needs to iterate through all gui windows and
+ // check if the rootwin is this window...
+ if (data->rootwin->active_gui_window != NULL) {
+ LOG("WM_CLOSED initiated destroy for bw %p", data->rootwin->active_gui_window->browser->bw);
+ browser_window_destroy(
+ data->rootwin->active_gui_window->browser->bw);
+ }
+ break;
+
+ case AP_DRAGDROP:
+ on_file_dropped(data->rootwin, msg);
+ break;
+
+ case WM_TOOLBAR:
+ toolbar_mouse_input(data->rootwin->toolbar, msg[4], msg[7]);
+ break;
+
+ default:
+ break;
+ }
+ }
+ if ((ev_out->emo_events & MU_KEYBD) != 0) {
+
+ // handle key
+ uint16_t nkc = gem_to_norm( (short)ev_out->emo_kmeta,
+ (short)ev_out->emo_kreturn);
+ LOG("rootwin MU_KEYBD input, nkc: %x\n", nkc);
+ retval = on_window_key_input(data->rootwin, nkc);
+ // printf("on_window_key_input: %d\n", retval);
+
+ }
+ if ((ev_out->emo_events & MU_BUTTON) != 0) {
+ LOG("rootwin MU_BUTTON input, x: %d, y: %d\n", ev_out->emo_mouse.p_x, ev_out->emo_mouse.p_x);
+ window_get_grect(data->rootwin, BROWSER_AREA_CONTENT,
+ &area);
+ if (POINT_WITHIN(ev_out->emo_mouse.p_x, ev_out->emo_mouse.p_y,
+ area)) {
+ on_content_mouse_click(data->rootwin);
+ }
+ }
+ if ((ev_out->emo_events & (MU_M1)) != 0) {
+
+ short ghandle = wind_find(ev_out->emo_mouse.p_x, ev_out->emo_mouse.p_y);
+
+ if (data->rootwin->aes_handle==ghandle) {
+ // The window found at x,y is an gui_window
+ // and it's the input window.
+ window_get_grect(data->rootwin, BROWSER_AREA_CONTENT,
+ &area);
+ if (POINT_WITHIN(ev_out->emo_mouse.p_x, ev_out->emo_mouse.p_y,
+ area)) {
+ on_content_mouse_move(data->rootwin, &area);
+ } else {
+ GRECT tb_area;
+ window_get_grect(data->rootwin, BROWSER_AREA_URL_INPUT, &tb_area);
+ if (POINT_WITHIN(ev_out->emo_mouse.p_x, ev_out->emo_mouse.p_y,
+ tb_area)) {
+ gem_set_cursor(&gem_cursors.ibeam);
+ prev_url = true;
+ } else {
+ if(prev_url) {
+ struct gui_window *gw;
+ gw = window_get_active_gui_window(data->rootwin);
+ gem_set_cursor(gw->cursor);
+ prev_url = false;
+ }
+ }
+ }
+ }
+ }
+
+ return(retval);
+}
+
+/* -------------------------------------------------------------------------- */
+/* Module public functions: */
+/* -------------------------------------------------------------------------- */
+
+int window_create(struct gui_window * gw,
+ struct browser_window * bw,
+ struct gui_window * existing,
+ unsigned long inflags)
+{
+ int err = 0;
+ bool tb, sb;
+ int flags;
+ struct rootwin_data_s *data;
+ struct gemtk_wm_scroll_info_s *slid;
+
+ tb = (inflags & WIDGET_TOOLBAR);
+ sb = (inflags & WIDGET_STATUSBAR);
+
+ flags = CLOSER | MOVER | NAME | FULLER | SMALLER;
+ if( inflags & WIDGET_SCROLL ) {
+ flags |= (UPARROW | DNARROW | LFARROW | RTARROW | VSLIDE | HSLIDE);
+ }
+ if( inflags & WIDGET_RESIZE ) {
+ flags |= ( SIZER );
+ }
+ if( inflags & WIDGET_STATUSBAR ) {
+ flags |= ( INFO );
+ }
+
+ gw->root = malloc(sizeof(struct s_gui_win_root));
+ if (gw->root == NULL)
+ return(-1);
+ memset(gw->root, 0, sizeof(struct s_gui_win_root) );
+ gw->root->title = malloc(atari_sysinfo.aes_max_win_title_len+1);
+
+ redraw_slots_init(&gw->root->redraw_slots, 8);
+
+ gw->root->aes_handle = wind_create(flags, 40, 40, desk_area.g_w,
+ desk_area.g_h);
+ if(gw->root->aes_handle<0) {
+ free(gw->root->title);
+ free(gw->root);
+ return( -1 );
+ }
+ gw->root->win = gemtk_wm_add(gw->root->aes_handle,
+ GEMTK_WM_FLAG_PREPROC_WM | GEMTK_WM_FLAG_RECV_PREPROC_WM, handle_event);
+
+ data = malloc(sizeof(struct rootwin_data_s));
+ data->rootwin = gw->root;
+ gemtk_wm_set_user_data(gw->root->win, (void*)data);
+ slid = gemtk_wm_get_scroll_info(gw->root->win);
+ slid->y_unit_px = 32;
+ slid->x_unit_px = 32;
+
+ /* create */
+ if(tb) {
+ gw->root->toolbar = toolbar_create(gw->root);
+ assert(gw->root->toolbar);
+ gemtk_wm_set_toolbar(gw->root->win, gw->root->toolbar->form, 0, 0);
+ gemtk_wm_set_toolbar_redraw_func(gw->root->win, toolbar_redraw_cb);
+ } else {
+ gw->root->toolbar = NULL;
+ }
+
+ /* create browser component: */
+ gw->browser = (struct s_browser *)malloc( sizeof(struct s_browser));
+
+ assert(gw->browser);
+
+ gw->browser->bw = bw;
+ gw->scale = browser_window_get_scale(bw);
+
+
+ /* create statusbar component: */
+ if(sb) {
+ gw->root->statusbar = sb_create( gw );
+ } else {
+ gw->root->statusbar = NULL;
+ }
+
+ // Setup some window defaults:
+ wind_set_str(gw->root->aes_handle, WF_NAME, (char*)"NetSurf");
+ wind_set(gw->root->aes_handle, WF_OPTS, 1, WO0_FULLREDRAW, 0, 0);
+ wind_set(gw->root->aes_handle, WF_OPTS, 1, WO0_NOBLITW, 0, 0);
+ wind_set(gw->root->aes_handle, WF_OPTS, 1, WO0_NOBLITH, 0, 0);
+
+ if (inflags & WIN_TOP) {
+ window_set_focus(gw->root, BROWSER, gw->browser);
+ }
+
+ return (err);
+}
+
+void window_unref_gui_window(ROOTWIN *rootwin, struct gui_window *gw)
+{
+ struct gui_window *w;
+ input_window = NULL;
+
+ LOG("window: %p, gui_window: %p", rootwin, gw);
+
+ w = window_list;
+ // find the next active tab:
+ while( w != NULL ) {
+ if(w->root == rootwin && w != gw) {
+ LOG("activating next tab %p", w);
+ gui_set_input_gui_window(w);
+ break;
+ }
+ w = w->next;
+ }
+ if(input_window == NULL) {
+ // the last gui window for this rootwin was removed:
+ redraw_slots_free(&rootwin->redraw_slots);
+ window_destroy(rootwin);
+ }
+}
+
+int window_destroy(ROOTWIN *rootwin)
+{
+ int err = 0;
+ struct gui_window *w;
+
+ assert(rootwin != NULL);
+
+ LOG("%p", rootwin);
+
+ if (gemtk_wm_get_user_data(rootwin->win) != NULL) {
+ free(gemtk_wm_get_user_data(rootwin->win));
+ }
+
+ // make sure we do not destroy windows which have gui_windows attached:
+ w = window_list;
+ while( w != NULL ) {
+ if(w->root == rootwin) {
+ assert(rootwin == NULL);
+ }
+ w = w->next;
+ }
+
+ if (rootwin->toolbar)
+ toolbar_destroy(rootwin->toolbar);
+
+ if(rootwin->statusbar)
+ sb_destroy(rootwin->statusbar);
+
+ if(rootwin->title)
+ free(rootwin->title);
+
+ gemtk_wm_remove(rootwin->win);
+ wind_close(rootwin->aes_handle);
+ wind_delete(rootwin->aes_handle);
+ free(rootwin);
+ return(err);
+}
+
+
+void window_open(ROOTWIN *rootwin, struct gui_window *gw, GRECT pos)
+{
+ GRECT g;
+
+ rootwin->active_gui_window = gw;
+
+ assert(rootwin->active_gui_window != NULL);
+
+ wind_open(rootwin->aes_handle, pos.g_x, pos.g_y, pos.g_w, pos.g_h );
+ wind_set_str(rootwin->aes_handle, WF_NAME, (char *)"");
+
+ rootwin->active_gui_window->browser->attached = true;
+ if(rootwin->statusbar != NULL) {
+ sb_attach(rootwin->statusbar, rootwin->active_gui_window);
+ }
+
+ /* Set initial size of the toolbar region: */
+ gemtk_wm_get_grect(rootwin->win, GEMTK_WM_AREA_TOOLBAR, &g);
+ toolbar_set_attached(rootwin->toolbar, true);
+ toolbar_set_dimensions(rootwin->toolbar, &g);
+
+ /* initially hide the search area of the toolbar: */
+ window_close_search(rootwin);
+
+ window_update_back_forward(rootwin);
+
+ window_set_focus(rootwin, BROWSER, rootwin->active_gui_window->browser);
+}
+
+void window_restore_active_gui_window(ROOTWIN *rootwin)
+{
+ GRECT tb_area;
+ struct gui_window *gw;
+
+ LOG("rootwin %p", rootwin);
+
+ assert(rootwin->active_gui_window);
+
+ gw = rootwin->active_gui_window;
+
+ window_set_icon(rootwin, gw->icon);
+ window_set_stauts(rootwin, gw->status);
+ window_set_title(rootwin, gw->title);
+
+ if (gw->search != NULL) {
+ // TODO: update search session (especially browser window)
+ }
+
+ toolbar_get_grect(rootwin->toolbar, 0, &tb_area);
+ gemtk_wm_set_toolbar_size(rootwin->win, tb_area.g_h);
+
+ window_update_back_forward(rootwin);
+
+ toolbar_set_url(rootwin->toolbar, gw->url);
+}
+
+
+/* update back forward buttons (see tb_update_buttons (bug) ) */
+void window_update_back_forward(struct s_gui_win_root *rootwin)
+{
+ struct gui_window * active_gw = rootwin->active_gui_window;
+ toolbar_update_buttons(rootwin->toolbar, active_gw->browser->bw, -1);
+}
+
+void window_set_stauts(struct s_gui_win_root *rootwin, char * text)
+{
+ assert(rootwin != NULL);
+
+ CMP_STATUSBAR sb = rootwin->statusbar;
+
+ if( sb == NULL)
+ return;
+
+ if(text != NULL)
+ sb_set_text(sb, text);
+ else
+ sb_set_text(sb, "");
+}
+
+void window_set_title(struct s_gui_win_root * rootwin, char *title)
+{
+ wind_set_str(rootwin->aes_handle, WF_NAME, title);
+}
+
+void window_scroll_by(ROOTWIN *root, int sx, int sy)
+{
+ struct gemtk_wm_scroll_info_s *slid = gemtk_wm_get_scroll_info(root->win);
+
+ if (sx < 0) {
+ sx = 0;
+ }
+ if (sy < 0) {
+ sy = 0;
+ }
+ int xunits = sx / slid->x_unit_px;
+ int yunits = sy / slid->y_unit_px;
+
+ gemtk_wm_scroll(root->win, GEMTK_WM_VSLIDER, yunits - slid->y_pos, false);
+ gemtk_wm_scroll(root->win, GEMTK_WM_HSLIDER, xunits - slid->x_pos, false);
+ gemtk_wm_update_slider(root->win, GEMTK_WM_VH_SLIDER);
+}
+
+/**
+* Set the dimensions of the scrollable content.
+*
+*/
+void window_set_content_size(ROOTWIN *rootwin, int width, int height)
+{
+ GRECT area;
+ struct gemtk_wm_scroll_info_s *slid = gemtk_wm_get_scroll_info(rootwin->win);
+
+ window_get_grect(rootwin, BROWSER_AREA_CONTENT, &area);
+
+ slid->x_units = (width/slid->x_unit_px);
+ slid->y_units = (height/slid->y_unit_px);
+ if(slid->x_units < slid->x_pos)
+ slid->x_pos = 0;
+ if(slid->y_units < slid->y_pos)
+ slid->y_pos = 0;
+ gemtk_wm_update_slider(rootwin->win, GEMTK_WM_VH_SLIDER);
+}
+
+/* set focus to an arbitary element */
+void window_set_focus(struct s_gui_win_root *rootwin,
+ enum focus_element_type type, void * element)
+{
+ assert(rootwin != NULL);
+
+ if (rootwin->focus.type != type || rootwin->focus.element != element) {
+ LOG("Set focus: %p (%d)\n", element, type);
+ rootwin->focus.type = type;
+ rootwin->focus.element = element;
+ switch( type ) {
+
+ case URL_WIDGET:
+ // TODO: make something like: toolbar_text_select_all();
+ toolbar_key_input(rootwin->toolbar, (short)(NKF_CTRL | 'A') );
+/*
+ ta = toolbar_get_textarea(rootwin->toolbar,
+ URL_INPUT_TEXT_AREA);
+ textarea_keypress(ta, NS_KEY_SELECT_ALL);
+ */
+ break;
+
+ case SEARCH_INPUT:
+ gemtk_wm_set_toolbar_edit_obj(rootwin->win, TOOLBAR_TB_SRCH, 0);
+ break;
+
+ default:
+ break;
+
+ }
+ }
+}
+
+/* check if the url widget has focus */
+bool window_url_widget_has_focus(struct s_gui_win_root *rootwin)
+{
+ assert(rootwin != NULL);
+
+ if (rootwin->focus.type == URL_WIDGET) {
+ return true;
+ }
+ return false;
+}
+
+/* check if an arbitary window widget / or frame has the focus */
+bool window_widget_has_focus(struct s_gui_win_root *rootwin,
+ enum focus_element_type t, void * element)
+{
+ assert(rootwin != NULL);
+ if( element == NULL ) {
+ return((rootwin->focus.type == t));
+ }
+
+ return((element == rootwin->focus.element && t == rootwin->focus.type));
+}
+
+void window_set_icon(ROOTWIN *rootwin, struct bitmap * bmp )
+{
+ rootwin->icon = bmp;
+ /* redraw window when it is iconyfied: */
+ if (rootwin->icon != NULL) {
+ if (gemtk_wm_get_state(rootwin->win) & GEMTK_WM_STATUS_ICONIFIED) {
+ window_redraw_favicon(rootwin, NULL);
+ }
+ }
+}
+
+void window_set_active_gui_window(ROOTWIN *rootwin, struct gui_window *gw)
+{
+ struct gui_window *old_gw = rootwin->active_gui_window;
+
+ LOG("gw %p",gw);
+
+ if (rootwin->active_gui_window != NULL) {
+ if(rootwin->active_gui_window == gw) {
+ LOG("nothing to do...");
+ return;
+ }
+ }
+
+ // TODO: when the window isn't on top, initiate WM_TOPPED.
+
+ rootwin->active_gui_window = gw;
+ if (old_gw != NULL) {
+ LOG("restoring window...");
+ window_restore_active_gui_window(rootwin);
+ }
+}
+
+struct gui_window * window_get_active_gui_window(ROOTWIN * rootwin)
+{
+ return(rootwin->active_gui_window);
+}
+
+void window_get_scroll(ROOTWIN *rootwin, int *x, int *y)
+{
+ struct gemtk_wm_scroll_info_s *slid;
+
+ slid = gemtk_wm_get_scroll_info(rootwin->win);
+
+ *x = slid->x_pos * slid->x_unit_px;
+ *y = slid->y_pos * slid->y_unit_px;
+}
+
+void window_get_grect(ROOTWIN *rootwin, enum browser_area_e which, GRECT *d)
+{
+
+ d->g_x = 0;
+ d->g_y = 0;
+ d->g_w = 0;
+ d->g_h = 0;
+
+ if (which == BROWSER_AREA_TOOLBAR) {
+ // gemtk_wm_get_grect(rootwin->win, GEMTK_WM_AREA_TOOLBAR, d);
+ toolbar_get_grect(rootwin->toolbar, 0, d);
+
+ } else if (which == BROWSER_AREA_CONTENT) {
+
+ GRECT tb_area;
+
+ gemtk_wm_get_grect(rootwin->win, GEMTK_WM_AREA_WORK, d);
+ toolbar_get_grect(rootwin->toolbar, 0, &tb_area);
+
+ d->g_y += tb_area.g_h;
+ d->g_h -= tb_area.g_h;
+
+ } else if (which == BROWSER_AREA_URL_INPUT) {
+
+ toolbar_get_grect(rootwin->toolbar, TOOLBAR_AREA_URL, d);
+
+ } else if (which == BROWSER_AREA_SEARCH) {
+ // todo: check if search is visible
+ toolbar_get_grect(rootwin->toolbar, TOOLBAR_AREA_SEARCH, d);
+ } else {
+
+ }
+
+
+ // sanitize the results
+ if (d->g_h < 0) {
+ d->g_h = 0;
+ }
+ if (d->g_w < 0) {
+ d->g_w = 0;
+ }
+
+ //printf("window_get_grect %d:", which);
+ //dbg_grect("", d);
+
+}
+
+
+void window_open_search(ROOTWIN *rootwin, bool reformat)
+{
+ struct browser_window *bw;
+ struct gui_window *gw;
+ GRECT area;
+ OBJECT *obj;
+
+ LOG("rootwin %p", rootwin);
+
+ gw = rootwin->active_gui_window;
+ bw = gw->browser->bw;
+ obj = toolbar_get_form(rootwin->toolbar);
+
+ if (gw->search == NULL) {
+ gw->search = nsatari_search_session_create(obj, gw);
+ }
+
+ toolbar_set_visible(rootwin->toolbar, TOOLBAR_AREA_SEARCH, true);
+ window_get_grect(rootwin, BROWSER_AREA_TOOLBAR, &area);
+ gemtk_wm_set_toolbar_size(rootwin->win, area.g_h);
+ window_get_grect(rootwin, BROWSER_AREA_SEARCH, &area);
+ window_schedule_redraw_grect(rootwin, &area);
+ window_process_redraws(rootwin);
+ window_set_focus(rootwin, SEARCH_INPUT, NULL);
+
+ window_get_grect(rootwin, BROWSER_AREA_CONTENT, &area);
+ if (reformat) {
+ browser_window_reformat(bw, false, area.g_w, area.g_h);
+ }
+}
+
+void window_close_search(ROOTWIN *rootwin)
+{
+ struct browser_window *bw;
+ struct gui_window *gw;
+ GRECT area;
+ OBJECT *obj;
+
+
+ gw = rootwin->active_gui_window;
+ bw = gw->browser->bw;
+ obj = gemtk_obj_get_tree(TOOLBAR);
+
+ if (gw->search != NULL) {
+ nsatari_search_session_destroy(gw->search);
+ gw->search = NULL;
+ }
+
+ toolbar_set_visible(rootwin->toolbar, TOOLBAR_AREA_SEARCH, false);
+ window_get_grect(rootwin, BROWSER_AREA_TOOLBAR, &area);
+ gemtk_wm_set_toolbar_size(rootwin->win, area.g_h);
+ window_get_grect(rootwin, BROWSER_AREA_CONTENT, &area);
+ browser_window_reformat(bw, false, area.g_w, area.g_h);
+}
+
+/**
+ * Redraw the favicon
+*/
+void window_redraw_favicon(ROOTWIN *rootwin, GRECT *clip_ro)
+{
+ GRECT work, visible, clip;
+
+ assert(rootwin);
+
+ //printf("window_redraw_favicon: root: %p, win: %p\n", rootwin, rootwin->win);
+
+ gemtk_wm_clear(rootwin->win);
+ gemtk_wm_get_grect(rootwin->win, GEMTK_WM_AREA_WORK, &work);
+
+ if (clip_ro == NULL) {
+ clip = work;
+ } else {
+ clip = *clip_ro;
+ if(!rc_intersect(&work, &clip)) {
+ return;
+ }
+ }
+
+ //dbg_grect("favicon redrw area", clip);
+ //dbg_grect("favicon work area", &work);
+
+ if (rootwin->icon == NULL) {
+ //printf("window_redraw_favicon OBJCTREE\n");
+
+ OBJECT * tree = gemtk_obj_get_tree(ICONIFY);
+ tree->ob_x = work.g_x;
+ tree->ob_y = work.g_y;
+ tree->ob_width = work.g_w;
+ tree->ob_height = work.g_h;
+
+ wind_get_grect(rootwin->aes_handle, WF_FIRSTXYWH, &visible);
+ while (visible.g_h > 0 && visible.g_w > 0) {
+
+ if (rc_intersect(&clip, &visible)) {
+ //dbg_grect("redraw vis area", &visible);
+ objc_draw(tree, 0, 8, visible.g_x, visible.g_y, visible.g_w,
+ visible.g_h);
+ } else {
+ //dbg_grect("redraw vis area outside", &visible);
+ }
+
+ wind_get_grect(rootwin->aes_handle, WF_NEXTXYWH, &visible);
+ }
+
+ } else {
+ //printf("window_redraw_favicon image %p\n", rootwin->icon);
+ VdiHdl plot_vdi_handle = plot_get_vdi_handle();
+ short pxy[4];
+ int xoff=0;
+
+ if (work.g_w > work.g_h) {
+ xoff = ((work.g_w-work.g_h)/2);
+ work.g_w = work.g_h;
+ }
+ plot_set_dimensions( work.g_x+xoff, work.g_y, work.g_w,
+ work.g_h);
+
+ wind_get_grect(rootwin->aes_handle, WF_FIRSTXYWH, &visible);
+ while (visible.g_h > 0 && visible.g_w > 0) {
+
+ if (rc_intersect(&clip, &visible)) {
+
+ //dbg_grect("redraw vis area", &visible);
+
+ // Manually clip drawing region:
+ pxy[0] = visible.g_x;
+ pxy[1] = visible.g_y;
+ pxy[2] = pxy[0] + visible.g_w-1;
+ pxy[3] = pxy[1] + visible.g_h-1;
+ vs_clip(plot_vdi_handle, 1, (short*)&pxy);
+ //dbg_pxy("vdi clip", (short*)&pxy);
+
+ atari_plotters.bitmap(0, 0, work.g_w, work.g_h,
+ rootwin->icon, 0xffffff, 0);
+ } else {
+ //dbg_grect("redraw vis area outside", &visible);
+ }
+
+ wind_get_grect(rootwin->aes_handle, WF_NEXTXYWH, &visible);
+ }
+ }
+}
+
+/***
+* Schedule an redraw area, redraw requests during redraw are
+* not optimized (merged) into other areas, so that the redraw
+* functions can spot the change.
+*
+*/
+void window_schedule_redraw_grect(ROOTWIN *rootwin, GRECT *area)
+{
+ GRECT work;
+
+
+ //dbg_grect("window_schedule_redraw_grect input ", area);
+
+ gemtk_wm_get_grect(rootwin->win, GEMTK_WM_AREA_WORK, &work);
+ if(!rc_intersect(area, &work))
+ return;
+
+ //dbg_grect("window_schedule_redraw_grect intersection ", &work);
+
+ redraw_slot_schedule_grect(&rootwin->redraw_slots, &work, redraw_active);
+}
+
+static void window_redraw_content(ROOTWIN *rootwin, GRECT *content_area,
+ GRECT *clip,
+ struct gemtk_wm_scroll_info_s * slid,
+ struct browser_window *bw)
+{
+
+ struct rect redraw_area;
+ GRECT content_area_rel;
+ float oldscale = 1.0;
+
+ //dbg_grect("browser redraw, content area", content_area);
+ //dbg_grect("browser redraw, content clip", clip);
+
+ plot_set_dimensions(content_area->g_x, content_area->g_y,
+ content_area->g_w, content_area->g_h);
+ oldscale = plot_set_scale(browser_window_get_scale(rootwin->active_gui_window->browser->bw));
+
+ /* first, we make the coords relative to the content area: */
+ content_area_rel.g_x = clip->g_x - content_area->g_x;
+ content_area_rel.g_y = clip->g_y - content_area->g_y;
+ content_area_rel.g_w = clip->g_w;
+ content_area_rel.g_h = clip->g_h;
+
+ if (content_area_rel.g_x < 0) {
+ content_area_rel.g_w += content_area_rel.g_x;
+ content_area_rel.g_x = 0;
+ }
+
+ if (content_area_rel.g_y < 0) {
+ content_area_rel.g_h += content_area_rel.g_y;
+ content_area_rel.g_y = 0;
+ }
+
+ //dbg_grect("browser redraw, relative plot coords:", &content_area_rel);
+
+ redraw_area.x0 = content_area_rel.g_x;
+ redraw_area.y0 = content_area_rel.g_y;
+ redraw_area.x1 = content_area_rel.g_x + content_area_rel.g_w;
+ redraw_area.y1 = content_area_rel.g_y + content_area_rel.g_h;
+
+ plot_clip(&redraw_area);
+
+ //dbg_rect("rdrw area", &redraw_area);
+
+ browser_window_redraw( bw, -(slid->x_pos*slid->x_unit_px),
+ -(slid->y_pos*slid->y_unit_px), &redraw_area, &rootwin_rdrw_ctx);
+
+ plot_set_scale(oldscale);
+}
+
+
+void window_place_caret(ROOTWIN *rootwin, short mode, int content_x,
+ int content_y, int h, GRECT *work)
+{
+ struct s_caret *caret = &rootwin->caret;
+ VdiHdl vh = gemtk_wm_get_vdi_handle(rootwin->win);
+ short pxy[8];
+ GRECT mywork, caret_pos;
+ MFDB screen;
+ int scroll_x, scroll_y;
+ uint16_t *fd_addr;
+ struct gemtk_wm_scroll_info_s *slid;
+ short colors[2] = {G_BLACK, G_WHITE};
+ bool render_required = false;
+
+ // avoid duplicate draw of the caret:
+ if (mode == 1 &&(caret->state&CARET_STATE_VISIBLE)!=0) {
+ if (caret->dimensions.g_x == content_x
+ && caret->dimensions.g_y == content_y
+ && caret->dimensions.g_h == h) {
+ return;
+ }
+ }
+
+ if(work == NULL) {
+ window_get_grect(rootwin, BROWSER_AREA_CONTENT, &mywork);
+ work = &mywork;
+ }
+ slid = gemtk_wm_get_scroll_info(rootwin->win);
+
+ scroll_x = slid->x_pos * slid->x_unit_px;
+ scroll_y = slid->y_pos * slid->y_unit_px;
+
+ init_mfdb(0, 1, h, 0, &screen);
+
+ // enable clipping:
+ pxy[0] = work->g_x;
+ pxy[1] = work->g_y;
+ pxy[2] = pxy[0] + work->g_w - 1;
+ pxy[3] = pxy[1] + work->g_h - 1;
+ vs_clip(vh, 1, pxy);
+
+ // when the caret is visible, undraw it:
+ if (caret->symbol.fd_addr != NULL
+ && (caret->state&CARET_STATE_VISIBLE)!=0) {
+
+ caret_pos.g_x = work->g_x + (caret->dimensions.g_x - scroll_x);
+ caret_pos.g_y = work->g_y + (caret->dimensions.g_y - scroll_y);
+ caret_pos.g_w = caret->dimensions.g_w;
+ caret_pos.g_h = caret->dimensions.g_h;
+
+ if (rc_intersect(work, &caret_pos)) {
+
+ pxy[0] = 0;
+ pxy[1] = 0;
+ pxy[2] = caret->dimensions.g_w-1;
+ pxy[3] = caret->dimensions.g_h-1;
+
+ pxy[4] = caret_pos.g_x;
+ pxy[5] = caret_pos.g_y;
+ pxy[6] = pxy[4] + caret_pos.g_w-1;
+ pxy[7] = pxy[5] + caret_pos.g_h-1;
+
+ vrt_cpyfm(vh, MD_XOR, pxy, &caret->symbol, &screen, colors);
+ }
+ }
+ if (mode == 0) {
+ // update state:
+ caret->state &= ~CARET_STATE_VISIBLE;
+ goto exit;
+ }
+
+ // when the caret isn't allocated, create it:
+ if (caret->symbol.fd_addr == NULL) {
+ caret->fd_size = init_mfdb(1, 16, h, MFDB_FLAG_ZEROMEM,
+ &caret->symbol);
+ render_required = true;
+ } else {
+ // the caret may need more memory:
+ if (caret->dimensions.g_h < h) {
+ caret->fd_size = init_mfdb(1, 16, h, MFDB_FLAG_NOALLOC,
+ &caret->symbol);
+ realloc(caret->symbol.fd_addr, caret->fd_size);
+ render_required = true;
+ }
+ }
+
+ // set new caret position:
+ caret->dimensions.g_x = content_x;
+ caret->dimensions.g_y = content_y;
+ caret->dimensions.g_w = 1;
+ caret->dimensions.g_h = h;
+
+ // draw the caret into the mfdb buffer:
+ if (render_required) {
+ int i;
+
+ assert(caret->symbol.fd_nplanes == 1);
+ assert(caret->symbol.fd_w == 16);
+
+ // draw an vertical line into the mfdb buffer
+ fd_addr = (uint16_t*)caret->symbol.fd_addr;
+ for(i = 0; i<caret->symbol.fd_h; i++) {
+ fd_addr[i] = 0xFFFF;
+ }
+ }
+
+ // convert content coords to screen coords:
+
+ caret_pos.g_x = work->g_x + (content_x - scroll_x);
+ caret_pos.g_y = work->g_y + (content_y - scroll_y);
+ caret_pos.g_w = caret->dimensions.g_w;
+ caret_pos.g_h = caret->dimensions.g_h;
+
+ if (rc_intersect(work, &caret_pos) && redraw_active == false) {
+
+ pxy[0] = 0;
+ pxy[1] = 0;
+ pxy[2] = caret->dimensions.g_w-1;
+ pxy[3] = caret->dimensions.g_h-1;
+
+ pxy[4] = caret_pos.g_x;
+ pxy[5] = caret_pos.g_y;
+ pxy[6] = pxy[4] + caret_pos.g_w-1;
+ pxy[7] = pxy[5] + caret_pos.g_h-1;
+
+ //dbg_pxy("caret screen coords (md_repl)", &pxy[4]);
+
+ // TODO: walk rectangle list (use MD_REPLACE then)
+ // draw caret to screen coords:
+ vrt_cpyfm(vh, /*MD_REPLACE*/ MD_XOR, pxy, &caret->symbol, &screen, colors);
+
+ // update state:
+ caret->state |= CARET_STATE_VISIBLE;
+ }
+
+exit:
+ // disable clipping:
+ vs_clip(gemtk_wm_get_vdi_handle(rootwin->win), 0, pxy);
+}
+
+void window_process_redraws(ROOTWIN * rootwin)
+{
+ GRECT visible_ro, tb_area, content_area;
+ short i;
+ short scroll_x=0, scroll_y=0;
+ bool caret_rdrw_required = false;
+ struct gemtk_wm_scroll_info_s *slid =NULL;
+ int caret_h = 0;
+ struct s_caret *caret = &rootwin->caret;
+
+ redraw_active = true;
+
+ window_get_grect(rootwin, BROWSER_AREA_TOOLBAR, &tb_area);
+ //gemtk_wm_set_toolbar_size(rootwin->win, tb_area.g_h);
+ window_get_grect(rootwin, BROWSER_AREA_CONTENT, &content_area);
+
+ //dbg_grect("content area", &content_area);
+ //dbg_grect("window_process_redraws toolbar area", &tb_area);
+
+ while(plot_lock() == false);
+
+ if (((rootwin->caret.state & CARET_STATE_ENABLED)!=0)
+ && rootwin->caret.dimensions.g_h > 0) {
+ // hide caret:
+ window_place_caret(rootwin, 0, -1, -1, -1, &content_area);
+ }
+/*
+ short pxy_clip[4];
+ pxy_clip[0] = tb_area.g_x;
+ pxy_clip[0] = tb_area.g_y;
+ pxy_clip[0] = pxy_clip[0] + tb_area.g_w + content_area.g_w - 1;
+ pxy_clip[0] = pxy_clip[1] + tb_area.g_h + content_area.g_h - 1;
+ vs_clip(gemtk_wm_get_vdi_handle(rootwin->win), 1, pxy_clip);
+ //gemtk_wm_clear(rootwin->win);
+*/
+ wind_get_grect(rootwin->aes_handle, WF_FIRSTXYWH, &visible_ro);
+ while (visible_ro.g_w > 0 && visible_ro.g_h > 0) {
+ plot_set_abs_clipping(&visible_ro);
+
+ //dbg_grect("visible ", &visible_ro);
+
+ // TODO: optimze the rectangle list -
+ // remove rectangles which were completly inside the visible area.
+ // that way we don't have to loop over again...
+ for(i=0; i<rootwin->redraw_slots.areas_used; i++) {
+
+ GRECT rdrw_area_ro = {
+ rootwin->redraw_slots.areas[i].x0,
+ rootwin->redraw_slots.areas[i].y0,
+ rootwin->redraw_slots.areas[i].x1 -
+ rootwin->redraw_slots.areas[i].x0,
+ rootwin->redraw_slots.areas[i].y1 -
+ rootwin->redraw_slots.areas[i].y0
+ };
+
+ if (!rc_intersect(&visible_ro, &rdrw_area_ro)) {
+ continue;
+ }
+ GRECT rdrw_area = rdrw_area_ro;
+
+ if (rc_intersect(&tb_area, &rdrw_area)) {
+ toolbar_redraw(rootwin->toolbar, &rdrw_area);
+ }
+
+ rdrw_area = rdrw_area_ro;
+ if (rc_intersect(&content_area, &rdrw_area)) {
+
+ if(slid == NULL) {
+ slid = gemtk_wm_get_scroll_info(rootwin->win);
+
+ scroll_x = slid->x_pos * slid->x_unit_px;
+ scroll_y = slid->y_pos * slid->y_unit_px;
+ }
+
+ window_redraw_content(rootwin, &content_area, &rdrw_area,
+ slid,
+ rootwin->active_gui_window->browser->bw);
+ if (((rootwin->caret.state & CARET_STATE_ENABLED)!=0)) {
+
+ GRECT caret_pos;
+
+ caret_pos.g_x = content_area.g_x +
+ (caret->dimensions.g_x - scroll_x);
+ caret_pos.g_y = content_area.g_y +
+ (caret->dimensions.g_y - scroll_y);
+ caret_pos.g_w = caret->dimensions.g_w;
+ caret_pos.g_h = caret->dimensions.g_h;
+
+ if (gemtk_rc_intersect_ro(&caret_pos, &content_area)) {
+ caret_rdrw_required = true;
+ }
+ }
+
+ }
+ }
+ wind_get_grect(rootwin->aes_handle, WF_NEXTXYWH, &visible_ro);
+ }
+
+
+ // disable clipping:
+ //vs_clip(gemtk_wm_get_vdi_handle(rootwin->win), 0, pxy_clip);
+
+ if (caret_rdrw_required && ((rootwin->caret.state & CARET_STATE_ENABLED)!=0)) {
+
+ // force redraw of caret:
+ caret_h = rootwin->caret.dimensions.g_h;
+ rootwin->caret.dimensions.g_h = 0;
+ redraw_active = false;
+ window_place_caret(rootwin, 1, rootwin->caret.dimensions.g_x,
+ rootwin->caret.dimensions.g_y,
+ caret_h, &content_area);
+ }
+
+ rootwin->redraw_slots.areas_used = 0;
+ redraw_active = false;
+
+ plot_unlock();
+}
+
+
+/* -------------------------------------------------------------------------- */
+/* Event Handlers: */
+/* -------------------------------------------------------------------------- */
+static void on_content_mouse_move(ROOTWIN *rootwin, GRECT *content_area)
+{
+ int mx, my, sx, sy;
+ struct gemtk_wm_scroll_info_s *slid;
+ struct gui_window *gw;
+ struct browser_window *bw;
+
+ // make relative mouse coords:
+ mx = aes_event_out.emo_mouse.p_x - content_area->g_x;
+ my = aes_event_out.emo_mouse.p_y - content_area->g_y;
+
+ slid = gemtk_wm_get_scroll_info(rootwin->win);
+ gw = window_get_active_gui_window(rootwin);
+ bw = gw->browser->bw;
+
+ // calculate scroll pos. in pixel:
+ sx = slid->x_pos * slid->x_unit_px;
+ sy = slid->y_pos * slid->y_unit_px;
+
+ browser_window_mouse_track(bw, 0, mx + sx, my + sy);
+}
+
+static void on_content_mouse_click(ROOTWIN *rootwin)
+{
+ short dummy, mbut, mx, my;
+ GRECT cwork;
+ browser_mouse_state bmstate = 0;
+ struct gui_window *gw;
+ struct gemtk_wm_scroll_info_s *slid;
+
+ gw = window_get_active_gui_window(rootwin);
+ if(input_window != gw) {
+ gui_set_input_gui_window(gw);
+ }
+
+ window_set_focus(gw->root, BROWSER, (void*)gw->browser );
+ window_get_grect(gw->root, BROWSER_AREA_CONTENT, &cwork);
+
+ /* convert screen coords to component coords: */
+ mx = aes_event_out.emo_mouse.p_x - cwork.g_x;
+ my = aes_event_out.emo_mouse.p_y - cwork.g_y;
+ //printf("content click at %d,%d\n", mx, my);
+
+ /* Translate GEM key state to netsurf mouse modifier */
+ if ( aes_event_out.emo_kmeta & (K_RSHIFT | K_LSHIFT)) {
+ bmstate |= BROWSER_MOUSE_MOD_1;
+ } else {
+ bmstate &= ~(BROWSER_MOUSE_MOD_1);
+ }
+ if ( (aes_event_out.emo_kmeta & K_CTRL) ) {
+ bmstate |= BROWSER_MOUSE_MOD_2;
+ } else {
+ bmstate &= ~(BROWSER_MOUSE_MOD_2);
+ }
+ if ( (aes_event_out.emo_kmeta & K_ALT) ) {
+ bmstate |= BROWSER_MOUSE_MOD_3;
+ } else {
+ bmstate &= ~(BROWSER_MOUSE_MOD_3);
+ }
+
+ /* convert component coords to scrolled content coords: */
+ slid = gemtk_wm_get_scroll_info(rootwin->win);
+ int sx_origin = mx;
+ int sy_origin = my;
+
+ short rel_cur_x, rel_cur_y;
+ short prev_x=sx_origin, prev_y=sy_origin;
+ bool dragmode = false;
+
+ /* Detect left mouse button state and compare with event state: */
+ graf_mkstate(&rel_cur_x, &rel_cur_y, &mbut, &dummy);
+ if( (mbut & 1) && (aes_event_out.emo_mbutton & 1) ) {
+ /* Mouse still pressed, report drag */
+ rel_cur_x = (rel_cur_x - cwork.g_x);
+ rel_cur_y = (rel_cur_y - cwork.g_y);
+ browser_window_mouse_click( gw->browser->bw,
+ BROWSER_MOUSE_DRAG_ON|BROWSER_MOUSE_DRAG_1,
+ rel_cur_x + slid->x_pos * slid->x_unit_px,
+ rel_cur_y + slid->y_pos * slid->y_unit_px);
+ do {
+ // only consider movements of 5px or more as drag...:
+ if( abs(prev_x-rel_cur_x) > 5 || abs(prev_y-rel_cur_y) > 5 ) {
+ browser_window_mouse_track( gw->browser->bw,
+ BROWSER_MOUSE_DRAG_ON|BROWSER_MOUSE_DRAG_1,
+ rel_cur_x + slid->x_pos * slid->x_unit_px,
+ rel_cur_y + slid->y_pos * slid->y_unit_px);
+ prev_x = rel_cur_x;
+ prev_y = rel_cur_y;
+ dragmode = true;
+ } else {
+ if( dragmode == false ) {
+ browser_window_mouse_track( gw->browser->bw,BROWSER_MOUSE_PRESS_1,
+ rel_cur_x + slid->x_pos * slid->x_unit_px,
+ rel_cur_y + slid->y_pos * slid->y_unit_px);
+ }
+ }
+
+ // we may need to process scrolling:
+ // TODO: this doesn't work, because gemtk schedules redraw via
+ // AES window messages but we do not process them right here...
+ if (rootwin->redraw_slots.areas_used > 0) {
+ window_process_redraws(rootwin);
+ }
+ evnt_timer(150);
+
+ graf_mkstate(&rel_cur_x, &rel_cur_y, &mbut, &dummy);
+ rel_cur_x = (rel_cur_x - cwork.g_x);
+ rel_cur_y = (rel_cur_y - cwork.g_y);
+ } while( mbut & 1 );
+ browser_window_mouse_track(gw->browser->bw, 0,
+ rel_cur_x + slid->x_pos * slid->x_unit_px,
+ rel_cur_y + slid->y_pos * slid->y_unit_px);
+ } else {
+ /* Right button pressed? */
+ if ((aes_event_out.emo_mbutton & 2 ) ) {
+ context_popup(gw, aes_event_out.emo_mouse.p_x,
+ aes_event_out.emo_mouse.p_y);
+ } else {
+ browser_window_mouse_click(gw->browser->bw,
+ bmstate|BROWSER_MOUSE_PRESS_1,
+ sx_origin + slid->x_pos * slid->x_unit_px,
+ sy_origin + slid->y_pos * slid->y_unit_px);
+ browser_window_mouse_click(gw->browser->bw,
+ bmstate|BROWSER_MOUSE_CLICK_1,
+ sx_origin + slid->x_pos * slid->x_unit_px,
+ sy_origin + slid->y_pos * slid->y_unit_px);
+ }
+ }
+ if (rootwin->redraw_slots.areas_used > 0) {
+ window_process_redraws(rootwin);
+ }
+}
+
+/*
+ Report keypress to browser component.
+ parameter:
+ - unsigned short nkc ( CFLIB normalised key code )
+*/
+static bool on_content_keypress(struct gui_window *gw, unsigned short nkc)
+{
+ bool r = false;
+ unsigned char ascii = (nkc & 0xFF);
+ long ucs4;
+ long ik = nkc_to_input_key( nkc, &ucs4 );
+
+ // pass event to specific control?
+
+ if (ik == 0) {
+ if (ascii >= 9) {
+ r = browser_window_key_press(gw->browser->bw, ucs4);
+ }
+ } else {
+ r = browser_window_key_press(gw->browser->bw, ik);
+ if (r == false) {
+
+ GRECT g;
+ GUIWIN * w = gw->root->win;
+ window_get_grect(gw->root, BROWSER_AREA_CONTENT, &g);
+
+ struct gemtk_wm_scroll_info_s *slid = gemtk_wm_get_scroll_info(w);
+
+ switch( ik ) {
+ case NS_KEY_LINE_START:
+ gemtk_wm_scroll(w, GEMTK_WM_HSLIDER, -(g.g_w/slid->x_unit_px),
+ false);
+ r = true;
+ break;
+
+ case NS_KEY_LINE_END:
+ gemtk_wm_scroll(w, GEMTK_WM_HSLIDER, (g.g_w/slid->x_unit_px),
+ false);
+ r = true;
+ break;
+
+ case NS_KEY_PAGE_UP:
+ gemtk_wm_scroll(w, GEMTK_WM_VSLIDER, -(g.g_h/slid->y_unit_px),
+ false);
+ r = true;
+ break;
+
+ case NS_KEY_PAGE_DOWN:
+ gemtk_wm_scroll(w, GEMTK_WM_VSLIDER, (g.g_h/slid->y_unit_px),
+ false);
+ r = true;
+ break;
+
+ case NS_KEY_RIGHT:
+ gemtk_wm_scroll(w, GEMTK_WM_HSLIDER, -1, false);
+ r = true;
+ break;
+
+ case NS_KEY_LEFT:
+ gemtk_wm_scroll(w, GEMTK_WM_HSLIDER, 1, false);
+ r = true;
+ break;
+
+ case NS_KEY_UP:
+ gemtk_wm_scroll(w, GEMTK_WM_VSLIDER, -1, false);
+ r = true;
+ break;
+
+ case NS_KEY_DOWN:
+ gemtk_wm_scroll(w, GEMTK_WM_VSLIDER, 1, false);
+ r = true;
+ break;
+
+ case NS_KEY_TEXT_START:
+ window_scroll_by(gw->root, 0, 0);
+ r = true;
+ break;
+
+ default:
+ break;
+ }
+ gemtk_wm_update_slider(w, GEMTK_WM_VSLIDER|GEMTK_WM_HSLIDER);
+ }
+ }
+
+ return(r);
+}
+
+static short on_window_key_input(ROOTWIN *rootwin, unsigned short nkc)
+{
+ bool done = false;
+ struct gui_window * gw = window_get_active_gui_window(rootwin);
+
+ if( gw == NULL )
+ return(false);
+
+ if(window_url_widget_has_focus((void*)gw->root)) {
+ /* make sure we report for the root window and report...: */
+ done = toolbar_key_input(gw->root->toolbar, nkc);
+ } else {
+ if( window_widget_has_focus(input_window->root, BROWSER,
+ (void*)input_window->browser)) {
+ done = on_content_keypress(input_window, nkc);
+ }
+ else if(window_widget_has_focus(input_window->root, SEARCH_INPUT, NULL)) {
+ OBJECT * obj;
+ obj = toolbar_get_form(input_window->root->toolbar);
+ obj[TOOLBAR_BT_SEARCH_FWD].ob_state &= ~OS_DISABLED;
+ obj[TOOLBAR_BT_SEARCH_BACK].ob_state &= ~OS_DISABLED;
+ window_schedule_redraw_grect(input_window->root,
+ gemtk_obj_screen_rect(obj, TOOLBAR_BT_SEARCH_FWD));
+ window_schedule_redraw_grect(input_window->root,
+ gemtk_obj_screen_rect(obj, TOOLBAR_BT_SEARCH_BACK));
+ }
+ }
+ return((done==true) ? 1 : 0);
+}
+
+
+static void on_redraw(ROOTWIN *rootwin, short msg[8])
+{
+ GRECT clip = {msg[4], msg[5], msg[6], msg[7]};
+
+ //dbg_grect("on_redraw", &clip);
+
+ if(gemtk_wm_get_state(rootwin->win) & GEMTK_WM_STATUS_ICONIFIED) {
+ // TODO: remove asignment:
+ window_redraw_favicon(rootwin, NULL);
+ } else {
+ window_schedule_redraw_grect(rootwin, &clip);
+ }
+}
+
+static void on_resized(ROOTWIN *rootwin)
+{
+ GRECT g, work;
+ struct gui_window *gw;
+
+ gw = window_get_active_gui_window(rootwin);
+
+ //printf("resized...\n");
+
+ assert(gw != NULL);
+
+ if(gw == NULL)
+ return;
+
+ wind_get_grect(rootwin->aes_handle, WF_CURRXYWH, &g);
+ gemtk_wm_get_grect(rootwin->win, GEMTK_WM_AREA_WORK, &work);
+
+ if (rootwin->loc.g_w != g.g_w || rootwin->loc.g_h != g.g_h) {
+
+ /* resized */
+ toolbar_set_width(rootwin->toolbar, work.g_w);
+
+ if ( browser_window_has_content(gw->browser->bw) ) {
+ browser_window_reformat(gw->browser->bw, true, work.g_w, work.g_h);
+ }
+ }
+ if (rootwin->loc.g_x != g.g_x || rootwin->loc.g_y != g.g_y) {
+ /* moved */
+ toolbar_set_origin(rootwin->toolbar, work.g_x, work.g_y);
+ }
+
+ rootwin->loc = g;
+}
+
+static void on_file_dropped(ROOTWIN *rootwin, short msg[8])
+{
+ char file[DD_NAMEMAX];
+ char name[DD_NAMEMAX];
+ char *buff=NULL;
+ int dd_hdl;
+ int dd_msg; /* pipe-handle */
+ long size;
+ char ext[32];
+ short mx,my,bmstat,mkstat;
+ struct gui_window *gw;
+
+ graf_mkstate(&mx, &my, &bmstat, &mkstat);
+
+ gw = window_get_active_gui_window(rootwin);
+
+ if( gw == NULL )
+ return;
+
+ if(gemtk_wm_get_state(rootwin->win) & GEMTK_WM_STATUS_ICONIFIED)
+ return;
+
+ dd_hdl = gemtk_dd_open( msg[7], DD_OK);
+ if( dd_hdl<0)
+ return; /* pipe not open */
+ memset( ext, 0, 32);
+ strcpy( ext, "ARGS");
+ dd_msg = gemtk_dd_sexts( dd_hdl, ext);
+ if( dd_msg<0)
+ goto error;
+ dd_msg = gemtk_dd_rtry( dd_hdl, (char*)&name[0], (char*)&file[0], (char*)&ext[0], &size);
+ if( size+1 >= PATH_MAX )
+ goto error;
+ if( !strncmp( ext, "ARGS", 4) && dd_msg > 0) {
+ gemtk_dd_reply(dd_hdl, DD_OK);
+ buff = (char*)malloc(sizeof(char)*(size+1));
+ if (buff != NULL) {
+ if (Fread(dd_hdl, size, buff ) == size) {
+
+ int sx, sy;
+ bool processed = false;
+ GRECT content_area;
+
+ buff[size] = 0;
+
+ LOG("file: %s, ext: %s, size: %ld dropped at: %d,%d\n", (char *)buff, (char *)&ext, size, mx, my);
+
+ gui_window_get_scroll(gw, &sx, &sy);
+
+ window_get_grect(rootwin, BROWSER_AREA_CONTENT, &content_area);
+ mx = mx - content_area.g_x;
+ my = my - content_area.g_y;
+ if((mx < 0 || mx > content_area.g_w)
+ || (my < 0 || my > content_area.g_h))
+ return;
+
+ processed = browser_window_drop_file_at_point(gw->browser->bw,
+ mx+sx, my+sy,
+ NULL);
+ if(processed == true) {
+ nserror ret;
+ char *utf8_fn;
+
+ ret = utf8_from_local_encoding(buff, 0, &utf8_fn);
+ if (ret != NSERROR_OK) {
+ free(buff);
+ /* A bad encoding should never happen */
+ LOG("utf8_from_local_encoding failed");
+ assert(ret != NSERROR_BAD_ENCODING);
+ /* no memory */
+ goto error;
+ }
+ processed = browser_window_drop_file_at_point(gw->browser->bw,
+ mx+sx, my+sy,
+ utf8_fn);
+ free(utf8_fn);
+ }
+
+ if(processed == false) {
+ // TODO: use localized string:
+ if(gemtk_msg_box_show(GEMTK_MSG_BOX_CONFIRM, "Open File?") > 0) {
+ nsurl * ns_url = NULL;
+ char * tmp_url = local_file_to_url(buff);
+ if ((tmp_url != NULL)
+ && nsurl_create(tmp_url, &ns_url) == NSERROR_OK) {
+ browser_window_navigate(gw->browser->bw, ns_url, NULL,
+ BW_NAVIGATE_HISTORY,
+ NULL, NULL, NULL);
+ nsurl_unref(ns_url);
+ }
+ }
+ }
+ }
+ }
+ }
+error:
+ if (buff) {
+ free(buff);
+ }
+ gemtk_dd_close( dd_hdl);
+}
+
+static void toolbar_redraw_cb(GUIWIN *win, uint16_t msg, GRECT *clip)
+{
+ struct rootwin_data_s * ud;
+
+ if (msg != WM_REDRAW) {
+ ud = gemtk_wm_get_user_data(win);
+
+ assert(ud);
+
+ toolbar_redraw(ud->rootwin->toolbar, clip);
+ }
+}
diff --git a/frontends/atari/rootwin.h b/frontends/atari/rootwin.h
new file mode 100644
index 000000000..99b286f70
--- /dev/null
+++ b/frontends/atari/rootwin.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.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 NS_ATARI_BROWSER_WIN_H
+#define NS_ATARI_BROWSER_WIN_H
+
+#include <atari/gui.h>
+
+#define GEMTK_WM_VISIBLE(gw) (gw->root->handle->status & WS_OPEN)
+#define GEMWIN_VISIBLE(win) (win->status & WS_OPEN)
+
+#define WIDGET_STATUSBAR 0x1
+#define WIDGET_TOOLBAR 0x2
+#define WIDGET_SCROLL 0x4
+#define WIDGET_RESIZE 0x8
+#define WIN_TOP 0x100
+
+enum browser_area_e {
+ BROWSER_AREA_CONTENT = 1,
+ BROWSER_AREA_STATUSBAR,
+ BROWSER_AREA_TOOLBAR,
+ BROWSER_AREA_URL_INPUT,
+ BROWSER_AREA_SEARCH
+};
+
+
+/* -------------------------------------------------------------------------- */
+/* Public module functions: */
+/* -------------------------------------------------------------------------- */
+
+/* Creates an normal Browser window with [toolbar], [statusbar] */
+int window_create(struct gui_window * gw,
+ struct browser_window * bw,
+ struct gui_window * existing,
+ unsigned long flags );
+/* Destroys WinDom part of gui_window */
+int window_destroy(ROOTWIN *rootwin);
+
+/** show the window at specified position and make gw the active tab. */
+void window_open(ROOTWIN *rootwin, struct gui_window *gw, GRECT pos);
+
+void window_snd_redraw(ROOTWIN *rootwin, short x, short y, short w, short h );
+/* Update Shade / Unshade state of the fwd/back buttons*/
+void window_update_back_forward(struct s_gui_win_root * rootwin);
+/* set root browser component: */
+void window_attach_browser(ROOTWIN *rootwin, CMP_BROWSER b);
+
+/* set focus element */
+void window_set_focus(ROOTWIN *rootwin, enum focus_element_type type,
+ void * element );
+/* Shade / Unshade the forward/back bt. of toolbar, depending on history.*/
+bool window_widget_has_focus(ROOTWIN *rootwin, enum focus_element_type t,
+ void * element);
+bool window_url_widget_has_focus(ROOTWIN *rootwin);
+void window_set_url(ROOTWIN *rootwin, const char * text);
+void window_set_stauts(ROOTWIN *rootwin, char * text);
+void window_set_title(ROOTWIN *rootwin, char * text);
+void window_set_content_size(ROOTWIN *rootwin, int w, int h);
+void window_set_icon(ROOTWIN *rootwin, struct bitmap * bmp );
+void window_set_active_gui_window(ROOTWIN *rootwin, struct gui_window *gw);
+void window_restore_active_gui_window(ROOTWIN *rootwin);
+void window_open_search(ROOTWIN *rootwin, bool reformat);
+void window_close_search(ROOTWIN *rootwin);
+void window_scroll_by(ROOTWIN *rootwin, int x, int y);
+void window_schedule_redraw_grect(ROOTWIN *rootwin, GRECT *area);
+void window_process_redraws(ROOTWIN * rootwin);
+void window_place_caret(ROOTWIN *rootwin, short mode, int content_x,
+ int content_y, int h, GRECT *work);
+struct gui_window * window_get_active_gui_window(ROOTWIN * rootwin);
+void window_get_scroll(ROOTWIN *rootwin, int *x, int *y);
+void window_get_grect(ROOTWIN *rootwin, enum browser_area_e which, GRECT *d);
+void window_redraw_favicon(struct s_gui_win_root * rootwin, GRECT *clip);
+void window_unref_gui_window(ROOTWIN *rootwin, struct gui_window *gw);
+bool window_key_input(unsigned short kcode, unsigned short kstate,
+ unsigned short nkc);
+
+
+/* -------------------------------------------------------------------------- */
+/* Public event handlers: */
+/* -------------------------------------------------------------------------- */
+
+#endif
diff --git a/frontends/atari/save.h b/frontends/atari/save.h
new file mode 100644
index 000000000..01086be4b
--- /dev/null
+++ b/frontends/atari/save.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2012 Ole Loots <ole@monochrom.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 NSATARI_SAVE_H
+#define NSATARI_SAVE_H
+
+#endif
diff --git a/frontends/atari/schedule.c b/frontends/atari/schedule.c
new file mode 100644
index 000000000..48980426d
--- /dev/null
+++ b/frontends/atari/schedule.c
@@ -0,0 +1,228 @@
+/*
+ * Copyright 2008 Vincent Sanders <vince@simtec.co.uk>
+ * Copyright 2011 Ole Loots <ole@monochrom.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 <time.h>
+
+#include "utils/sys_time.h"
+#include "utils/errors.h"
+
+#include "atari/schedule.h"
+
+#ifdef DEBUG_SCHEDULER
+#include "utils/log.h"
+#else
+#define LOG(x...)
+#endif
+
+#define MS_NOW() ((clock() * 1000) / CLOCKS_PER_SEC)
+
+/* linked list of scheduled callbacks */
+static struct nscallback *schedule_list = NULL;
+
+/**
+ * scheduled callback.
+ */
+struct nscallback
+{
+ struct nscallback *next;
+ unsigned long timeout;
+ void (*callback)(void *p);
+ void *p;
+};
+
+static int max_scheduled;
+static int cur_scheduled;
+
+/**
+ * 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 nscallback *cur_nscb;
+ struct nscallback *prev_nscb;
+ struct nscallback *unlnk_nscb;
+
+ /* check there is something on the list to remove */
+ if (schedule_list == NULL) {
+ return NSERROR_OK;
+ }
+
+ LOG("removing %p, %p", callback, p);
+
+ cur_nscb = schedule_list;
+ prev_nscb = NULL;
+
+ while (cur_nscb != NULL) {
+ if ((cur_nscb->callback == callback) &&
+ (cur_nscb->p == p)) {
+ /* item to remove */
+ LOG("callback entry %p removing %p(%p)", cur_nscb, cur_nscb->callback, cur_nscb->p);
+
+ /* remove callback */
+ unlnk_nscb = cur_nscb;
+ cur_nscb = unlnk_nscb->next;
+
+ if (prev_nscb == NULL) {
+ schedule_list = cur_nscb;
+ } else {
+ prev_nscb->next = cur_nscb;
+ }
+ free (unlnk_nscb);
+ cur_scheduled--;
+ } else {
+ /* move to next element */
+ prev_nscb = cur_nscb;
+ cur_nscb = prev_nscb->next;
+ }
+ }
+ return NSERROR_OK;
+}
+
+/* exported function documented in atari/schedule.h */
+nserror atari_schedule(int ival, void (*callback)(void *p), void *p)
+{
+ struct nscallback *nscb;
+ nserror ret;
+
+ /* remove any existing callback of this kind */
+ ret = schedule_remove(callback, p);
+ if ((ival < 0) || (ret != NSERROR_OK)) {
+ return ret;
+ }
+
+ nscb = calloc(1, sizeof(struct nscallback));
+
+ nscb->timeout = MS_NOW() + ival;
+
+ LOG("adding callback %p for %p(%p) at %d ms", nscb, callback, p, nscb->timeout);
+
+ nscb->callback = callback;
+ nscb->p = p;
+
+ /* add to list front */
+ nscb->next = schedule_list;
+ schedule_list = nscb;
+ cur_scheduled++;
+ if( cur_scheduled > max_scheduled ) {
+ max_scheduled = cur_scheduled;
+ }
+
+ return NSERROR_OK;
+}
+
+
+/* exported function documented in atari/schedule.h */
+int schedule_run(void)
+{
+ unsigned long nexttime;
+ struct nscallback *cur_nscb;
+ struct nscallback *prev_nscb;
+ struct nscallback *unlnk_nscb;
+ unsigned long now = MS_NOW();
+
+ if (schedule_list == NULL)
+ return -1;
+
+ /* reset enumeration to the start of the list */
+ cur_nscb = schedule_list;
+ prev_nscb = NULL;
+ nexttime = cur_nscb->timeout;
+
+ while (cur_nscb != NULL) {
+ if (now > cur_nscb->timeout) {
+ /* scheduled time */
+
+ /* remove callback */
+ unlnk_nscb = cur_nscb;
+ if (prev_nscb == NULL) {
+ schedule_list = unlnk_nscb->next;
+ } else {
+ prev_nscb->next = unlnk_nscb->next;
+ }
+
+ LOG("callback entry %p running %p(%p)", unlnk_nscb, unlnk_nscb->callback, unlnk_nscb->p);
+
+ /* call callback */
+ unlnk_nscb->callback(unlnk_nscb->p);
+ free(unlnk_nscb);
+ cur_scheduled--;
+
+ /* need to deal with callback modifying the list. */
+ if (schedule_list == NULL) {
+ LOG("schedule_list == NULL");
+
+ return -1; /* no more callbacks scheduled */
+ }
+
+ /* reset enumeration to the start of the list */
+ cur_nscb = schedule_list;
+ prev_nscb = NULL;
+ nexttime = cur_nscb->timeout;
+ } else {
+ /* if the time to the event is sooner than the
+ * currently recorded soonest event record it
+ */
+ if (nexttime > cur_nscb->timeout) {
+ nexttime = cur_nscb->timeout;
+ }
+ /* move to next element */
+ prev_nscb = cur_nscb;
+ cur_nscb = prev_nscb->next;
+ }
+ }
+
+ /* make rettime relative to now and convert to ms */
+ nexttime = nexttime - now;
+
+ LOG("returning time to next event as %ldms", nexttime);
+
+ /*return next event time in milliseconds (24days max wait) */
+ return nexttime;
+}
+
+
+/* exported function documented in atari/schedule.h */
+void list_schedule(void)
+{
+ struct nscallback *cur_nscb;
+
+ LOG("schedule list at ms clock %ld", MS_NOW());
+
+ cur_nscb = schedule_list;
+ while (cur_nscb != NULL) {
+ LOG("Schedule %p at %ld", cur_nscb, cur_nscb->timeout);
+ cur_nscb = cur_nscb->next;
+ }
+ LOG("Maxmium callbacks scheduled: %d", max_scheduled);
+}
+
+
+/*
+ * Local Variables:
+ * c-basic-offset:8
+ * End:
+ */
diff --git a/frontends/atari/schedule.h b/frontends/atari/schedule.h
new file mode 100644
index 000000000..05eebb2d7
--- /dev/null
+++ b/frontends/atari/schedule.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2008 Vincent Sanders <vince@simtec.co.uk>
+ * 2012 Ole Loots <ole@monochrom.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 NS_ATARI_SCHEDULE_H
+#define NS_ATARI_SCHEDULE_H
+
+/**
+ * Process events up to current time.
+ *
+ * \return The number of miliseconds until the next scheduled event.
+ */
+int schedule_run(void);
+
+/**
+ * Schedule a callback.
+ *
+ * \param ival interval before the callback should be made in miliseconds.
+ * \param callback callback function.
+ * \param p user parameter, passed to callback function.
+ * \return NSERROR_OK on success or appropriate error code.
+ *
+ * The callback function will be called as soon as possible after \a ival
+ * ms have passed.
+ */
+nserror atari_schedule(int ival, void (*callback)(void *p), void *p);
+
+/**
+ * LOG all current scheduled events.
+ */
+void list_schedule(void);
+
+#endif
diff --git a/frontends/atari/scripts/env-v4e.sh b/frontends/atari/scripts/env-v4e.sh
new file mode 100755
index 000000000..6e353ffe4
--- /dev/null
+++ b/frontends/atari/scripts/env-v4e.sh
@@ -0,0 +1,7 @@
+export GCCSDK_INSTALL_CROSSBIN=/opt/netsurf-v4e/m5475-atari-mint/cross/bin/
+export GCCSDK_INSTALL_ENV="/opt/netsurf-v4e/m5475-atari-mint/env"
+export PATH=/opt/netsurf-v4e/m5475-atari-mint/cross/bin:$PATH
+export PREFIX=/opt/netsurf-v4e/
+export LD_LIBRARY_PATH=/opt/netsurf-v4e/m5475-atari-mint/lib:/opt/netsurf-v4e/m5475-atari-mint/env/lib/
+export PKG_CONFIG_PATH=/opt/netsurf-v4e/m5475-atari-mint/env/lib/pkgconfig:/opt/netsurf-v4e/lib/pkgconfig
+export C_INCLUDE_PATH=/opt/netsurf-v4e/include/:/opt/netsurf-v4e/m5475-atari-mint/env/include/
diff --git a/frontends/atari/scripts/env-x86.sh b/frontends/atari/scripts/env-x86.sh
new file mode 100755
index 000000000..027da3f3b
--- /dev/null
+++ b/frontends/atari/scripts/env-x86.sh
@@ -0,0 +1,9 @@
+#export PKG_CONFIG_PATH=${HOME}/netsurf/workspace_gtk/inst/lib/pkgconfig::
+#export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${HOME}/netsurf/workspace_gtk/inst/lib
+#export PREFIX=${HOME}/netsurf/workspace_gtk/inst
+
+export PATH=/opt/netsurf/x86/bin:$PATH
+export PREFIX=/opt/netsurf/x86
+export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/opt/netsurf/x86/lib
+export PKG_CONFIG_PATH=${PKG_CONFIG_PATH}:/opt/netsurf/x86/lib/pkgconfig
+
diff --git a/frontends/atari/search.c b/frontends/atari/search.c
new file mode 100644
index 000000000..d72d3caaa
--- /dev/null
+++ b/frontends/atari/search.c
@@ -0,0 +1,303 @@
+/*
+ * Copyright 2013 Ole Loots <ole@monochrom.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 <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdbool.h>
+#include <assert.h>
+
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "desktop/browser.h"
+#include "desktop/search.h"
+#include "desktop/gui_search.h"
+
+#include "atari/gui.h"
+#include "atari/rootwin.h"
+#include "atari/misc.h"
+#include "atari/toolbar.h"
+#include "atari/search.h"
+#include "atari/gemtk/gemtk.h"
+#include "atari/res/netsurf.rsh"
+
+extern struct gui_window * input_window;
+
+
+static void nsatari_search_set_status(bool found, void *p);
+static void nsatari_search_set_hourglass(bool active, void *p);
+static void nsatari_search_add_recent(const char *string, void *p);
+void nsatari_search_set_forward_state(bool active, void *p);
+void nsatari_search_set_back_state(bool active, void *p);
+
+static struct gui_search_table search_table = {
+ nsatari_search_set_status,
+ nsatari_search_set_hourglass,
+ nsatari_search_add_recent,
+ nsatari_search_set_forward_state,
+ nsatari_search_set_back_state,
+};
+
+struct gui_search_table *atari_search_table = &search_table;
+
+
+
+/**
+ * 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 nsatari_search_set_status(bool found, void *p)
+{
+ LOG("%p set status: %d\n", p, found);
+ // TODO: maybe update GUI
+}
+
+
+/**
+ * display hourglass while searching
+ * \param active start/stop indicator
+ * \param p the pointer sent to search_verify_new() / search_create_context()
+ */
+void nsatari_search_set_hourglass(bool active, void *p)
+{
+ SEARCH_FORM_SESSION s = (SEARCH_FORM_SESSION)p;
+ LOG("active: %d, session: %p", active, p);
+ if (active) {
+ gui_window_set_pointer(s->g, GUI_POINTER_PROGRESS);
+ } else {
+ gui_window_set_pointer(s->g, GUI_POINTER_DEFAULT);
+ }
+}
+
+
+/**
+ * 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;
+ * core gives no guarantee of the integrity of the const char *
+ * \param string search pattern
+ * \param p the pointer sent to search_verify_new() / search_create_context()
+ */
+void nsatari_search_add_recent(const char *string, void *p)
+{
+ LOG("%p add recent: %s\n", p, string);
+}
+
+
+/**
+ * activate search forwards button in gui
+ * \param active activate/inactivate
+ * \param p the pointer sent to search_verify_new() / search_create_context()
+ */
+void nsatari_search_set_forward_state(bool active, void *p)
+{
+ struct gui_window *gw;
+ OBJECT *toolbar;
+ GRECT area;
+ SEARCH_FORM_SESSION s = (SEARCH_FORM_SESSION)p;
+ /* deactivate back cb */
+ LOG("%p: set forward state: %d\n", p, active);
+
+ gw = s->g;
+
+ toolbar = toolbar_get_form(gw->root->toolbar);
+ if (active) {
+ toolbar[TOOLBAR_BT_SEARCH_FWD].ob_state &= ~OS_DISABLED;
+ } else {
+ toolbar[TOOLBAR_BT_SEARCH_FWD].ob_state |= OS_DISABLED;
+ }
+ window_get_grect(gw->root, BROWSER_AREA_SEARCH, &area);
+ window_schedule_redraw_grect(gw->root, &area);
+}
+
+
+/**
+ * activate search back button in gui
+ * \param active activate/inactivate
+ * \param p the pointer sent to search_verify_new() / search_create_context()
+ */
+void nsatari_search_set_back_state(bool active, void *p)
+{
+ struct gui_window *gw;
+ OBJECT *toolbar;
+ GRECT area;
+ SEARCH_FORM_SESSION s = (SEARCH_FORM_SESSION)p;
+ /* deactivate back cb */
+ LOG("%p: set back state: %d\n", p, active);
+
+ s->state.back_avail = active;
+ gw = s->g;
+
+ toolbar = toolbar_get_form(gw->root->toolbar);
+ if (active) {
+ toolbar[TOOLBAR_BT_SEARCH_BACK].ob_state &= ~OS_DISABLED;
+ } else {
+ toolbar[TOOLBAR_BT_SEARCH_BACK].ob_state |= OS_DISABLED;
+ }
+ window_get_grect(gw->root, BROWSER_AREA_SEARCH, &area);
+ window_schedule_redraw_grect(gw->root, &area);
+}
+
+
+static int apply_form(OBJECT *obj, struct s_search_form_state *s)
+{
+ char * cstr;
+
+ assert(s != NULL);
+
+ s->flags = 0;
+
+ if ((obj[TOOLBAR_CB_CASESENSE].ob_state & OS_SELECTED) != 0 ) {
+ s->flags |= SEARCH_FLAG_CASE_SENSITIVE;
+ }
+ if ((obj[TOOLBAR_CB_SHOWALL].ob_state & OS_SELECTED) != 0 ) {
+ s->flags |= SEARCH_FLAG_SHOWALL;
+ }
+
+ cstr = gemtk_obj_get_text(obj, TOOLBAR_TB_SRCH);
+ snprintf(s->text, 32, "%s", cstr);
+ return ( 0 );
+
+}
+
+static void set_text(OBJECT *obj, short idx, char * text, int len)
+{
+ char spare[255];
+
+ if (len > 254) {
+ len = 254;
+ }
+ if (text != NULL) {
+ strncpy(spare, text, 254);
+ } else {
+ strcpy(spare, "");
+ }
+
+ set_string(obj, idx, spare);
+}
+
+
+void nsatari_search_restore_form( struct s_search_form_session *s, OBJECT *obj)
+{
+ if ((s->state.flags & SEARCH_FLAG_SHOWALL) != 0) {
+ obj[TOOLBAR_CB_SHOWALL].ob_state |= OS_SELECTED;
+ } else {
+ obj[TOOLBAR_CB_SHOWALL].ob_state &= ~OS_SELECTED;
+ }
+
+ if ((s->state.flags & SEARCH_FLAG_CASE_SENSITIVE) != 0) {
+ obj[TOOLBAR_CB_CASESENSE].ob_state |= OS_SELECTED;
+ } else {
+ obj[TOOLBAR_CB_CASESENSE].ob_state &= ~OS_SELECTED;
+ }
+
+ if (s->state.back_avail == false) {
+ obj[TOOLBAR_BT_SEARCH_BACK].ob_state |= OS_DISABLED;
+ } else {
+ obj[TOOLBAR_BT_SEARCH_BACK].ob_state &= ~OS_DISABLED;
+ }
+
+ TEDINFO *t = ((TEDINFO *)get_obspec(obj, TOOLBAR_TB_SRCH));
+ set_text(obj, TOOLBAR_TB_SRCH, s->state.text, t->te_txtlen);
+}
+
+
+void nsatari_search_session_destroy(struct s_search_form_session *s)
+{
+ if (s != NULL) {
+ LOG("session %p", s);
+ browser_window_search_clear(s->g->browser->bw);
+ free(s);
+ }
+}
+
+
+/** checks for search parameters changes */
+static bool search_session_compare(struct s_search_form_session *s, OBJECT *obj)
+{
+ uint32_t flags_old;
+ uint32_t flags_mask = SEARCH_FLAG_SHOWALL | SEARCH_FLAG_CASE_SENSITIVE;
+ struct s_search_form_state cur;
+
+ assert(s != NULL && obj != NULL);
+
+ flags_old = s->state.flags;
+
+ apply_form(obj, &cur);
+ if ((cur.flags&flags_mask) != (flags_old&flags_mask)) {
+ return( true );
+ }
+
+ char * cstr;
+ cstr = gemtk_obj_get_text(obj, TOOLBAR_TB_SRCH);
+ if (cstr != NULL) {
+ if (strcmp(cstr, (char*)&s->state.text) != 0) {
+ return (true);
+ }
+ }
+
+ return( false );
+}
+
+
+void nsatari_search_perform(struct s_search_form_session *s, OBJECT *obj,
+ search_flags_t f)
+{
+ assert(s!=null);
+ assert(input_window->browser->bw == s->g->browser->bw);
+
+ if (search_session_compare(s, obj)) {
+ browser_window_search_clear(s->g->browser->bw);
+ apply_form(obj, &s->state);
+ }
+
+ /* get search direction manually: */
+ if ( (f&SEARCH_FLAG_FORWARDS) != 0 ) {
+ s->state.flags |= SEARCH_FLAG_FORWARDS;
+ } else {
+ s->state.flags &= (~SEARCH_FLAG_FORWARDS);
+ }
+
+ browser_window_search(s->g->browser->bw, s,
+ s->state.flags,
+ gemtk_obj_get_text(obj, TOOLBAR_TB_SRCH));
+}
+
+
+struct s_search_form_session * nsatari_search_session_create(OBJECT * obj,
+ struct gui_window *gw)
+{
+ struct s_search_form_session *sfs;
+
+ sfs = calloc(1, sizeof(struct s_search_form_session));
+
+ assert(obj);
+ assert(sfs);
+
+ sfs->g = gw;
+
+ apply_form(obj, &sfs->state);
+
+ browser_window_search_clear(gw->browser->bw);
+
+ return(sfs);
+}
diff --git a/frontends/atari/search.h b/frontends/atari/search.h
new file mode 100644
index 000000000..04dfed4eb
--- /dev/null
+++ b/frontends/atari/search.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2013 Ole Loots <ole@monochrom.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 NS_ATARI_SEARCH_H
+#define NS_ATARI_SEARCH_H
+
+#define SEARCH_MAX_SLEN 24
+
+struct gui_window;
+struct browser_window;
+
+#include "desktop/search.h"
+
+struct s_search_form_state {
+ char text[32];
+ uint32_t flags;
+ bool back_avail;
+};
+
+struct s_search_form_session {
+ struct gui_window *g;
+ struct s_search_form_state state;
+};
+
+typedef struct s_search_form_session * SEARCH_FORM_SESSION;
+
+struct s_search_form_session * nsatari_search_session_create(OBJECT * obj,
+ struct gui_window *gw);
+
+struct gui_search_table *atari_search_table;
+
+void nsatari_search_session_destroy(struct s_search_form_session *s);
+void nsatari_search_perform(struct s_search_form_session *s, OBJECT *obj,
+ search_flags_t f);
+void nsatari_search_restore_form( struct s_search_form_session *s, OBJECT *obj);
+
+#endif
diff --git a/frontends/atari/settings.c b/frontends/atari/settings.c
new file mode 100644
index 000000000..b6df12760
--- /dev/null
+++ b/frontends/atari/settings.c
@@ -0,0 +1,990 @@
+/*
+ * Copyright 2013 Ole Loots <ole@monochrom.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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <time.h>
+#include <limits.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdbool.h>
+#include <cflib.h>
+#include <gem.h>
+
+#include "utils/dirent.h"
+#include "utils/nsoption.h"
+#include "utils/log.h"
+#include "desktop/plot_style.h"
+
+#include "atari/gui.h"
+#include "atari/res/netsurf.rsh"
+#include "atari/settings.h"
+#include "atari/deskmenu.h"
+#include "atari/misc.h"
+#include "atari/plot/plot.h"
+#include "atari/bitmap.h"
+#include "atari/findfile.h"
+#include "atari/gemtk/gemtk.h"
+
+extern char options[PATH_MAX];
+extern GRECT desk_area;
+
+static float tmp_option_minimum_gif_delay;
+static unsigned tmp_option_memory_cache_size;
+static unsigned int tmp_option_disc_cache_size;
+static unsigned int tmp_option_expire_url;
+static unsigned int tmp_option_disc_cache_age;
+static unsigned int tmp_option_font_min_size;
+static unsigned int tmp_option_font_size;
+static unsigned int tmp_option_min_reflow_period;
+static unsigned int tmp_option_max_fetchers;
+static unsigned int tmp_option_max_fetchers_per_host;
+static unsigned int tmp_option_max_cached_fetch_handles;
+
+static int num_locales = 0;
+static char **locales = NULL;
+static short h_aes_win = 0;
+static GUIWIN * settings_guiwin = NULL;
+static OBJECT * dlgtree;
+
+/* Available font engines for the font engine selection popup: */
+static const char *font_engines[] = {
+
+#ifdef WITH_FREETYPE_FONT_DRIVER
+ "freetype",
+#endif
+
+#ifdef WITH_INTERNAL_FONT_DRIVER
+ "internal",
+#endif
+
+#ifdef WITH_VDI_FONT_DRIVER
+ "vdi",
+#endif
+};
+
+/* Available GUI timeouts for the timeout selection popup: */
+static const char *gui_timeouts[] = {
+ "0", "5", "10"
+};
+
+#define OBJ_SELECTED(idx) ((bool)((dlgtree[idx].ob_state & OS_SELECTED)!=0))
+
+#define OBJ_CHECK(idx) (dlgtree[idx].ob_state |= (OS_SELECTED));
+
+#define OBJ_UNCHECK(idx) (dlgtree[idx].ob_state &= ~(OS_SELECTED));
+
+#define OBJ_REDRAW(idx) gemtk_wm_exec_redraw(settings_guiwin, \
+ gemtk_obj_screen_rect(dlgtree, idx));
+
+#define DISABLE_OBJ(idx) (dlgtree[idx].ob_state |= OS_DISABLED); \
+ gemtk_wm_exec_redraw(settings_guiwin, \
+ gemtk_obj_screen_rect(dlgtree, idx));
+
+#define ENABLE_OBJ(idx) (dlgtree[idx].ob_state &= ~(OS_DISABLED)); \
+ gemtk_wm_exec_redraw(settings_guiwin, \
+ gemtk_obj_screen_rect(dlgtree, idx));
+
+#define FORMEVENT(idx) form_event(idx, 0);
+
+#define INPUT_HOMEPAGE_URL_MAX_LEN 44
+#define INPUT_LOCALE_MAX_LEN 6
+#define INPUT_PROXY_HOST_MAX_LEN 31
+#define INPUT_PROXY_USERNAME_MAX_LEN 36
+#define INPUT_PROXY_PASSWORD_MAX_LEN 36
+#define INPUT_PROXY_PORT_MAX_LEN 5
+#define INPUT_MIN_REFLOW_PERIOD_MAX_LEN 4
+#define LABEL_FONT_RENDERER_MAX_LEN 8
+#define LABEL_PATH_MAX_LEN 40
+#define LABEL_ICONSET_MAX_LEN 8
+#define INPUT_TOOLBAR_COLOR_MAX_LEN 6
+
+
+static void display_settings(void);
+static void form_event(int index, int external);
+static void apply_settings(void);
+static void save_settings(void);
+
+
+static void set_text( short idx, char * text, int len )
+{
+ char spare[255];
+
+ if( len > 254 )
+ len = 254;
+ if( text != NULL ) {
+ strncpy(spare, text, 254);
+ } else {
+ strcpy(spare, "");
+ }
+
+ set_string( dlgtree, idx, spare);
+}
+
+
+
+
+/**
+ * Toogle all objects which are directly influenced by other GUI elements
+ * ( like checkbox )
+ */
+static void toggle_objects(void)
+{
+ /* enable / disable (refresh) objects depending on radio button values: */
+ /* Simulate GUI events which trigger refresh of bound elements: */
+ FORMEVENT(SETTINGS_CB_USE_PROXY);
+ FORMEVENT(SETTINGS_CB_PROXY_AUTH);
+ FORMEVENT(SETTINGS_BT_SEL_FONT_RENDERER);
+}
+
+static char **read_locales(void)
+{
+ char buf[PATH_MAX];
+ char tmp_locale[16];
+ char **locales = NULL;
+
+ FILE * fp_locales = NULL;
+
+ atari_find_resource(buf, "languages", "./res/languages");
+
+ fp_locales = fopen(buf, "r");
+
+ if (fp_locales == NULL) {
+ atari_warn_user("Failed to load locales: %s",buf);
+ return(NULL);
+ } else {
+ LOG("Reading locales from: %s...", buf);
+ }
+
+ /* Count items: */
+ num_locales = 0;
+ while (fgets(tmp_locale, 16, fp_locales) != NULL) {
+ num_locales++;
+ }
+
+ locales = malloc(sizeof(char*)*num_locales);
+
+ rewind(fp_locales);
+ int i = 0;
+ while (fgets(tmp_locale, 16, fp_locales) != NULL) {
+ int len = strlen(tmp_locale);
+ tmp_locale[len-1] = 0;
+ len--;
+ locales[i] = malloc(len+1);
+ // do not copy the last \n
+ snprintf(locales[i], 16, "%s", tmp_locale);
+ i++;
+ }
+
+ fclose(fp_locales);
+
+ return(locales);
+}
+
+
+static void save_settings(void)
+{
+ apply_settings();
+ // Save settings
+ nsoption_write( (const char*)&options, NULL, NULL);
+ nsoption_read( (const char*)&options , NULL);
+ close_settings();
+ form_alert(1, "[1][Some options require an netsurf restart!][OK]");
+ deskmenu_update();
+}
+
+/* this gets called each time the settings dialog is opened: */
+static void display_settings(void)
+{
+ char spare[255];
+ // read current settings and display them
+
+
+ /* "Browser" tab: */
+ set_text( SETTINGS_EDIT_HOMEPAGE, nsoption_charp(homepage_url),
+ INPUT_HOMEPAGE_URL_MAX_LEN );
+
+ if( nsoption_bool(block_advertisements) ) {
+ OBJ_CHECK( SETTINGS_CB_HIDE_ADVERTISEMENT );
+ } else {
+ OBJ_UNCHECK( SETTINGS_CB_HIDE_ADVERTISEMENT );
+ }
+ if( nsoption_bool(target_blank) ) {
+ OBJ_UNCHECK( SETTINGS_CB_DISABLE_POPUP_WINDOWS );
+ } else {
+ OBJ_CHECK( SETTINGS_CB_DISABLE_POPUP_WINDOWS );
+ }
+ if( nsoption_bool(send_referer) ) {
+ OBJ_CHECK( SETTINGS_CB_SEND_HTTP_REFERRER );
+ } else {
+ OBJ_UNCHECK( SETTINGS_CB_SEND_HTTP_REFERRER );
+ }
+ if( nsoption_bool(do_not_track) ) {
+ OBJ_CHECK( SETTINGS_CB_SEND_DO_NOT_TRACK );
+ } else {
+ OBJ_UNCHECK( SETTINGS_CB_SEND_DO_NOT_TRACK );
+ }
+
+ set_text( SETTINGS_BT_SEL_LOCALE,
+ nsoption_charp(accept_language) ? nsoption_charp(accept_language) : (char*)"en",
+ INPUT_LOCALE_MAX_LEN );
+
+ sprintf(spare, "%d", nsoption_int(atari_gui_poll_timeout));
+ set_text(SETTINGS_BT_GUI_TOUT, spare, 2);
+
+ tmp_option_expire_url = nsoption_int(expire_url);
+ snprintf( spare, 255, "%02d", nsoption_int(expire_url) );
+ set_text( SETTINGS_EDIT_HISTORY_AGE, spare, 3);
+
+ /* "Cache" tab: */
+ tmp_option_memory_cache_size = nsoption_int(memory_cache_size) / (1024*1024);
+ snprintf( spare, 255, "%d", tmp_option_memory_cache_size );
+ set_text( SETTINGS_STR_MAX_MEM_CACHE, spare, 4 );
+
+ tmp_option_disc_cache_size = nsoption_int(disc_cache_size) / (1024*1024);
+ snprintf( spare, 255, "%d", tmp_option_disc_cache_size );
+ set_text( SETTINGS_STR_MAX_DISC_CACHE, spare, 4 );
+
+ tmp_option_disc_cache_age = nsoption_int(disc_cache_age);
+ snprintf( spare, 255, "%02d", tmp_option_disc_cache_age );
+ set_text( SETTINGS_EDIT_CACHE_AGE, spare, 3 );
+
+ /* "Paths" tab: */
+ set_text( SETTINGS_EDIT_DOWNLOAD_PATH, nsoption_charp(downloads_path),
+ LABEL_PATH_MAX_LEN );
+ set_text( SETTINGS_EDIT_HOTLIST_FILE, nsoption_charp(hotlist_file),
+ LABEL_PATH_MAX_LEN );
+ set_text( SETTINGS_EDIT_CA_BUNDLE, nsoption_charp(ca_bundle),
+ LABEL_PATH_MAX_LEN );
+ set_text( SETTINGS_EDIT_CA_CERTS_PATH, nsoption_charp(ca_path),
+ LABEL_PATH_MAX_LEN );
+ set_text( SETTINGS_EDIT_EDITOR, nsoption_charp(atari_editor),
+ LABEL_PATH_MAX_LEN );
+
+ /* "Rendering" tab: */
+ set_text( SETTINGS_BT_SEL_FONT_RENDERER, nsoption_charp(atari_font_driver),
+ LABEL_FONT_RENDERER_MAX_LEN );
+ SET_BIT(dlgtree[SETTINGS_CB_TRANSPARENCY].ob_state,
+ OS_SELECTED, nsoption_int(atari_transparency) ? 1 : 0 );
+ SET_BIT(dlgtree[SETTINGS_CB_ENABLE_ANIMATION].ob_state,
+ OS_SELECTED, nsoption_bool(animate_images) ? 1 : 0 );
+ SET_BIT(dlgtree[SETTINGS_CB_FG_IMAGES].ob_state,
+ OS_SELECTED, nsoption_bool(foreground_images) ? 1 : 0 );
+ SET_BIT(dlgtree[SETTINGS_CB_BG_IMAGES].ob_state,
+ OS_SELECTED, nsoption_bool(background_images) ? 1 : 0 );
+
+
+ // TODO: enable this option?
+ /* SET_BIT(dlgtree[SETTINGS_CB_INCREMENTAL_REFLOW].ob_state,
+ OS_SELECTED, nsoption_bool(incremental_reflow) ? 1 : 0 );*/
+
+ SET_BIT(dlgtree[SETTINGS_CB_ANTI_ALIASING].ob_state,
+ OS_SELECTED, nsoption_int(atari_font_monochrom) ? 0 : 1 );
+
+
+ // TODO: activate this option?
+ tmp_option_min_reflow_period = nsoption_int(min_reflow_period);
+ snprintf( spare, 255, "%04d", tmp_option_min_reflow_period );
+ set_text( SETTINGS_EDIT_MIN_REFLOW_PERIOD, spare,
+ INPUT_MIN_REFLOW_PERIOD_MAX_LEN );
+
+
+ tmp_option_minimum_gif_delay = (float)nsoption_int(minimum_gif_delay) / (float)100;
+ snprintf( spare, 255, "%01.1f", tmp_option_minimum_gif_delay );
+ set_text( SETTINGS_EDIT_MIN_GIF_DELAY, spare, 3 );
+
+ /* "Network" tab: */
+ set_text( SETTINGS_EDIT_PROXY_HOST, nsoption_charp(http_proxy_host),
+ INPUT_PROXY_HOST_MAX_LEN );
+ snprintf( spare, 255, "%5d", nsoption_int(http_proxy_port) );
+ set_text( SETTINGS_EDIT_PROXY_PORT, spare,
+ INPUT_PROXY_PORT_MAX_LEN );
+
+ set_text( SETTINGS_EDIT_PROXY_USERNAME, nsoption_charp(http_proxy_auth_user),
+ INPUT_PROXY_USERNAME_MAX_LEN );
+ set_text( SETTINGS_EDIT_PROXY_PASSWORD, nsoption_charp(http_proxy_auth_pass),
+ INPUT_PROXY_PASSWORD_MAX_LEN );
+ SET_BIT(dlgtree[SETTINGS_CB_USE_PROXY].ob_state,
+ OS_SELECTED, nsoption_bool(http_proxy) ? 1 : 0 );
+ SET_BIT(dlgtree[SETTINGS_CB_PROXY_AUTH].ob_state,
+ OS_SELECTED, nsoption_int(http_proxy_auth) ? 1 : 0 );
+
+ tmp_option_max_cached_fetch_handles = nsoption_int(max_cached_fetch_handles);
+ snprintf( spare, 255, "%2d", nsoption_int(max_cached_fetch_handles) );
+ set_text( SETTINGS_EDIT_MAX_CACHED_CONNECTIONS, spare , 2 );
+
+ tmp_option_max_fetchers = nsoption_int(max_fetchers);
+ snprintf( spare, 255, "%2d", nsoption_int(max_fetchers) );
+ set_text( SETTINGS_EDIT_MAX_FETCHERS, spare , 2 );
+
+ tmp_option_max_fetchers_per_host = nsoption_int(max_fetchers_per_host);
+ snprintf( spare, 255, "%2d", nsoption_int(max_fetchers_per_host) );
+ set_text( SETTINGS_EDIT_MAX_FETCHERS_PER_HOST, spare , 2 );
+
+
+ /* "Style" tab: */
+ tmp_option_font_min_size = nsoption_int(font_min_size);
+ snprintf( spare, 255, "%3d", nsoption_int(font_min_size) );
+ set_text( SETTINGS_EDIT_MIN_FONT_SIZE, spare , 3 );
+
+ tmp_option_font_size = nsoption_int(font_size);
+ snprintf( spare, 255, "%3d", nsoption_int(font_size) );
+ set_text( SETTINGS_EDIT_DEF_FONT_SIZE, spare , 3 );
+
+ toggle_objects();
+}
+
+static void handle_filesystem_select_button(short rsc_bt)
+{
+ bool require_path = false;
+ bool is_folder = false;
+ short rsc_te = 0; // The textarea that is bound to the button
+ const char * title = "";
+ const char * path = NULL;
+
+ // TODO: localize String:
+ switch (rsc_bt) {
+
+
+ case SETTINGS_BT_SEL_DOWNLOAD_DIR:
+ title = "Select Download Directory:";
+ rsc_te = SETTINGS_EDIT_DOWNLOAD_PATH;
+ require_path = true;
+ break;
+
+ case SETTINGS_BT_SEL_HOTLIST:
+ title = "Select Hotlist File:";
+ rsc_te = SETTINGS_EDIT_HOTLIST_FILE;
+ break;
+
+ case SETTINGS_BT_SEL_CA_BUNDLE:
+ title = "Select CA Bundle File:";
+ rsc_te = SETTINGS_EDIT_CA_BUNDLE;
+ break;
+
+ case SETTINGS_BT_SEL_CA_CERTS:
+ title = "Select Certs Directory:";
+ rsc_te = SETTINGS_EDIT_CA_CERTS_PATH;
+ require_path = true;
+ break;
+
+ case SETTINGS_BT_SEL_EDITOR:
+ title = "Select Editor Application:";
+ rsc_te = SETTINGS_EDIT_EDITOR;
+ break;
+
+ default:
+ break;
+ };
+
+ assert(rsc_te != 0);
+
+ if (require_path == false) {
+ path = file_select(title, "");
+ if (path != NULL) {
+ gemtk_obj_set_str_safe(dlgtree, rsc_te, path);
+ }
+ }
+ else {
+ do {
+ /* display file selector: */
+ path = file_select(title, "");
+ if (path) {
+ is_folder = is_dir(path);
+ }
+ if ((is_folder == false) && (path != NULL)) {
+ gemtk_msg_box_show(GEMTK_MSG_BOX_ALERT, "Folder Required!");
+ }
+ } while ((is_folder == false) && (path != NULL));
+
+ if ((is_folder == true) && (path != NULL)) {
+ gemtk_obj_set_str_safe(dlgtree, rsc_te, path);
+ }
+ }
+
+ OBJ_UNCHECK(rsc_bt);
+ OBJ_REDRAW(rsc_bt);
+ OBJ_REDRAW(rsc_te);
+}
+
+static void form_event(int index, int external)
+{
+ char spare[255];
+ bool is_button = false;
+ bool checked = OBJ_SELECTED(index);
+ char * tmp;
+ MENU pop_menu, me_data;
+
+ short x, y;
+ int choice;
+
+ switch(index) {
+
+ case SETTINGS_CB_USE_PROXY:
+ if( checked ) {
+ ENABLE_OBJ(SETTINGS_EDIT_PROXY_HOST);
+ ENABLE_OBJ(SETTINGS_EDIT_PROXY_PORT);
+ ENABLE_OBJ(SETTINGS_CB_PROXY_AUTH);
+ } else {
+ DISABLE_OBJ(SETTINGS_EDIT_PROXY_HOST);
+ DISABLE_OBJ(SETTINGS_EDIT_PROXY_PORT);
+ DISABLE_OBJ(SETTINGS_CB_PROXY_AUTH);
+ }
+ FORMEVENT(SETTINGS_CB_PROXY_AUTH);
+ OBJ_REDRAW(SETTINGS_CB_USE_PROXY);
+ break;
+
+ case SETTINGS_CB_PROXY_AUTH:
+ if( checked && OBJ_SELECTED( SETTINGS_CB_USE_PROXY ) ) {
+ ENABLE_OBJ(SETTINGS_EDIT_PROXY_USERNAME);
+ ENABLE_OBJ(SETTINGS_EDIT_PROXY_PASSWORD);
+ } else {
+ DISABLE_OBJ(SETTINGS_EDIT_PROXY_USERNAME);
+ DISABLE_OBJ(SETTINGS_EDIT_PROXY_PASSWORD);
+ }
+ break;
+
+ case SETTINGS_CB_ENABLE_ANIMATION:
+ if( checked ) {
+ ENABLE_OBJ( SETTINGS_EDIT_MIN_GIF_DELAY );
+ } else {
+ DISABLE_OBJ( SETTINGS_EDIT_MIN_GIF_DELAY );
+ }
+ break;
+
+ case SETTINGS_BT_SEL_FONT_RENDERER:
+ if( external ) {
+ objc_offset(dlgtree, SETTINGS_BT_SEL_FONT_RENDERER, &x, &y);
+ tmp = gemtk_obj_get_text(dlgtree, SETTINGS_BT_SEL_FONT_RENDERER);
+ // point mn_tree tree to font renderer popup:
+ pop_menu.mn_tree = gemtk_obj_create_popup_tree(font_engines,
+ NOF_ELEMENTS(font_engines), tmp, false,
+ -1, -1);
+
+ assert(pop_menu.mn_tree != NULL);
+
+ pop_menu.mn_menu = 0;
+ pop_menu.mn_item = 1;
+ pop_menu.mn_scroll = SCROLL_NO;
+ pop_menu.mn_keystate = 0;
+
+ /* Show the popup: */
+ menu_popup(&pop_menu, x, y, &me_data);
+ choice = me_data.mn_item;
+
+ /* Process selection: */
+ if (choice > 0 && choice <= (short)NOF_ELEMENTS(font_engines)) {
+ get_string(pop_menu.mn_tree, choice, spare);
+ set_text(SETTINGS_BT_SEL_FONT_RENDERER,
+ (char*)&spare[2],
+ LABEL_FONT_RENDERER_MAX_LEN);
+ OBJ_REDRAW(SETTINGS_BT_SEL_FONT_RENDERER);
+ }
+
+ gemtk_obj_destroy_popup_tree(pop_menu.mn_tree);
+ }
+ tmp = gemtk_obj_get_text(dlgtree, SETTINGS_BT_SEL_FONT_RENDERER);
+ if (strcasecmp(tmp, "freetype") == 0) {
+ ENABLE_OBJ(SETTINGS_CB_ANTI_ALIASING);
+ } else {
+ DISABLE_OBJ(SETTINGS_CB_ANTI_ALIASING);
+ }
+ break;
+
+ case SETTINGS_BT_SEL_LOCALE:
+ objc_offset(dlgtree, SETTINGS_BT_SEL_LOCALE, &x, &y);
+
+ if(num_locales < 1 || locales == NULL){
+ locales = read_locales();
+ }
+
+ if (num_locales < 1 || locales == NULL) {
+ // point mn_tree tree to states popup:
+ num_locales = 15;
+ pop_menu.mn_tree = gemtk_obj_get_tree(POP_LANGUAGE);
+ pop_menu.mn_item = POP_LANGUAGE_CS;
+ } else {
+ // point mn_tree tree to dynamic list:
+ tmp = gemtk_obj_get_text(dlgtree, SETTINGS_BT_SEL_LOCALE);
+ pop_menu.mn_tree = gemtk_obj_create_popup_tree((const char**)locales,
+ num_locales, tmp, false,
+ -1, 100);
+
+ pop_menu.mn_item = 0;
+ }
+
+ pop_menu.mn_menu = 0;
+ pop_menu.mn_scroll = SCROLL_YES;
+ pop_menu.mn_keystate = 0;
+
+ /* display popup: */
+ menu_popup(&pop_menu, x, y, &me_data);
+
+ /* Process user selection: */
+ choice = me_data.mn_item;
+ if( choice > 0 && choice <= num_locales ) {
+ get_string(pop_menu.mn_tree, choice, spare);
+ set_text(SETTINGS_BT_SEL_LOCALE, (char*)&spare[2], 5);
+ }
+
+ gemtk_obj_destroy_popup_tree(pop_menu.mn_tree);
+
+ OBJ_REDRAW(SETTINGS_BT_SEL_LOCALE);
+ break;
+
+ case SETTINGS_BT_GUI_TOUT:
+ objc_offset(dlgtree, SETTINGS_BT_GUI_TOUT, &x, &y);
+ tmp = gemtk_obj_get_text(dlgtree, SETTINGS_BT_GUI_TOUT);
+ pop_menu.mn_tree = gemtk_obj_create_popup_tree(gui_timeouts,
+ NOF_ELEMENTS(gui_timeouts), tmp, false, -1,
+ 100);
+
+ pop_menu.mn_item = 0;
+ pop_menu.mn_menu = 0;
+ pop_menu.mn_scroll = SCROLL_NO;
+ pop_menu.mn_keystate = 0;
+
+ /* Display popup: */
+ menu_popup(&pop_menu, x, y, &me_data);
+
+ /* Process user selection: */
+ choice = me_data.mn_item;
+ if( choice > 0 && choice <= (int)NOF_ELEMENTS(gui_timeouts)) {
+ get_string(pop_menu.mn_tree, choice, spare);
+ set_text(SETTINGS_BT_GUI_TOUT, (char*)&spare[2], 5);
+ }
+
+ gemtk_obj_destroy_popup_tree(pop_menu.mn_tree);
+
+ OBJ_REDRAW(SETTINGS_BT_GUI_TOUT);
+ break;
+
+ case SETTINGS_BT_SEL_DOWNLOAD_DIR:
+ case SETTINGS_BT_SEL_HOTLIST:
+ case SETTINGS_BT_SEL_CA_BUNDLE:
+ case SETTINGS_BT_SEL_CA_CERTS:
+ case SETTINGS_BT_SEL_EDITOR:
+ handle_filesystem_select_button(index);
+ break;
+
+ case SETTINGS_INC_MEM_CACHE:
+ case SETTINGS_DEC_MEM_CACHE:
+ if( index == SETTINGS_DEC_MEM_CACHE )
+ tmp_option_memory_cache_size -= 1;
+ else
+ tmp_option_memory_cache_size += 1;
+
+ if( tmp_option_memory_cache_size < 0 )
+ tmp_option_memory_cache_size = 1;
+ if( tmp_option_memory_cache_size > 999 )
+ tmp_option_memory_cache_size = 999;
+ snprintf( spare, 255, "%02d", tmp_option_memory_cache_size );
+ set_text( SETTINGS_STR_MAX_MEM_CACHE, spare, 5 );
+ is_button = true;
+ OBJ_REDRAW(SETTINGS_STR_MAX_MEM_CACHE);
+ break;
+
+ case SETTINGS_INC_DISC_CACHE:
+ case SETTINGS_DEC_DISC_CACHE:
+ if( index == SETTINGS_DEC_DISC_CACHE )
+ tmp_option_disc_cache_size -= 1;
+ else
+ tmp_option_disc_cache_size += 1;
+
+ if( tmp_option_disc_cache_size < 0 )
+ tmp_option_disc_cache_size = 1;
+ if( tmp_option_disc_cache_size > 9999 )
+ tmp_option_disc_cache_size = 9999;
+ snprintf( spare, 255, "%02d", tmp_option_disc_cache_size );
+ set_text( SETTINGS_STR_MAX_DISC_CACHE, spare, 5 );
+ is_button = true;
+ OBJ_REDRAW(SETTINGS_STR_MAX_DISC_CACHE);
+ break;
+
+ case SETTINGS_INC_CACHE_AGE:
+ case SETTINGS_DEC_CACHE_AGE:
+ if( index == SETTINGS_INC_CACHE_AGE )
+ tmp_option_disc_cache_age += 1;
+ else
+ tmp_option_disc_cache_age -= 1;
+
+ if( tmp_option_disc_cache_age > 99 )
+ tmp_option_disc_cache_age = 0;
+
+ snprintf( spare, 255, "%02d", tmp_option_disc_cache_age );
+ set_text( SETTINGS_EDIT_CACHE_AGE, spare, 2 );
+ is_button = true;
+ OBJ_REDRAW(SETTINGS_EDIT_CACHE_AGE);
+ break;
+
+ case SETTINGS_INC_CACHED_CONNECTIONS:
+ case SETTINGS_DEC_CACHED_CONNECTIONS:
+ if( index == SETTINGS_INC_CACHED_CONNECTIONS )
+ tmp_option_max_cached_fetch_handles += 1;
+ else
+ tmp_option_max_cached_fetch_handles -= 1;
+ if( tmp_option_max_cached_fetch_handles > 31 )
+ tmp_option_max_cached_fetch_handles = 31;
+
+ snprintf( spare, 255, "%02d", tmp_option_max_cached_fetch_handles );
+ set_text( SETTINGS_EDIT_MAX_CACHED_CONNECTIONS, spare, 2 );
+ is_button = true;
+ OBJ_REDRAW(SETTINGS_EDIT_MAX_CACHED_CONNECTIONS);
+ break;
+
+ case SETTINGS_INC_MAX_FETCHERS:
+ case SETTINGS_DEC_MAX_FETCHERS:
+ if( index == SETTINGS_INC_MAX_FETCHERS )
+ tmp_option_max_fetchers += 1;
+ else
+ tmp_option_max_fetchers -= 1;
+ if( tmp_option_max_fetchers > 31 )
+ tmp_option_max_fetchers = 31;
+
+ snprintf( spare, 255, "%02d", tmp_option_max_fetchers );
+ set_text( SETTINGS_EDIT_MAX_FETCHERS, spare, 2 );
+ is_button = true;
+ OBJ_REDRAW(SETTINGS_EDIT_MAX_FETCHERS);
+ break;
+
+ case SETTINGS_INC_MAX_FETCHERS_PER_HOST:
+ case SETTINGS_DEC_MAX_FETCHERS_PER_HOST:
+ if( index == SETTINGS_INC_MAX_FETCHERS_PER_HOST )
+ tmp_option_max_fetchers_per_host += 1;
+ else
+ tmp_option_max_fetchers_per_host -= 1;
+ if( tmp_option_max_fetchers_per_host > 31 )
+ tmp_option_max_fetchers_per_host = 31;
+
+ snprintf( spare, 255, "%02d", tmp_option_max_fetchers_per_host );
+ set_text( SETTINGS_EDIT_MAX_FETCHERS_PER_HOST, spare, 2 );
+ is_button = true;
+ OBJ_REDRAW(SETTINGS_EDIT_MAX_FETCHERS_PER_HOST);
+ break;
+
+ case SETTINGS_INC_HISTORY_AGE:
+ case SETTINGS_DEC_HISTORY_AGE:
+ if( index == SETTINGS_INC_HISTORY_AGE )
+ tmp_option_expire_url += 1;
+ else
+ tmp_option_expire_url -= 1;
+
+ if( tmp_option_expire_url > 99 )
+ tmp_option_expire_url = 0;
+
+ snprintf( spare, 255, "%02d", tmp_option_expire_url );
+ set_text( SETTINGS_EDIT_HISTORY_AGE, spare, 2 );
+ is_button = true;
+ OBJ_REDRAW(SETTINGS_EDIT_HISTORY_AGE);
+ break;
+
+ case SETTINGS_INC_GIF_DELAY:
+ case SETTINGS_DEC_GIF_DELAY:
+ if( index == SETTINGS_INC_GIF_DELAY )
+ tmp_option_minimum_gif_delay += 0.1;
+ else
+ tmp_option_minimum_gif_delay -= 0.1;
+
+ if( tmp_option_minimum_gif_delay < 0.1 )
+ tmp_option_minimum_gif_delay = 0.1;
+ if( tmp_option_minimum_gif_delay > 9.0 )
+ tmp_option_minimum_gif_delay = 9.0;
+ snprintf( spare, 255, "%01.1f", tmp_option_minimum_gif_delay );
+ set_text( SETTINGS_EDIT_MIN_GIF_DELAY, spare, 3 );
+ is_button = true;
+ OBJ_REDRAW(SETTINGS_EDIT_MIN_GIF_DELAY);
+ break;
+
+ case SETTINGS_INC_MIN_FONT_SIZE:
+ case SETTINGS_DEC_MIN_FONT_SIZE:
+ if( index == SETTINGS_INC_MIN_FONT_SIZE )
+ tmp_option_font_min_size += 1;
+ else
+ tmp_option_font_min_size -= 1;
+
+ if( tmp_option_font_min_size > 500 )
+ tmp_option_font_min_size = 500;
+ if( tmp_option_font_min_size < 10 )
+ tmp_option_font_min_size = 10;
+
+ snprintf( spare, 255, "%03d", tmp_option_font_min_size );
+ set_text( SETTINGS_EDIT_MIN_FONT_SIZE, spare, 3 );
+ is_button = true;
+ OBJ_REDRAW(SETTINGS_EDIT_MIN_FONT_SIZE);
+ break;
+
+ case SETTINGS_INC_DEF_FONT_SIZE:
+ case SETTINGS_DEC_DEF_FONT_SIZE:
+ if( index == SETTINGS_INC_DEF_FONT_SIZE )
+ tmp_option_font_size += 1;
+ else
+ tmp_option_font_size -= 1;
+
+ if( tmp_option_font_size > 999 )
+ tmp_option_font_size = 999;
+ if( tmp_option_font_size < 50 )
+ tmp_option_font_size = 50;
+
+ snprintf( spare, 255, "%03d", tmp_option_font_size );
+ set_text( SETTINGS_EDIT_DEF_FONT_SIZE, spare, 3 );
+ is_button = true;
+ OBJ_REDRAW(SETTINGS_EDIT_DEF_FONT_SIZE);
+ break;
+
+ case SETTINGS_INC_INCREMENTAL_REFLOW:
+ case SETTINGS_DEC_INCREMENTAL_REFLOW:
+ if( index == SETTINGS_INC_INCREMENTAL_REFLOW )
+ tmp_option_min_reflow_period += 1;
+ else
+ tmp_option_min_reflow_period -= 1;
+
+ if( tmp_option_min_reflow_period > 9999 )
+ tmp_option_min_reflow_period = 10;
+
+ snprintf( spare, 255, "%04d", tmp_option_min_reflow_period );
+ set_text( SETTINGS_EDIT_MIN_REFLOW_PERIOD, spare, 4 );
+ is_button = true;
+ OBJ_REDRAW(SETTINGS_EDIT_MIN_REFLOW_PERIOD);
+ break;
+
+ default:
+ break;
+ }
+
+ if( is_button ) {
+ // remove selection indicator from button element:
+ OBJ_UNCHECK(index);
+ OBJ_REDRAW(index);
+ }
+}
+
+
+static void apply_settings(void)
+{
+ /* "Network" tab: */
+ nsoption_set_bool(http_proxy, OBJ_SELECTED(SETTINGS_CB_USE_PROXY));
+ if ( OBJ_SELECTED(SETTINGS_CB_PROXY_AUTH) ) {
+ nsoption_set_int(http_proxy_auth, OPTION_HTTP_PROXY_AUTH_BASIC);
+ } else {
+ nsoption_set_int(http_proxy_auth, OPTION_HTTP_PROXY_AUTH_NONE);
+ }
+ nsoption_set_charp(http_proxy_auth_pass,
+ gemtk_obj_get_text(dlgtree, SETTINGS_EDIT_PROXY_PASSWORD));
+ nsoption_set_charp(http_proxy_auth_user,
+ gemtk_obj_get_text(dlgtree, SETTINGS_EDIT_PROXY_USERNAME));
+ nsoption_set_charp(http_proxy_host,
+ gemtk_obj_get_text(dlgtree, SETTINGS_EDIT_PROXY_HOST));
+ nsoption_set_int(http_proxy_port,
+ atoi( gemtk_obj_get_text(dlgtree, SETTINGS_EDIT_PROXY_PORT) ));
+ nsoption_set_int(max_fetchers_per_host,
+ atoi( gemtk_obj_get_text(dlgtree, SETTINGS_EDIT_MAX_FETCHERS_PER_HOST)));
+ nsoption_set_int(max_cached_fetch_handles,
+ atoi( gemtk_obj_get_text(dlgtree, SETTINGS_EDIT_MAX_CACHED_CONNECTIONS)));
+ nsoption_set_int(max_fetchers,
+ atoi( gemtk_obj_get_text(dlgtree, SETTINGS_EDIT_MAX_FETCHERS) ));
+ nsoption_set_bool(foreground_images,
+ OBJ_SELECTED( SETTINGS_CB_FG_IMAGES ));
+ nsoption_set_bool(background_images,
+ OBJ_SELECTED( SETTINGS_CB_BG_IMAGES ));
+
+ /* "Style" tab: */
+ nsoption_set_int(font_min_size, tmp_option_font_min_size);
+ nsoption_set_int(font_size, tmp_option_font_size);
+
+ /* "Rendering" tab: */
+ nsoption_set_charp(atari_font_driver,
+ gemtk_obj_get_text(dlgtree, SETTINGS_BT_SEL_FONT_RENDERER));
+ nsoption_set_int(atari_transparency,
+ OBJ_SELECTED(SETTINGS_CB_TRANSPARENCY));
+ nsoption_set_bool(animate_images,
+ OBJ_SELECTED(SETTINGS_CB_ENABLE_ANIMATION));
+ nsoption_set_int(minimum_gif_delay,
+ (int)(tmp_option_minimum_gif_delay*100+0.5));
+ /* nsoption_set_bool(incremental_reflow,
+ OBJ_SELECTED(SETTINGS_CB_INCREMENTAL_REFLOW));*/
+ nsoption_set_int(min_reflow_period, tmp_option_min_reflow_period);
+ nsoption_set_int(atari_font_monochrom,
+ !OBJ_SELECTED( SETTINGS_CB_ANTI_ALIASING ));
+
+ /* "Paths" tabs: */
+ nsoption_set_charp(ca_bundle,
+ gemtk_obj_get_text(dlgtree, SETTINGS_EDIT_CA_BUNDLE));
+ nsoption_set_charp(ca_path,
+ gemtk_obj_get_text(dlgtree, SETTINGS_EDIT_CA_CERTS_PATH));
+ nsoption_set_charp(homepage_url,
+ gemtk_obj_get_text(dlgtree, SETTINGS_EDIT_CA_CERTS_PATH));
+ nsoption_set_charp(hotlist_file,
+ gemtk_obj_get_text(dlgtree, SETTINGS_EDIT_HOTLIST_FILE));
+ nsoption_set_charp(atari_editor,
+ gemtk_obj_get_text(dlgtree, SETTINGS_EDIT_EDITOR));
+ nsoption_set_charp(downloads_path,
+ gemtk_obj_get_text(dlgtree, SETTINGS_EDIT_DOWNLOAD_PATH));
+
+ /* "Cache" tab: */
+ tmp_option_memory_cache_size = atoi(gemtk_obj_get_text(dlgtree,
+ SETTINGS_STR_MAX_MEM_CACHE));
+ tmp_option_expire_url = atoi(gemtk_obj_get_text(dlgtree,
+ SETTINGS_EDIT_HISTORY_AGE));
+ tmp_option_disc_cache_size = atoi(gemtk_obj_get_text(dlgtree,
+ SETTINGS_STR_MAX_DISC_CACHE));
+ tmp_option_disc_cache_age = atoi(gemtk_obj_get_text(dlgtree,
+ SETTINGS_EDIT_CACHE_AGE));
+ nsoption_set_int(memory_cache_size,
+ tmp_option_memory_cache_size * (1024*1024));
+
+ nsoption_set_int(expire_url, tmp_option_expire_url);
+
+ nsoption_set_int(disc_cache_size, tmp_option_disc_cache_size * (1024*1024));
+
+ nsoption_set_int(disc_cache_age, tmp_option_disc_cache_age);
+
+
+ /* "Browser" tab: */
+ nsoption_set_bool(target_blank,
+ !OBJ_SELECTED(SETTINGS_CB_DISABLE_POPUP_WINDOWS));
+ nsoption_set_bool(block_advertisements,
+ OBJ_SELECTED(SETTINGS_CB_HIDE_ADVERTISEMENT));
+ nsoption_set_charp(accept_language,
+ gemtk_obj_get_text(dlgtree, SETTINGS_BT_SEL_LOCALE));
+ nsoption_set_int(atari_gui_poll_timeout,
+ atoi(gemtk_obj_get_text(dlgtree, SETTINGS_BT_GUI_TOUT)));
+ nsoption_set_bool(send_referer,
+ OBJ_SELECTED(SETTINGS_CB_SEND_HTTP_REFERRER));
+ nsoption_set_bool(do_not_track,
+ OBJ_SELECTED(SETTINGS_CB_SEND_DO_NOT_TRACK));
+ nsoption_set_charp(homepage_url,
+ gemtk_obj_get_text(dlgtree, SETTINGS_EDIT_HOMEPAGE));
+}
+
+static short on_aes_event(GUIWIN *win, EVMULT_OUT *ev_out, short msg[8])
+{
+ short retval = 0;
+
+ if ((ev_out->emo_events & MU_MESAG) != 0) {
+ // handle message
+ // printf("settings win msg: %d\n", msg[0]);
+ switch (msg[0]) {
+
+
+ case WM_CLOSED:
+ // TODO: this needs to iterate through all gui windows and
+ // check if the rootwin is this window...
+ close_settings();
+ break;
+
+ case WM_SIZED:
+ gemtk_wm_update_slider(win, GEMTK_WM_VH_SLIDER);
+ break;
+
+ case WM_MOVED:
+ break;
+
+ case WM_TOOLBAR:
+ switch(msg[4]) {
+ case TOOLBAR_SETTINGS_SAVE:
+ save_settings();
+ break;
+
+ case TOOLBAR_SETTINGS_ABORT:
+ close_settings();
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case GEMTK_WM_WM_FORM_CLICK:
+ form_event(msg[4], 1);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if ((ev_out->emo_events & MU_KEYBD) != 0) {
+ }
+
+ if ((ev_out->emo_events & MU_BUTTON) != 0) {
+ }
+
+ return(retval);
+}
+
+void open_settings(void)
+{
+ if (h_aes_win == 0) {
+
+ GRECT curr, area;
+ OBJECT * toolbartree;
+ struct gemtk_wm_scroll_info_s *slid;
+ uint32_t kind = CLOSER | NAME | MOVER | VSLIDE | HSLIDE | UPARROW
+ | DNARROW | LFARROW | RTARROW | SIZER;
+
+ dlgtree = gemtk_obj_get_tree(SETTINGS);
+ toolbartree = gemtk_obj_get_tree(TOOLBAR_SETTINGS);
+ area.g_x = area.g_y = 0;
+ area.g_w = MIN(dlgtree->ob_width, desk_area.g_w);
+ area.g_h = MIN(dlgtree->ob_height, desk_area.g_h);
+ wind_calc_grect(WC_BORDER, kind, &area, &area);
+ h_aes_win = wind_create_grect(kind, &area);
+ wind_set_str(h_aes_win, WF_NAME, "Settings");
+ settings_guiwin = gemtk_wm_add(h_aes_win, GEMTK_WM_FLAG_DEFAULTS,
+ on_aes_event);
+ curr.g_w = MIN(dlgtree->ob_width, desk_area.g_w);
+ curr.g_h = MIN(dlgtree->ob_height, desk_area.g_h-64);
+ curr.g_x = 1;
+ curr.g_y = (desk_area.g_h / 2) - (curr.g_h / 2);
+
+ wind_calc_grect(WC_BORDER, kind, &curr, &curr);
+
+ dlgtree->ob_x = curr.g_x;
+ dlgtree->ob_y = curr.g_y;
+
+ /* set current config values: */
+ display_settings();
+
+ wind_open_grect(h_aes_win, &curr);
+
+ gemtk_wm_set_toolbar(settings_guiwin, toolbartree, 0, 0);
+ gemtk_wm_set_form(settings_guiwin, dlgtree, 0);
+ gemtk_wm_set_scroll_grid(settings_guiwin, 32, 32);
+ gemtk_wm_get_grect(settings_guiwin, GEMTK_WM_AREA_CONTENT, &area);
+
+ slid = gemtk_wm_get_scroll_info(settings_guiwin);
+ gemtk_wm_set_content_units(settings_guiwin,
+ (dlgtree->ob_width/slid->x_unit_px),
+ (dlgtree->ob_height/slid->y_unit_px));
+ gemtk_wm_update_slider(settings_guiwin, GEMTK_WM_VH_SLIDER);
+ }
+}
+
+void close_settings(void)
+{
+ LOG("closing");
+ gemtk_wm_remove(settings_guiwin);
+ settings_guiwin = NULL;
+ wind_close(h_aes_win);
+ wind_delete(h_aes_win);
+ h_aes_win = 0;
+ LOG("Done");
+}
+
diff --git a/frontends/atari/settings.h b/frontends/atari/settings.h
new file mode 100644
index 000000000..ac7bd8aa4
--- /dev/null
+++ b/frontends/atari/settings.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2013 Ole Loots <ole@monochrom.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 NS_ATARI_SETTINGS
+#define NS_ATARI_SETTINGS
+
+void open_settings(void);
+void close_settings(void);
+
+#endif
diff --git a/frontends/atari/statusbar.c b/frontends/atari/statusbar.c
new file mode 100644
index 000000000..c9d0f78aa
--- /dev/null
+++ b/frontends/atari/statusbar.c
@@ -0,0 +1,232 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <math.h>
+
+#include "utils/log.h"
+#include "desktop/mouse.h"
+#include "desktop/plotters.h"
+
+#include "atari/gui.h"
+#include "atari/statusbar.h"
+#include "atari/rootwin.h"
+#include "atari/misc.h"
+#include "atari/res/netsurf.rsh"
+#include "atari/plot/plot.h"
+#include "atari/osspec.h"
+
+#ifdef WITH_CUSTOM_STATUSBAR
+extern int atari_plot_vdi_handle;
+
+static
+void __CDECL evnt_sb_redraw( COMPONENT *c, long buff[8] )
+{
+ struct gui_window * gw = (struct gui_window *)mt_CompDataSearch(&app, c, CDT_OWNER);
+ assert(gw != NULL);
+ CMP_STATUSBAR sb = gw->root->statusbar;
+ assert( sb != NULL );
+ if( sb == NULL )
+ return;
+
+ if( sb->attached == false )
+ return;
+
+ LGRECT work, lclip;
+ short pxy[8], d, pxyclip[4];
+
+ mt_CompGetLGrect(&app, sb->comp, WF_WORKXYWH, &work);
+ lclip = work;
+ if ( !rc_lintersect( (LGRECT*)&buff[4], &lclip ) ) {
+ return;
+ }
+ vsf_interior(atari_plot_vdi_handle, FIS_SOLID );
+ vsl_color(atari_plot_vdi_handle, BLACK );
+ vsl_type(atari_plot_vdi_handle, 1);
+ vsl_width(atari_plot_vdi_handle, 1 );
+ vst_color(atari_plot_vdi_handle, BLACK);
+
+ vst_height(atari_plot_vdi_handle, atari_sysinfo.medium_sfont_pxh, &pxy[0], &pxy[1], &pxy[2], &pxy[3] );
+ vst_alignment(atari_plot_vdi_handle, 0, 5, &d, &d );
+ vst_effects(atari_plot_vdi_handle, 0 );
+ pxyclip[0] = lclip.g_x;
+ pxyclip[1] = lclip.g_y;
+ pxyclip[2] = lclip.g_x + lclip.g_w-1;
+ pxyclip[3] = lclip.g_y + lclip.g_h-1;
+
+ vs_clip(atari_plot_vdi_handle, 1, (short*)&pxyclip );
+ vswr_mode(atari_plot_vdi_handle, MD_REPLACE );
+
+ if( lclip.g_y <= work.g_y ) {
+ pxy[0] = work.g_x;
+ pxy[1] = work.g_y;
+ pxy[2] = MIN( work.g_x + work.g_w, lclip.g_x + lclip.g_w );
+ pxy[3] = work.g_y;
+ v_pline(atari_plot_vdi_handle, 2, (short*)&pxy );
+ }
+
+ if(app.nplanes > 2) {
+ vsf_color(atari_plot_vdi_handle, LWHITE);
+ } else {
+ vsf_color(atari_plot_vdi_handle, WHITE );
+ }
+
+ pxy[0] = work.g_x;
+ pxy[1] = work.g_y+1;
+ pxy[2] = work.g_x + work.g_w-1;
+ pxy[3] = work.g_y + work.g_h-1;
+ v_bar(atari_plot_vdi_handle, pxy );
+
+
+ if( sb->textlen > 0 ) {
+ size_t i;
+ short curx;
+ short vqw[4];
+ char t[2];
+ short cw = 8;
+ t[1]=0;
+ if( atari_sysinfo.sfont_monospaced ) {
+ t[0]='A';
+ int r = vqt_width(atari_plot_vdi_handle, t[0], &vqw[0], &vqw[1], &vqw[2] );
+ cw = vqw[0];
+ }
+ vswr_mode(atari_plot_vdi_handle, MD_TRANS );
+ for( curx = work.g_x + 2, i=0 ; (curx+cw < work.g_x+work.g_w ) && i < sb->textlen; i++ ){
+ t[0] = sb->text[i];
+ if( !atari_sysinfo.sfont_monospaced ) {
+ vqt_width(atari_plot_vdi_handle, t[0], &vqw[0], &vqw[1], &vqw[2] );
+ cw = vqw[0];
+ }
+ if( curx >= lclip.g_x - cw ) {
+ v_gtext(atari_plot_vdi_handle, curx, work.g_y + 5, (char*)&t );
+ }
+ curx += cw;
+ if( curx >= lclip.g_x + lclip.g_w )
+ break;
+ }
+ }
+ vswr_mode(atari_plot_vdi_handle, MD_REPLACE );
+ pxy[0] = work.g_x + work.g_w;
+ pxy[1] = work.g_y + work.g_h;
+ pxy[2] = work.g_x + work.g_w;
+ pxy[3] = work.g_y + work.g_h-work.g_h;
+ v_pline(atari_plot_vdi_handle, 2, (short*)&pxy );
+
+ vs_clip(atari_plot_vdi_handle, 0, (short*)&pxyclip );
+ return;
+}
+
+static void __CDECL evnt_sb_click( COMPONENT *c, long buff[8] )
+{
+ static bool prevstate;
+ LGRECT work;
+ mt_CompGetLGrect(&app, c, WF_WORKXYWH, &work);
+ if( evnt.mx >= work.g_x + (work.g_w) && evnt.mx <= work.g_x + work.g_w &&
+ evnt.my >= work.g_y + (work.g_h) && evnt.my <= work.g_y + work.g_h ) {
+ // click within sb button
+ }
+}
+
+CMP_STATUSBAR sb_create( struct gui_window * gw )
+{
+ CMP_STATUSBAR s = malloc( sizeof(struct s_statusbar) );
+ s->attached = false;
+ s->comp = (COMPONENT*)mt_CompCreate(&app, CLT_HORIZONTAL, STATUSBAR_HEIGHT, 0);
+ s->comp->rect.g_h = STATUSBAR_HEIGHT;
+ s->comp->bounds.max_height = STATUSBAR_HEIGHT;
+ mt_CompDataAttach( &app, s->comp, CDT_OWNER, gw );
+ mt_CompEvntAttach( &app, s->comp, WM_REDRAW, evnt_sb_redraw );
+ mt_CompEvntAttach( &app, s->comp, WM_XBUTTON, evnt_sb_click );
+ sb_set_text( s, (char*)"" );
+ return( s );
+}
+
+void sb_destroy( CMP_STATUSBAR s )
+{
+ LOG("%s\n", __FUNCTION__);
+ if( s ) {
+ if( s->comp ){
+ mt_CompDelete( &app, s->comp );
+ }
+ free( s );
+ }
+}
+
+void sb_set_text(CMP_STATUSBAR sb , const char * text)
+{
+
+ LGRECT work;
+ assert( sb != NULL );
+ assert( sb->comp != NULL );
+ strncpy( (char*)&sb->text, text, STATUSBAR_MAX_SLEN );
+ sb->text[STATUSBAR_MAX_SLEN]=0;
+ sb->textlen = strlen( (char*)&sb->text );
+ if( sb->attached ){
+ struct gui_window * gw = (struct gui_window *)mt_CompDataSearch(&app, sb->comp, CDT_OWNER);
+ if( gw != NULL ){
+ mt_CompGetLGrect(&app, sb->comp, WF_WORKXYWH, &work);
+ ApplWrite( _AESapid, WM_REDRAW, gw->root->handle->handle,
+ work.g_x, work.g_y, work.g_w, work.g_h );
+ }
+ }
+}
+
+#else
+
+CMP_STATUSBAR sb_create( struct gui_window * gw )
+{
+ CMP_STATUSBAR s = malloc( sizeof(struct s_statusbar) );
+ s->attached = false;
+ sb_set_text( s, (char*)"" );
+ return( s );
+}
+
+void sb_destroy( CMP_STATUSBAR s )
+{
+ LOG("%s\n", __FUNCTION__);
+ if( s ) {
+ free( s );
+ }
+}
+
+void sb_attach(CMP_STATUSBAR sb, struct gui_window * gw)
+{
+ sb->aes_win = gemtk_wm_get_handle(gw->root->win);
+ sb->attached = true;
+}
+
+void sb_set_text(CMP_STATUSBAR sb, const char * text )
+{
+ assert( sb != NULL );
+ strncpy(sb->text, text, STATUSBAR_MAX_SLEN);
+ sb->text[STATUSBAR_MAX_SLEN]=0;
+ sb->textlen = strlen(sb->text);
+ if(sb->attached){
+ wind_set_str(sb->aes_win, WF_INFO, sb->text);
+ }
+}
+
+#endif
diff --git a/frontends/atari/statusbar.h b/frontends/atari/statusbar.h
new file mode 100644
index 000000000..8ac090497
--- /dev/null
+++ b/frontends/atari/statusbar.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.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 NS_ATARI_STATUSBAR
+#define NS_ATARI_STATUSBAR
+
+#define STATUSBAR_HEIGHT 16
+#define STATUSBAR_MAX_SLEN 255
+
+struct s_statusbar {
+#ifdef WITH_COMPONENT_STATUSBAR
+ COMPONENT * comp;
+#endif
+ char text[STATUSBAR_MAX_SLEN+1];
+ size_t textlen;
+ bool attached;
+ short aes_win;
+};
+
+CMP_STATUSBAR sb_create( struct gui_window * gw );
+void sb_destroy( CMP_STATUSBAR s );
+void sb_set_text( CMP_STATUSBAR sb , const char * text );
+void sb_attach(CMP_STATUSBAR sb, struct gui_window * gw);
+
+#endif
diff --git a/frontends/atari/toolbar.c b/frontends/atari/toolbar.c
new file mode 100644
index 000000000..f630332da
--- /dev/null
+++ b/frontends/atari/toolbar.c
@@ -0,0 +1,1041 @@
+/*
+ * Copyright 2012 Ole Loots <ole@monochrom.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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <math.h>
+
+#include "utils/log.h"
+#include "utils/nsoption.h"
+#include "utils/nsurl.h"
+#include "utils/utf8.h"
+#include "desktop/browser_history.h"
+#include "desktop/browser.h"
+#include "desktop/mouse.h"
+#include "desktop/plot_style.h"
+#include "desktop/plotters.h"
+#include "desktop/tree.h"
+#include "desktop/hotlist.h"
+#include "desktop/textarea.h"
+#include "desktop/textinput.h"
+#include "content/hlcache.h"
+
+#include "atari/clipboard.h"
+#include "atari/gui.h"
+#include "atari/search.h"
+#include "atari/toolbar.h"
+#include "atari/rootwin.h"
+#include "atari/clipboard.h"
+#include "atari/misc.h"
+#include "atari/plot/plot.h"
+#include "cflib.h"
+#include "atari/res/netsurf.rsh"
+#include "atari/encoding.h"
+
+
+#define TB_BUTTON_WIDTH 32
+#define THROBBER_WIDTH 32
+#define THROBBER_MIN_INDEX 1
+#define THROBBER_MAX_INDEX 12
+#define THROBBER_INACTIVE_INDEX 13
+
+enum e_toolbar_button_states {
+ button_on = 0,
+ button_off = 1
+};
+#define TOOLBAR_BUTTON_NUM_STATES 2
+
+struct s_toolbar;
+
+struct s_tb_button {
+ short rsc_id;
+ void (*cb_click)(struct s_toolbar *tb);
+ hlcache_handle *icon[TOOLBAR_BUTTON_NUM_STATES];
+ struct s_toolbar *owner;
+ enum e_toolbar_button_states state;
+ short index;
+ GRECT area;
+};
+
+
+extern char * option_homepage_url;
+extern void * h_gem_rsrc;
+extern struct gui_window * input_window;
+extern long atari_plot_flags;
+extern int atari_plot_vdi_handle;
+extern EVMULT_OUT aes_event_out;
+
+static OBJECT * aes_toolbar = NULL;
+static OBJECT * throbber_form = NULL;
+static bool init = false;
+static int area_navigation_height = 0;
+static int area_search_height = 0;
+static int area_full_height = 0;
+static float toolbar_url_scale = 1.0;
+
+static plot_font_style_t font_style_url = {
+ .family = PLOT_FONT_FAMILY_SANS_SERIF,
+ .size = 14*FONT_SIZE_SCALE,
+ .weight = 400,
+ .flags = FONTF_NONE,
+ .background = 0xffffff,
+ .foreground = 0x0
+};
+
+
+/* prototypes & order for button widgets: */
+
+static struct s_tb_button tb_buttons[] = {
+ {
+ TOOLBAR_BT_BACK,
+ toolbar_back_click,
+ {0,0},
+ 0, 0, 0, {0,0,0,0}
+ },
+ {
+ TOOLBAR_BT_HOME,
+ toolbar_home_click,
+ {0,0},
+ 0, 0, 0, {0,0,0,0}
+ },
+ {
+ TOOLBAR_BT_FORWARD,
+ toolbar_forward_click,
+ {0,0},
+ 0, 0, 0, {0,0,0,0}
+ },
+ {
+ TOOLBAR_BT_STOP,
+ toolbar_stop_click,
+ {0,0},
+ 0, 0, 0, {0,0,0,0}
+ },
+ {
+ TOOLBAR_BT_RELOAD,
+ toolbar_reload_click,
+ {0,0},
+ 0, 0, 0, {0,0,0,0}
+ },
+ { 0, 0, {0,0}, 0, -1, 0, {0,0,0,0}}
+};
+
+struct s_toolbar_style {
+ int font_height_pt;
+};
+
+static struct s_toolbar_style toolbar_styles[] = {
+ /* small (18 px height) */
+ {9},
+ /* medium (default - 26 px height) */
+ {14},
+ /* large ( 49 px height ) */
+ {18},
+ /* custom style: */
+ {18}
+};
+
+static const struct redraw_context toolbar_rdrw_ctx = {
+ .interactive = true,
+ .background_images = true,
+ .plot = &atari_plotters
+};
+
+static void tb_txt_request_redraw(void *data, int x, int y, int w, int h );
+
+/**
+ * Find a button for a specific resource ID
+ */
+static struct s_tb_button *find_button(struct s_toolbar *tb, int rsc_id)
+{
+ int i = 0;
+ while (i < tb->btcnt) {
+ if (tb->buttons[i].rsc_id == rsc_id) {
+ return(&tb->buttons[i]);
+ }
+ i++;
+ }
+ return(NULL);
+}
+
+/**
+ * Callback for textarea redraw
+ */
+static void tb_txt_request_redraw(void *data, int x, int y, int w, int h)
+{
+
+ GRECT area;
+ struct s_toolbar * tb = (struct s_toolbar *)data;
+
+ if (tb->attached == false) {
+ return;
+ }
+
+ toolbar_get_grect(tb, TOOLBAR_AREA_URL, &area);
+ area.g_x += x;
+ area.g_y += y;
+ area.g_w = w;
+ area.g_h = h;
+ /* dbg_grect("tb_txt_request_redraw", &area); */
+ window_schedule_redraw_grect(tb->owner, &area);
+ return;
+}
+
+static void tb_txt_callback(void *data, struct textarea_msg *msg)
+{
+ switch (msg->type) {
+
+ case TEXTAREA_MSG_DRAG_REPORT:
+ break;
+
+ case TEXTAREA_MSG_REDRAW_REQUEST:
+ tb_txt_request_redraw(data,
+ msg->data.redraw.x0, msg->data.redraw.y0,
+ msg->data.redraw.x1 - msg->data.redraw.x0,
+ msg->data.redraw.y1 - msg->data.redraw.y0);
+ break;
+
+ default:
+ break;
+ }
+}
+
+static struct s_tb_button *button_init(struct s_toolbar *tb, OBJECT * tree, int index,
+ struct s_tb_button * instance)
+{
+ *instance = tb_buttons[index];
+ instance->owner = tb;
+
+ return(instance);
+}
+
+
+static short __CDECL toolbar_url_userdraw(PARMBLK *parmblock)
+{
+ return(0);
+}
+
+void toolbar_init( void )
+{
+ static USERBLK userblk;
+
+ aes_toolbar = gemtk_obj_get_tree(TOOLBAR);
+ throbber_form = gemtk_obj_get_tree(THROBBER);
+
+ userblk.ub_code = toolbar_url_userdraw;
+ userblk.ub_parm = (long) aes_toolbar[TOOLBAR_AREA_URL].ob_spec.userblk;
+ aes_toolbar[TOOLBAR_AREA_URL].ob_spec.userblk = &userblk;
+
+ aes_toolbar[TOOLBAR_CB_SHOWALL].ob_state &= ~OS_SELECTED;
+ aes_toolbar[TOOLBAR_CB_CASESENSE].ob_state &= ~OS_SELECTED;
+
+ /* init default values: */
+ gemtk_obj_set_str_safe(aes_toolbar, TOOLBAR_TB_SRCH, (char*)"");
+
+ area_full_height = aes_toolbar->ob_height;
+ area_search_height = aes_toolbar[TOOLBAR_AREA_SEARCH].ob_height;
+ area_navigation_height = aes_toolbar[TOOLBAR_AREA_NAVIGATION].ob_height;
+
+ init = true;
+}
+
+
+void toolbar_exit(void)
+{
+
+}
+
+
+struct s_toolbar *toolbar_create(struct s_gui_win_root *owner)
+{
+ int i;
+ struct s_toolbar *t;
+
+ LOG("owner %p", owner);
+
+ assert(init == true);
+
+ t = calloc(1, sizeof(struct s_toolbar));
+
+ assert(t);
+
+ /* initialize the toolbar values: */
+ t->owner = owner;
+ t->style = 1;
+ t->search_visible = false;
+ t->visible = true;
+ t->reflow = true;
+
+ /* dublicate the form template: */
+ t->form = gemtk_obj_tree_copy(aes_toolbar);
+
+
+ /* count buttons and add them as components: */
+ i = 0;
+ while(tb_buttons[i].rsc_id > 0) {
+ i++;
+ }
+ t->btcnt = i;
+ t->buttons = malloc(t->btcnt * sizeof(struct s_tb_button));
+ memset(t->buttons, 0, t->btcnt * sizeof(struct s_tb_button));
+ for (i=0; i < t->btcnt; i++) {
+ button_init(t, aes_toolbar, i, &t->buttons[i]);
+ }
+
+ /* create the url widget: */
+ font_style_url.size =
+ toolbar_styles[t->style].font_height_pt * FONT_SIZE_SCALE;
+
+ textarea_flags ta_flags = TEXTAREA_INTERNAL_CARET;
+ textarea_setup ta_setup;
+ ta_setup.width = 300;
+ ta_setup.height = t->form[TOOLBAR_AREA_URL].ob_height;
+ ta_setup.pad_top = 0;
+ ta_setup.pad_right = 4;
+ ta_setup.pad_bottom = 0;
+ ta_setup.pad_left = 4;
+ ta_setup.border_width = 1;
+ ta_setup.border_col = 0x000000;
+ ta_setup.selected_text = 0xffffff;
+ ta_setup.selected_bg = 0x000000;
+ ta_setup.text = font_style_url;
+ ta_setup.text.foreground = 0x000000;
+ ta_setup.text.background = 0xffffff;
+ t->url.textarea = textarea_create(ta_flags, &ta_setup,
+ tb_txt_callback, t);
+
+ /* create the throbber widget: */
+ t->throbber.index = THROBBER_INACTIVE_INDEX;
+ t->throbber.max_index = THROBBER_MAX_INDEX;
+ t->throbber.running = false;
+
+ LOG("created toolbar: %p, root: %p, textarea: %p, throbber: %p",
+ t, owner, t->url.textarea, &t->throbber);
+ return( t );
+}
+
+
+void toolbar_destroy(struct s_toolbar *tb)
+{
+ free(tb->buttons);
+ free(tb->form);
+
+ textarea_destroy(tb->url.textarea);
+
+ free(tb);
+}
+
+static int toolbar_calculate_height(struct s_toolbar *tb)
+{
+ int r = 0;
+
+ if (tb->visible == false) {
+ return(0);
+ }
+
+ r += area_navigation_height;
+
+ if (tb->search_visible) {
+ r += area_search_height;
+ }
+
+ return(r);
+}
+
+static void toolbar_reflow(struct s_toolbar *tb)
+{
+ int i;
+ short offx, offy;
+
+ // position toolbar areas:
+ tb->form->ob_x = tb->area.g_x;
+ tb->form->ob_y = tb->area.g_y;
+ tb->form->ob_width = tb->area.g_w;
+ tb->form->ob_height = toolbar_calculate_height(tb);
+
+ // expand the "main" areas to the current width:
+ tb->form[TOOLBAR_AREA_NAVIGATION].ob_width = tb->area.g_w;
+ tb->form[TOOLBAR_AREA_SEARCH].ob_width = tb->area.g_w;
+
+ if (tb->search_visible) {
+ tb->form[TOOLBAR_AREA_SEARCH].ob_state &= ~OF_HIDETREE;
+ } else {
+ tb->form[TOOLBAR_AREA_SEARCH].ob_state |= OF_HIDETREE;
+
+ }
+
+ // align TOOLBAR_AREA_RIGHT IBOX at right edge:
+ tb->form[TOOLBAR_AREA_RIGHT].ob_x = tb->area.g_w
+ - tb->form[TOOLBAR_AREA_RIGHT].ob_width;
+
+ // center the URL area:
+ tb->form[TOOLBAR_AREA_URL].ob_width = tb->area.g_w
+ - (tb->form[TOOLBAR_AREA_LEFT].ob_width
+ + tb->form[TOOLBAR_AREA_RIGHT].ob_width);
+
+ // position throbber image above IBOX:
+ objc_offset(tb->form, TOOLBAR_THROBBER_AREA, &offx, &offy);
+ throbber_form[tb->throbber.index].ob_x = offx;
+ throbber_form[tb->throbber.index].ob_y = offy;
+
+ // align the search button:
+ tb->form[TOOLBAR_SEARCH_ALIGN_RIGHT].ob_x = tb->area.g_w
+ - tb->form[TOOLBAR_SEARCH_ALIGN_RIGHT].ob_width;
+
+ // set button states:
+ for (i=0; i < tb->btcnt; i++ ) {
+ if (tb->buttons[i].state == button_off) {
+ tb->form[tb->buttons[i].rsc_id].ob_state |= OS_DISABLED;
+ } else if (tb->buttons[i].state == button_on) {
+ tb->form[tb->buttons[i].rsc_id].ob_state &= ~OS_DISABLED;
+ }
+ }
+ tb->reflow = false;
+ // TODO: iterate through all other toolbars and set reflow = true
+}
+
+void toolbar_redraw(struct s_toolbar *tb, GRECT *clip)
+{
+ GRECT area, area_ro;
+
+ if (tb->attached == false) {
+ return;
+ }
+
+ if(tb->reflow == true)
+ toolbar_reflow(tb);
+
+ //dbg_grect("toolbar redraw clip", clip);
+
+ /* Redraw the AES objects: */
+ objc_draw_grect(tb->form,0,8,clip);
+ objc_draw_grect(&throbber_form[tb->throbber.index], 0, 1, clip);
+
+ toolbar_get_grect(tb, TOOLBAR_AREA_URL, &area_ro);
+ area = area_ro;
+
+ if (rc_intersect(clip, &area)) {
+ float old_scale;
+
+ plot_set_dimensions(area_ro.g_x, area_ro.g_y, area_ro.g_w, area_ro.g_h);
+ struct rect r = {
+ .x0 = MAX(0,area.g_x - area_ro.g_x),
+ .y0 = MAX(0,area.g_y - area_ro.g_y),
+ .x1 = MAX(0,area.g_x - area_ro.g_x) + area.g_w,
+ .y1 = MAX(0,area.g_y - area_ro.g_y) + area.g_h
+ };
+ //dbg_rect("tb textarea clip: ", &r);
+ // TODO: let this be handled by an userdef object redraw function:
+ /* Redraw the url input: */
+ old_scale = plot_set_scale(toolbar_url_scale);
+ textarea_redraw(tb->url.textarea, 0, 0, 0xffffff, 1.0, &r,
+ &toolbar_rdrw_ctx);
+ plot_set_scale(old_scale);
+ }
+}
+
+
+void
+toolbar_update_buttons(struct s_toolbar *tb,
+ struct browser_window *bw,
+ short button)
+{
+ LOG("tb %p", tb);
+
+ struct s_tb_button * bt;
+ bool enable = false;
+ GRECT area;
+
+ assert(bw != NULL);
+
+ if (button == TOOLBAR_BT_BACK || button <= 0 ) {
+ bt = find_button(tb, TOOLBAR_BT_BACK);
+ enable = browser_window_back_available(bw);
+ if (enable) {
+ bt->state = button_on;
+ } else {
+ bt->state = button_off;
+ }
+ }
+
+ if (button == TOOLBAR_BT_HOME || button <= 0 ) {
+
+ }
+
+ if (button == TOOLBAR_BT_FORWARD || button <= 0 ) {
+ bt = find_button(tb, TOOLBAR_BT_FORWARD);
+ enable = browser_window_forward_available(bw);
+ if (enable) {
+ bt->state = button_on;
+ } else {
+ bt->state = button_off;
+ }
+ }
+
+ if (button == TOOLBAR_BT_RELOAD || button <= 0 ) {
+ bt = find_button(tb, TOOLBAR_BT_RELOAD);
+ enable = browser_window_reload_available(bw);
+ if (enable) {
+ bt->state = button_on;
+ } else {
+ bt->state = button_off;
+ }
+ }
+
+ if (button == TOOLBAR_BT_STOP || button <= 0) {
+ bt = find_button(tb, TOOLBAR_BT_STOP);
+ enable = browser_window_stop_available(bw);
+ if (enable) {
+ bt->state = button_on;
+ } else {
+ bt->state = button_off;
+ }
+ }
+
+ if (tb->attached) {
+ if (button > 0) {
+ toolbar_get_grect(tb, button, &area);
+ window_schedule_redraw_grect(tb->owner, &area);
+ } else {
+ toolbar_get_grect(tb, TOOLBAR_AREA_LEFT, &area);
+ window_schedule_redraw_grect(tb->owner, &area);
+
+ toolbar_get_grect(tb, TOOLBAR_AREA_RIGHT, &area);
+ window_schedule_redraw_grect(tb->owner, &area);
+ }
+ }
+}
+
+void toolbar_set_width(struct s_toolbar *tb, short w)
+{
+ GRECT cur;
+
+ toolbar_get_grect(tb, 0, &cur);
+
+ if (w != cur.g_w) {
+
+ tb->area.g_w = w;
+
+ /* reflow now, just for url input calucation: */
+ toolbar_reflow(tb);
+ /* this will request an textarea redraw: */
+ textarea_set_dimensions(tb->url.textarea,
+ tb->form[TOOLBAR_AREA_URL].ob_width,
+ tb->form[TOOLBAR_AREA_URL].ob_height);
+ tb->reflow = true;
+ }
+}
+
+void toolbar_set_origin(struct s_toolbar *tb, short x, short y)
+{
+ GRECT cur;
+
+ toolbar_get_grect(tb, 0, &cur);
+
+ if (x != cur.g_x || y != cur.g_y) {
+ tb->area.g_x = x;
+ tb->area.g_y = y;
+ tb->reflow = true;
+ }
+}
+
+void toolbar_set_dimensions(struct s_toolbar *tb, GRECT *area)
+{
+ if (area->g_w != tb->area.g_w) {
+
+ tb->area = *area;
+
+ /* reflow now, just for url input calucation: */
+ toolbar_reflow(tb);
+ /* this will request an textarea redraw: */
+ textarea_set_dimensions(tb->url.textarea,
+ tb->form[TOOLBAR_AREA_URL].ob_width,
+ tb->form[TOOLBAR_AREA_URL].ob_height-1);
+ }
+ else {
+ tb->area = *area;
+ }
+ /* reflow for next redraw: */
+ /* TODO: that's only required because we do not reset others toolbars reflow
+ state on reflow */
+ tb->reflow = true;
+}
+
+
+void toolbar_set_url(struct s_toolbar *tb, const char *text)
+{
+ LOG("tb %p", tb);
+
+ textarea_set_text(tb->url.textarea, text);
+
+ if (tb->attached && tb->visible) {
+ GRECT area;
+ toolbar_get_grect(tb, TOOLBAR_AREA_URL, &area);
+ window_schedule_redraw_grect(tb->owner, &area);
+ struct gui_window * gw = window_get_active_gui_window(tb->owner);
+ assert(gw != NULL);
+ toolbar_update_buttons(tb, gw->browser->bw , 0);
+ }
+}
+
+void toolbar_set_throbber_state(struct s_toolbar *tb, bool active)
+{
+ GRECT throbber_area;
+
+ tb->throbber.running = active;
+ if (active) {
+ tb->throbber.index = THROBBER_MIN_INDEX;
+ } else {
+ tb->throbber.index = THROBBER_INACTIVE_INDEX;
+ }
+
+ tb->reflow = true;
+ toolbar_get_grect(tb, TOOLBAR_THROBBER_AREA, &throbber_area);
+ window_schedule_redraw_grect(tb->owner, &throbber_area);
+}
+
+void toolbar_set_visible(struct s_toolbar *tb, short area, bool visible)
+{
+ if (area == 0) {
+ if ((visible == false) && (tb->visible == true)) {
+ tb->visible = false;
+ tb->reflow = true;
+ } else if((visible == true) && (tb->visible == false)) {
+ tb->visible = false;
+ tb->reflow = true;
+ }
+ } else if (area == TOOLBAR_AREA_SEARCH) {
+ tb->search_visible = visible;
+ tb->reflow = true;
+ OBJECT *frm = toolbar_get_form(tb);
+ if(visible == false){
+ frm[TOOLBAR_AREA_SEARCH].ob_flags |= OF_HIDETREE;
+ } else {
+ frm[TOOLBAR_AREA_SEARCH].ob_flags &= ~OF_HIDETREE;
+ }
+ }
+}
+
+void toolbar_set_reflow(struct s_toolbar *tb, bool do_reflow)
+{
+ tb->reflow = do_reflow;
+}
+
+void toolbar_set_attached(struct s_toolbar *tb, bool attached)
+{
+ tb->attached = attached;
+
+}
+
+void toolbar_throbber_progress(struct s_toolbar *tb)
+{
+ GRECT throbber_area;
+
+ assert(tb->throbber.running == true);
+
+ if(tb->throbber.running == false)
+ return;
+
+ tb->throbber.index++;
+ if (tb->throbber.index > THROBBER_MAX_INDEX) {
+ tb->throbber.index = THROBBER_MIN_INDEX;
+ }
+
+ tb->reflow = true;
+ toolbar_get_grect(tb, TOOLBAR_THROBBER_AREA, &throbber_area);
+ window_schedule_redraw_grect(tb->owner, &throbber_area);
+}
+
+bool toolbar_text_input(struct s_toolbar *tb, char *text)
+{
+ bool handled = true;
+
+ LOG("tb %p", tb);
+
+ return(handled);
+}
+
+bool toolbar_key_input(struct s_toolbar *tb, short nkc)
+{
+
+ assert(tb!=NULL);
+ bool ret = false;
+ struct gui_window *gw = window_get_active_gui_window(tb->owner);
+
+ assert( gw != NULL );
+
+ long ucs4;
+ long ik = nkc_to_input_key(nkc, &ucs4);
+
+ if (ik == 0) {
+ if ((nkc&0xFF) >= 9) {
+ ret = textarea_keypress(tb->url.textarea, ucs4);
+ }
+
+ } else if (ik == NS_KEY_CR || ik == NS_KEY_NL) {
+ nsurl *url;
+ char tmp_url[PATH_MAX];
+ if ( textarea_get_text( tb->url.textarea, tmp_url, PATH_MAX) > 0 ) {
+ window_set_focus(tb->owner, BROWSER, gw->browser);
+ if (nsurl_create((const char*)&tmp_url, &url) != NSERROR_OK) {
+ atari_warn_user("NoMemory", 0);
+ } else {
+ browser_window_navigate(gw->browser->bw, url, NULL,
+ BW_NAVIGATE_HISTORY,
+ NULL, NULL, NULL);
+ nsurl_unref(url);
+ }
+
+ ret = true;
+ }
+
+ } else if (ik == NS_KEY_COPY_SELECTION) {
+ // copy whole text
+ char * text;
+ int len;
+ len = textarea_get_text( tb->url.textarea, NULL, 0 );
+ text = malloc( len+1 );
+ if (text){
+ textarea_get_text( tb->url.textarea, text, len+1 );
+ scrap_txt_write(text);
+ free( text );
+ }
+
+ } else if ( ik == NS_KEY_PASTE) {
+ char * clip = scrap_txt_read();
+ if ( clip != NULL ){
+ int clip_length = strlen( clip );
+ if ( clip_length > 0 ) {
+ char *utf8;
+ nserror res;
+ /* Clipboard is in local encoding so
+ * convert to UTF8 */
+ res = utf8_from_local_encoding( clip, clip_length, &utf8 );
+ if ( res == NSERROR_OK ) {
+ toolbar_set_url(tb, utf8);
+ free(utf8);
+ ret = true;
+ }
+ }
+ free( clip );
+ }
+
+ } else if (ik == NS_KEY_ESCAPE) {
+ textarea_keypress( tb->url.textarea, NS_KEY_SELECT_ALL );
+ textarea_keypress( tb->url.textarea, NS_KEY_DELETE_LEFT );
+
+ } else {
+ ret = textarea_keypress( tb->url.textarea, ik );
+
+ }
+
+ return( ret );
+}
+
+
+void toolbar_mouse_input(struct s_toolbar *tb, short obj, short button)
+{
+ GRECT work;
+ short mx, my, mb, kstat;
+ struct gui_window * gw;
+
+ LOG("tb %p", tb);
+
+
+ if (obj==TOOLBAR_AREA_URL) {
+ graf_mkstate(&mx, &my, &mb, &kstat);
+ toolbar_get_grect(tb, TOOLBAR_AREA_URL, &work);
+ mx -= work.g_x;
+ my -= work.g_y;
+
+ /* TODO: reset mouse state of browser window? */
+ /* select whole text when newly focused, otherwise set caret to
+ end of text */
+ if (!window_url_widget_has_focus(tb->owner)) {
+ window_set_focus(tb->owner, URL_WIDGET, (void*)&tb->url);
+
+ } else if (mb & 1) {
+ /* url widget has focus and mouse button is still pressed... */
+
+ textarea_mouse_action(tb->url.textarea, BROWSER_MOUSE_DRAG_1,
+ mx, my );
+ short prev_x = mx;
+ short prev_y = my;
+ do {
+ if (abs(prev_x-mx) > 5 || abs(prev_y-my) > 5) {
+ textarea_mouse_action( tb->url.textarea,
+ BROWSER_MOUSE_HOLDING_1, mx, my );
+ prev_x = mx;
+ prev_y = my;
+ window_schedule_redraw_grect(tb->owner, &work);
+ window_process_redraws(tb->owner);
+ }
+ graf_mkstate( &mx, &my, &mb, &kstat );
+ mx = mx - (work.g_x);
+ my = my - (work.g_y);
+ } while (mb & 1);
+
+ textarea_mouse_action( tb->url.textarea, BROWSER_MOUSE_HOVER, mx,
+ my);
+
+ } else if (button & 2) {
+ // TODO: open a context popup
+
+ } else {
+ /* when execution reaches here, mouse input is a click or dclick */
+ /* TODO: recognize click + shitoolbar_update_buttonsft key */
+ if (aes_event_out.emo_mclicks == 2 ) {
+ textarea_mouse_action( tb->url.textarea,
+ BROWSER_MOUSE_DOUBLE_CLICK | BROWSER_MOUSE_CLICK_1, mx,
+ my);
+ toolbar_get_grect(tb, TOOLBAR_AREA_URL, &work);
+ window_schedule_redraw_grect(tb->owner, &work);
+ } else {
+ textarea_mouse_action(tb->url.textarea,
+ BROWSER_MOUSE_PRESS_1, mx, my );
+ }
+ }
+
+ } else if(obj==TOOLBAR_TB_SRCH) {
+ window_set_focus(tb->owner, SEARCH_INPUT, NULL);
+
+ } else if (obj==TOOLBAR_BT_SEARCH_FWD) {
+ gw = tb->owner->active_gui_window;
+ assert(gw->search);
+ nsatari_search_perform(gw->search, tb->form, SEARCH_FLAG_FORWARDS);
+
+ } else if (obj==TOOLBAR_BT_SEARCH_BACK) {
+ gw = tb->owner->active_gui_window;
+ assert(gw->search);
+ nsatari_search_perform(gw->search, tb->form, 0);
+
+ } else if (obj==TOOLBAR_BT_CLOSE_SEARCH) {
+ tb->form[TOOLBAR_BT_CLOSE_SEARCH].ob_state &= ~OS_SELECTED;
+ window_close_search(tb->owner);
+ } else {
+ struct s_tb_button *bt = find_button(tb, obj);
+ if (bt != NULL && bt->state != button_off) {
+ bt->cb_click(tb);
+ struct gui_window * gw = window_get_active_gui_window(tb->owner);
+ toolbar_update_buttons(tb, gw->browser->bw, 0);
+ }
+ }
+}
+
+
+/**
+ * Receive a specific region of the toolbar.
+ * @param tb - the toolbar pointer
+ * @param which - the area to retrieve: 0 to receive the workarea,
+ all other values must be
+ an resource ID of the TOOLBAR tree.
+ * @param dst - GRECT pointer receiving the area.
+ */
+
+void toolbar_get_grect(struct s_toolbar *tb, short which, GRECT *dst)
+{
+#define LAST_TOOLBAR_AREA TOOLBAR_AREA_SEARCH
+
+ if (tb->reflow == true) {
+ toolbar_reflow(tb);
+ }
+
+ objc_offset(tb->form, which, &dst->g_x, &dst->g_y);
+
+ dst->g_w = tb->form[which].ob_width;
+ dst->g_h = tb->form[which].ob_height;
+ //tb->form[which].ob_height;
+
+ //printf("Toolbar get grect (%d): ", which);
+ //dbg_grect("", dst);
+
+#undef LAST_TOOLBAR_AREA
+}
+
+
+struct textarea *toolbar_get_textarea(struct s_toolbar *tb,
+ enum toolbar_textarea which)
+{
+ return(tb->url.textarea);
+}
+
+char *toolbar_get_url(struct s_toolbar *tb)
+{
+ char * c_url = NULL;
+ int c_url_len = 0;
+
+ c_url_len = textarea_get_text(tb->url.textarea, NULL, 0);
+
+ if (c_url_len > -1) {
+ c_url = malloc(c_url_len+1);
+ textarea_get_text(tb->url.textarea, c_url, c_url_len+1);
+ }
+
+ return(c_url);
+}
+
+nsurl * toolbar_get_nsurl(struct s_toolbar * tb)
+{
+ nsurl * ns_url = NULL;
+ char * c_url;
+
+ c_url = toolbar_get_url(tb);
+ if (c_url) {
+ nsurl_create(c_url, &ns_url);
+ }
+
+ return(ns_url);
+}
+
+
+OBJECT *toolbar_get_form(struct s_toolbar *tb)
+{
+ return(tb->form);
+}
+
+
+/* public event handler */
+void toolbar_back_click(struct s_toolbar *tb)
+{
+ struct browser_window * bw;
+ struct gui_window * gw;
+
+ gw = window_get_active_gui_window(tb->owner);
+ assert(gw != NULL);
+ bw = gw->browser->bw;
+ assert(bw != NULL);
+
+ if( browser_window_back_available(bw) ) {
+ browser_window_history_back(bw, false);
+ }
+}
+
+void toolbar_reload_click(struct s_toolbar *tb)
+{
+ struct browser_window * bw;
+ struct gui_window * gw;
+
+ gw = window_get_active_gui_window(tb->owner);
+ assert(gw != NULL);
+ bw = gw->browser->bw;
+ assert(bw != NULL);
+
+ browser_window_reload(bw, true);
+}
+
+void toolbar_forward_click(struct s_toolbar *tb)
+{
+ struct browser_window * bw;
+ struct gui_window * gw;
+
+ gw = window_get_active_gui_window(tb->owner);
+ assert(gw != NULL);
+ bw = gw->browser->bw;
+ assert(bw != NULL);
+
+ if (browser_window_forward_available(bw)) {
+ browser_window_history_forward(bw, false);
+ }
+}
+
+void toolbar_home_click(struct s_toolbar *tb)
+{
+ struct browser_window * bw;
+ struct gui_window * gw;
+ nsurl *url;
+ char * use_url = NULL;
+
+ gw = window_get_active_gui_window(tb->owner);
+ assert(gw != NULL);
+ bw = gw->browser->bw;
+ assert(bw != NULL);
+
+ use_url = nsoption_charp(homepage_url);
+ if (use_url == NULL || strlen(use_url) == 0){
+ use_url = (char*)"about:welcome";
+ }
+
+ if (nsurl_create(use_url, &url) != NSERROR_OK) {
+ atari_warn_user("NoMemory", 0);
+ } else {
+ browser_window_navigate(bw,
+ url,
+ NULL,
+ BW_NAVIGATE_HISTORY,
+ NULL,
+ NULL,
+ NULL);
+ nsurl_unref(url);
+ }
+}
+
+
+void toolbar_stop_click(struct s_toolbar *tb)
+{
+ struct browser_window * bw;
+ struct gui_window * gw;
+
+ gw = window_get_active_gui_window(tb->owner);
+
+ assert(gw != NULL);
+
+ bw = gw->browser->bw;
+
+ assert(bw != NULL);
+
+ browser_window_stop(bw);
+}
+
+void toolbar_favorite_click(struct s_toolbar *tb)
+{
+ nsurl * ns_url = NULL;
+ char * c_url;
+ int c_url_len = 0;
+
+ c_url = toolbar_get_url(tb);
+ c_url_len = strlen(c_url);
+
+ nsurl_create(c_url, &ns_url);
+
+ if (hotlist_has_url(ns_url)) {
+ char msg[c_url_len+100];
+ snprintf(msg, c_url_len+100, "Really delete from favorites: \"%s\"",
+ c_url);
+ if (gemtk_msg_box_show(GEMTK_MSG_BOX_CONFIRM, msg)) {
+ hotlist_remove_url(ns_url);
+ }
+
+ } else {
+ hotlist_add_url(ns_url);
+
+ }
+
+ nsurl_unref(ns_url);
+ free(c_url);
+}
+
+void toolbar_crypto_click(struct s_toolbar *tb)
+{
+
+}
diff --git a/frontends/atari/toolbar.h b/frontends/atari/toolbar.h
new file mode 100644
index 000000000..61ae48c82
--- /dev/null
+++ b/frontends/atari/toolbar.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2013 Ole Loots <ole@monochrom.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 NS_ATARI_TOOLBAR_H
+#define NS_ATARI_TOOLBAR_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+struct s_toolbar;
+struct nsurl;
+
+enum toolbar_textarea {
+ URL_INPUT_TEXT_AREA = 1
+};
+
+struct s_url_widget {
+ struct textarea *textarea;
+ GRECT area;
+};
+
+struct s_throbber_widget {
+ short index;
+ short max_index;
+ bool running;
+};
+
+struct s_toolbar {
+ struct s_gui_win_root *owner;
+ struct s_url_widget url;
+ struct s_throbber_widget throbber;
+ OBJECT *form;
+ GRECT area;
+
+ /* size & location of buttons: */
+ struct s_tb_button * buttons;
+ int btcnt;
+ int style;
+ bool attached;
+ bool reflow;
+ bool visible;
+ bool search_visible;
+};
+
+
+void toolbar_init(void);
+struct s_toolbar *toolbar_create(struct s_gui_win_root *owner);
+void toolbar_destroy(struct s_toolbar * tb);
+void toolbar_exit( void );
+bool toolbar_text_input(struct s_toolbar *tb, char *text);
+bool toolbar_key_input(struct s_toolbar *tb, short nkc);
+void toolbar_mouse_input(struct s_toolbar *tb, short obj, short mbut);
+void toolbar_update_buttons(struct s_toolbar *tb, struct browser_window *bw,
+ short idx);
+void toolbar_get_grect(struct s_toolbar *tb, short which, GRECT *g);
+OBJECT *toolbar_get_form(struct s_toolbar *tb);
+struct textarea *toolbar_get_textarea(struct s_toolbar *tb,
+ enum toolbar_textarea which);
+char *toolbar_get_url(struct s_toolbar *tb);
+struct nsurl * toolbar_get_nsurl(struct s_toolbar * tb);
+void toolbar_set_throbber_state(struct s_toolbar *tb, bool active);
+void toolbar_set_attached(struct s_toolbar *tb, bool attached);
+void toolbar_set_visible(struct s_toolbar *tb, short area, bool visible);
+void toolbar_set_reflow(struct s_toolbar *tb, bool do_reflow);
+void toolbar_set_width(struct s_toolbar *tb, short w);
+void toolbar_set_origin(struct s_toolbar *tb, short x, short y);
+void toolbar_set_dimensions(struct s_toolbar *tb, GRECT *area);
+void toolbar_set_url(struct s_toolbar *tb, const char *text);
+void toolbar_redraw(struct s_toolbar *tb, GRECT *clip);
+void toolbar_throbber_progress(struct s_toolbar *tb);
+/* public events handlers: */
+void toolbar_back_click(struct s_toolbar *tb);
+void toolbar_reload_click(struct s_toolbar *tb);
+void toolbar_forward_click(struct s_toolbar *tb);
+void toolbar_home_click(struct s_toolbar *tb);
+void toolbar_stop_click(struct s_toolbar *tb);
+void toolbar_favorite_click(struct s_toolbar *tb);
+void toolbar_crypto_click(struct s_toolbar *tb);
+
+
+#endif
diff --git a/frontends/atari/treeview.c b/frontends/atari/treeview.c
new file mode 100644
index 000000000..513e2dfe9
--- /dev/null
+++ b/frontends/atari/treeview.c
@@ -0,0 +1,794 @@
+/*
+ * Copyright 2013 Ole Loots <ole@monochrom.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 <inttypes.h>
+#include <sys/types.h>
+#include <string.h>
+
+#include "assert.h"
+#include "cflib.h"
+
+#include "utils/nsoption.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/utils.h"
+#include "content/urldb.h"
+#include "desktop/plotters.h"
+#include "desktop/mouse.h"
+#include "desktop/treeview.h"
+
+#include "atari/gui.h"
+#include "atari/plot/plot.h"
+#include "atari/misc.h"
+#include "atari/gemtk/gemtk.h"
+#include "atari/treeview.h"
+#include "atari/res/netsurf.rsh"
+
+
+/**
+ * Declare Core Window Callbacks:
+ */
+
+void atari_treeview_redraw_request(struct core_window *cw,
+ const struct rect *r);
+void atari_treeview_update_size(struct core_window *cw, int width, int height);
+void atari_treeview_scroll_visible(struct core_window *cw,
+ const struct rect *r);
+void atari_treeview_get_window_dimensions(struct core_window *cw,
+ int *width, int *height);
+ // TODO: implement drag status!
+void atari_treeview_drag_status(struct core_window *cw,
+ core_window_drag_status ds);
+
+static struct core_window_callback_table cw_t = {
+ .redraw_request = atari_treeview_redraw_request,
+ .update_size = atari_treeview_update_size,
+ .scroll_visible = atari_treeview_scroll_visible,
+ .get_window_dimensions = atari_treeview_get_window_dimensions,
+ .drag_status = atari_treeview_drag_status
+};
+
+
+struct atari_treeview_window {
+ struct atari_treeview_window * prev_open;
+ struct atari_treeview_window * next_open;
+ GUIWIN * window;
+ bool disposing;
+ bool redraw;
+ bool is_open;
+ GRECT rdw_area;
+ POINT extent;
+ POINT click;
+ POINT startdrag;
+ struct atari_treeview_callbacks *io;
+ void * user_data;
+};
+
+static struct atari_treeview_window * treeviews_open;
+
+/* native GUI event handlers: */
+static void on_mbutton_event(struct core_window *cw, EVMULT_OUT *ev_out,
+ short msg[8]);
+static void on_keybd_event(struct core_window *cw, EVMULT_OUT *ev_out,
+ short msg[8]);
+static void on_redraw_event(struct core_window *cw, EVMULT_OUT *ev_out,
+ short msg[8]);
+
+/* static utils: */
+//static void atari_treeview_dump_info(struct atari_treeview_window *tv, char *s);
+
+/**
+ * Schedule a redraw of the treeview content
+ *
+ */
+static void atari_treeview_redraw_grect_request(struct core_window *cw,
+ GRECT *area)
+{
+ struct atari_treeview_window *tv = (struct atari_treeview_window *)cw;
+ if (cw != NULL) {
+ if( tv->redraw == false ){
+ tv->redraw = true;
+ tv->rdw_area.g_x = area->g_x;
+ tv->rdw_area.g_y = area->g_y;
+ tv->rdw_area.g_w = area->g_w;
+ tv->rdw_area.g_h = area->g_h;
+ } else {
+ /* merge the redraw area to the new area.: */
+ int newx1 = area->g_x+area->g_w;
+ int newy1 = area->g_y+area->g_h;
+ int oldx1 = tv->rdw_area.g_x + tv->rdw_area.g_w;
+ int oldy1 = tv->rdw_area.g_y + tv->rdw_area.g_h;
+ tv->rdw_area.g_x = MIN(tv->rdw_area.g_x, area->g_x);
+ tv->rdw_area.g_y = MIN(tv->rdw_area.g_y, area->g_y);
+ tv->rdw_area.g_w = ( oldx1 > newx1 ) ? oldx1 - tv->rdw_area.g_x : newx1 - tv->rdw_area.g_x;
+ tv->rdw_area.g_h = ( oldy1 > newy1 ) ? oldy1 - tv->rdw_area.g_y : newy1 - tv->rdw_area.g_y;
+ }
+ //dbg_grect("atari_treeview_request_redraw_grect", &tv->rdw_area);
+ }
+}
+
+
+void atari_treeview_get_grect(struct core_window *cw, enum treeview_area_e mode,
+ GRECT *dest)
+{
+
+ struct atari_treeview_window *tv = (struct atari_treeview_window *)cw;
+
+ if (mode == TREEVIEW_AREA_CONTENT) {
+ gemtk_wm_get_grect(tv->window, GEMTK_WM_AREA_CONTENT, dest);
+ }
+ else if (mode == TREEVIEW_AREA_TOOLBAR) {
+ gemtk_wm_get_grect(tv->window, GEMTK_WM_AREA_TOOLBAR, dest);
+ }
+}
+
+GUIWIN * atari_treeview_get_gemtk_window(struct core_window *cw)
+{
+ struct atari_treeview_window *tv = (struct atari_treeview_window *)cw;
+ return(tv->window);
+}
+
+/*
+static void atari_treeview_dump_info(struct atari_treeview_window *tv,
+ char * title)
+{
+ printf("Treeview Dump (%s)\n", title);
+ printf("=================================\n");
+ gemtk_wm_dump_window_info(atari_treeview_get_gemtk_window((struct core_window *)tv));
+ GEMTK_DBG_GRECT("Redraw Area: \n", &tv->rdw_area)
+ dbg_grect("Redraw Area2: \n", &tv->rdw_area);
+ printf("Extent: x: %d, y: %d\n", tv->extent.x, tv->extent.y);
+}
+*/
+
+static bool atari_treeview_is_iconified(struct core_window *cw){
+
+ struct atari_treeview_window *tv = (struct atari_treeview_window *)cw;
+
+ return((gemtk_wm_get_state(tv->window)&GEMTK_WM_STATUS_ICONIFIED) != 0);
+}
+
+static void atari_treeview_redraw_icon(struct core_window *cw, GRECT *clip)
+{
+ struct atari_treeview_window *tv = (struct atari_treeview_window *)cw;
+ GRECT visible, work;
+ OBJECT * tree = gemtk_obj_get_tree(ICONIFY);
+ short aesh = gemtk_wm_get_handle(tv->window);
+
+ gemtk_wm_get_grect(tv->window, GEMTK_WM_AREA_WORK, &work);
+
+ tree->ob_x = work.g_x;
+ tree->ob_y = work.g_y;
+ tree->ob_width = work.g_w;
+ tree->ob_height = work.g_h;
+
+ wind_get_grect(aesh, WF_FIRSTXYWH, &visible);
+ while (visible.g_h > 0 && visible.g_w > 0) {
+
+ if (rc_intersect(&work, &visible)) {
+ objc_draw(tree, 0, 8, visible.g_x, visible.g_y, visible.g_w,
+ visible.g_h);
+ } else {
+ //dbg_grect("redraw vis area outside", &visible);
+ }
+
+ wind_get_grect(aesh, WF_NEXTXYWH, &visible);
+ }
+}
+
+void atari_treeview_redraw(struct core_window *cw)
+{
+ struct atari_treeview_window *tv = (struct atari_treeview_window *)cw;
+ short pxy[4];
+
+ if (tv != NULL && tv->is_open) {
+ if( tv->redraw && ((plot_get_flags() & PLOT_FLAG_OFFSCREEN) == 0) ) {
+
+ short todo[4];
+ GRECT work;
+ short handle = gemtk_wm_get_handle(tv->window);
+ struct gemtk_wm_scroll_info_s *slid;
+
+ gemtk_wm_get_grect(tv->window, GEMTK_WM_AREA_CONTENT, &work);
+ slid = gemtk_wm_get_scroll_info(tv->window);
+
+// // Debug code: this 3 lines help to inspect the redraw
+// // areas...
+// pxy[0] = work.g_x;
+// pxy[1] = work.g_y;
+// pxy[2] = pxy[0] + work.g_w-1;
+// pxy[3] = pxy[1] + work.g_h-1;
+//
+// vsf_color(plot_get_vdi_handle(), 0);
+// v_bar(plot_get_vdi_handle(), (short*)&pxy);
+// evnt_timer(500);
+
+ struct redraw_context ctx = {
+ .interactive = true,
+ .background_images = true,
+ .plot = &atari_plotters
+ };
+ plot_set_dimensions(work.g_x, work.g_y, work.g_w, work.g_h);
+ if (plot_lock() == false)
+ return;
+
+ if( wind_get(handle, WF_FIRSTXYWH,
+ &todo[0], &todo[1], &todo[2], &todo[3] )!=0 ) {
+ while (todo[2] && todo[3]) {
+
+ if(!rc_intersect(&work, (GRECT*)&todo)){
+ if (wind_get(handle, WF_NEXTXYWH,
+ &todo[0], &todo[1], &todo[2], &todo[3])==0) {
+ break;
+ }
+ continue;
+ }
+ pxy[0] = todo[0];
+ pxy[1] = todo[1];
+ pxy[2] = todo[0] + todo[2]-1;
+ pxy[3] = todo[1] + todo[3]-1;
+ vs_clip(plot_get_vdi_handle(), 1, (short*)&pxy);
+
+ // Debug code: this 3 lines help to inspect the redraw
+ // areas...
+
+// vsf_color(plot_get_vdi_handle(), 3);
+// v_bar(plot_get_vdi_handle(), (short*)&pxy);
+// evnt_timer(500);
+
+
+ /* convert screen to treeview coords: */
+ todo[0] = todo[0] - work.g_x ;//+ slid->x_pos*slid->x_unit_px;
+ todo[1] = todo[1] - work.g_y ;//+ slid->y_pos*slid->y_unit_px;
+ if( todo[0] < 0 ){
+ todo[2] = todo[2] + todo[0];
+ todo[0] = 0;
+ }
+ if( todo[1] < 0 ){
+ todo[3] = todo[3] + todo[1];
+ todo[1] = 0;
+ }
+
+ if (rc_intersect((GRECT *)&tv->rdw_area,(GRECT *)&todo)) {
+ struct rect clip;
+
+ clip.x0 = todo[0]+(slid->x_pos*slid->x_unit_px);
+ clip.y0 = todo[1]+(slid->y_pos*slid->y_unit_px);
+ clip.x1 = clip.x0 + todo[2]+(slid->x_pos*slid->x_unit_px);
+ clip.y1 = clip.y0 + todo[3]+(slid->y_pos*slid->y_unit_px);
+
+ tv->io->draw(cw, -(slid->x_pos*slid->x_unit_px),
+ -(slid->y_pos*slid->y_unit_px),
+ &clip, &ctx);
+ }
+ vs_clip(plot_get_vdi_handle(), 0, (short*)&pxy);
+ if (wind_get(handle, WF_NEXTXYWH,
+ &todo[0], &todo[1], &todo[2], &todo[3])==0) {
+ break;
+ }
+ }
+ } else {
+ plot_unlock();
+ return;
+ }
+ plot_unlock();
+ tv->redraw = false;
+ tv->rdw_area.g_x = 65000;
+ tv->rdw_area.g_y = 65000;
+ tv->rdw_area.g_w = -1;
+ tv->rdw_area.g_h = -1;
+ } else {
+ /* just copy stuff from the offscreen buffer */
+ }
+ }
+}
+
+
+/**
+ * GEMTK (netsurf's GEM toolkit) event sink
+ *
+*/
+static short handle_event(GUIWIN *win, EVMULT_OUT *ev_out, short msg[8])
+{
+ short retval = 0;
+ struct atari_treeview_window *tv = (struct atari_treeview_window *)
+ gemtk_wm_get_user_data(win);
+ struct core_window *cw = (struct core_window *)tv;
+
+ if( (ev_out->emo_events & MU_MESAG) != 0 ) {
+ // handle message
+ switch (msg[0]) {
+
+ case WM_REDRAW:
+ on_redraw_event(cw, ev_out, msg);
+ break;
+
+ default:
+ break;
+ }
+ }
+ if( (ev_out->emo_events & MU_KEYBD) != 0 ) {
+ on_keybd_event(cw, ev_out, msg);
+ }
+ if( (ev_out->emo_events & MU_BUTTON) != 0 ) {
+ LOG("Treeview click at: %d,%d\n", ev_out->emo_mouse.p_x, ev_out->emo_mouse.p_y);
+ on_mbutton_event(cw, ev_out, msg);
+ }
+
+ if(tv != NULL && tv->io->gemtk_user_func != NULL){
+ tv->io->gemtk_user_func(win, ev_out, msg);
+ }
+
+ // TODO: evaluate return values of event handler functions and pass them on:
+ return(retval);
+}
+
+
+static void __CDECL on_keybd_event(struct core_window *cw, EVMULT_OUT *ev_out,
+ short msg[8])
+{
+ long kstate = 0;
+ long kcode = 0;
+ long ucs4;
+ long ik;
+ unsigned short nkc = 0;
+ unsigned char ascii;
+ struct atari_treeview_window *tv = (struct atari_treeview_window *)cw;
+
+ kstate = ev_out->emo_kmeta;
+ kcode = ev_out->emo_kreturn;
+ nkc= gem_to_norm( (short)kstate, (short)kcode );
+ ascii = (nkc & 0xFF);
+ ik = nkc_to_input_key(nkc, &ucs4);
+
+ if (ik == 0) {
+ if (ascii >= 9) {
+ tv->io->keypress(cw, ucs4);
+ }
+ } else {
+ tv->io->keypress(cw, ik);
+ }
+}
+
+
+static void __CDECL on_redraw_event(struct core_window *cw, EVMULT_OUT *ev_out,
+ short msg[8])
+{
+ GRECT work, clip;
+ struct gemtk_wm_scroll_info_s *slid;
+ struct atari_treeview_window *tv = (struct atari_treeview_window *)cw;
+
+ if (tv == NULL)
+ return;
+
+ gemtk_wm_get_grect(tv->window, GEMTK_WM_AREA_CONTENT, &work);
+ //dbg_grect("treeview work: ", &work);
+
+ atari_treeview_get_grect(cw, TREEVIEW_AREA_CONTENT, &work);
+ //dbg_grect("treeview work: ", &work);
+ slid = gemtk_wm_get_scroll_info(tv->window);
+
+ clip = work;
+
+ /* check if the redraw area intersects with the content area: */
+ if ( !rc_intersect( (GRECT*)&msg[4], &clip)) {
+ return;
+ }
+
+ if (atari_treeview_is_iconified(cw) == true) {
+ atari_treeview_redraw_icon(cw, &clip);
+ return;
+ }
+
+ /* make redraw coords relative to content viewport */
+ clip.g_x -= work.g_x;
+ clip.g_y -= work.g_y;
+
+ /* normalize the redraw coords: */
+ if( clip.g_x < 0 ) {
+ clip.g_w = work.g_w + clip.g_x;
+ clip.g_x = 0;
+ }
+ if( clip.g_y < 0 ) {
+ clip.g_h = work.g_h + clip.g_y;
+ clip.g_y = 0;
+ }
+
+ /* Merge redraw coords: */
+ if( clip.g_h > 0 && clip.g_w > 0 ) {
+
+ GRECT rdrw_area;
+
+ rdrw_area.g_x = clip.g_x;
+ rdrw_area.g_y = clip.g_y;
+ rdrw_area.g_w = clip.g_w;
+ rdrw_area.g_h = clip.g_h;
+
+ //dbg_grect("treeview on_redraw_event ", &rdrw_area);
+
+ atari_treeview_redraw_grect_request(cw, &rdrw_area);
+ }
+}
+
+static void __CDECL on_mbutton_event(struct core_window *cw, EVMULT_OUT *ev_out,
+ short msg[8])
+{
+ struct atari_treeview_window *tv = (struct atari_treeview_window *)cw;
+ struct gemtk_wm_scroll_info_s *slid;
+ GRECT work;
+ short mx, my;
+ short cur_rel_x, cur_rel_y, dummy, mbut;
+
+ assert(tv);
+
+ gemtk_wm_get_grect(tv->window, GEMTK_WM_AREA_CONTENT, &work);
+ slid = gemtk_wm_get_scroll_info(tv->window);
+ mx = ev_out->emo_mouse.p_x;
+ my = ev_out->emo_mouse.p_y;
+
+ /* mouse click relative origin: */
+
+ short origin_rel_x = (mx-work.g_x) +
+ (slid->x_pos*slid->x_unit_px);
+ short origin_rel_y = (my-work.g_y) +
+ (slid->y_pos*slid->y_unit_px);
+
+ /* Only pass on events in the content area: */
+ if( origin_rel_x >= 0 && origin_rel_y >= 0
+ && mx < work.g_x + work.g_w
+ && my < work.g_y + work.g_h )
+ {
+ if (ev_out->emo_mclicks == 2) {
+ tv->io->mouse_action(cw,
+ BROWSER_MOUSE_CLICK_1|BROWSER_MOUSE_DOUBLE_CLICK,
+ origin_rel_x, origin_rel_y);
+ return;
+ }
+
+ graf_mkstate(&cur_rel_x, &cur_rel_y, &mbut, &dummy);
+ /* check for click or hold: */
+ if( (mbut&1) == 0 ){
+ int bms;
+ bms = BROWSER_MOUSE_CLICK_1 | BROWSER_MOUSE_PRESS_1;
+ if(ev_out->emo_mclicks == 2 ) {
+ bms = BROWSER_MOUSE_DOUBLE_CLICK;
+ }
+ tv->io->mouse_action(cw, bms, origin_rel_x, origin_rel_y);
+ } else {
+ /* button still pressed */
+ short prev_x = origin_rel_x;
+ short prev_y = origin_rel_y;
+
+ cur_rel_x = origin_rel_x;
+ cur_rel_y = origin_rel_y;
+
+ gem_set_cursor(&gem_cursors.hand);
+
+ tv->startdrag.x = origin_rel_x;
+ tv->startdrag.y = origin_rel_y;
+ /* First, report mouse press, to trigger entry selection */
+ tv->io->mouse_action(cw, BROWSER_MOUSE_CLICK_1 | BROWSER_MOUSE_PRESS_1, cur_rel_x,
+ cur_rel_y);
+ atari_treeview_redraw(cw);
+ tv->io->mouse_action(cw, BROWSER_MOUSE_DRAG_1 | BROWSER_MOUSE_DRAG_ON,
+ cur_rel_x, cur_rel_y);
+ do{
+ if (abs(prev_x-cur_rel_x) > 5 || abs(prev_y-cur_rel_y) > 5) {
+ tv->io->mouse_action(cw,
+ BROWSER_MOUSE_HOLDING_1 | BROWSER_MOUSE_DRAG_ON,
+ cur_rel_x, cur_rel_y);
+ prev_x = cur_rel_x;
+ prev_y = cur_rel_y;
+ }
+
+ if (tv->redraw) {
+ // TODO: maybe GUI poll would fit better here?
+ // ... is gui_poll re-entrance save?
+ atari_treeview_redraw(cw);
+ }
+
+ /* sample mouse button state: */
+ graf_mkstate(&cur_rel_x, &cur_rel_y, &mbut, &dummy);
+ cur_rel_x = (cur_rel_x-work.g_x)+(slid->x_pos*slid->x_unit_px);
+ cur_rel_y = (cur_rel_y-work.g_y)+(slid->y_pos*slid->y_unit_px);
+ } while( mbut & 1 );
+
+ /* End drag: */
+ tv->io->mouse_action(cw, BROWSER_MOUSE_HOVER, cur_rel_x, cur_rel_y);
+ gem_set_cursor(&gem_cursors.arrow);
+ }
+ }
+}
+
+
+struct core_window *
+atari_treeview_create(GUIWIN *win, struct atari_treeview_callbacks * callbacks,
+ void * user_data, uint32_t flags)
+{
+
+ /* allocate the core_window struct: */
+ struct atari_treeview_window * tv;
+ struct gemtk_wm_scroll_info_s *slid;
+
+ tv = calloc(1, sizeof(struct atari_treeview_window));
+ if (tv == NULL) {
+ LOG("calloc failed");
+ atari_warn_user(messages_get_errorcode(NSERROR_NOMEM), 0);
+ return NULL;
+ }
+
+ /* Store the window ref inside the new treeview: */
+ tv->window = win;
+ tv->io = callbacks;
+ tv->user_data = user_data;
+
+ // Setup gemtk event handler function:
+ gemtk_wm_set_event_handler(win, handle_event);
+
+ // bind window user data to treeview ref:
+ gemtk_wm_set_user_data(win, (void*)tv);
+
+ // Get acces to the gemtk scroll info struct:
+ slid = gemtk_wm_get_scroll_info(tv->window);
+
+ // Setup line and column height/width of the window,
+ // each scroll takes the configured steps:
+ slid->y_unit_px = 16;
+ slid->x_unit_px = 16;
+
+ assert(tv->io);
+ assert(tv->io->init_phase2);
+
+ /* Now that the window is configured for treeview content, */
+ /* call init_phase2 which must create the treeview */
+ /* descriptor, and at least setup the the default */
+ /* event handlers of the treeview: */
+ /* It would be more simple to not pass around the callbacks */
+ /* but the treeview constructor requires them for initialization... */
+ nserror err = tv->io->init_phase2((struct core_window *)tv, &cw_t);
+ if (err != NSERROR_OK) {
+ free(tv);
+ tv = NULL;
+ }
+
+ return((struct core_window *)tv);
+}
+
+void atari_treeview_delete(struct core_window * cw)
+{
+ struct atari_treeview_window *tv = (struct atari_treeview_window*)cw;
+
+ assert(tv);
+ assert(tv->io->finish);
+
+ tv->io->finish(cw);
+
+ free(tv);
+}
+
+
+void atari_treeview_open(struct core_window *cw, GRECT *pos)
+{
+ struct atari_treeview_window *tv = (struct atari_treeview_window*)cw;
+ if (tv->window != NULL && tv->is_open == false) {
+ tv->is_open = true;
+ wind_open_grect(gemtk_wm_get_handle(tv->window), pos);
+ gemtk_wm_link(tv->window);
+ if (treeviews_open == NULL) {
+ treeviews_open = tv;
+ treeviews_open->next_open = NULL;
+ treeviews_open->prev_open = NULL;
+ } else {
+ struct atari_treeview_window * tmp;
+ tmp = treeviews_open;
+ while(tmp->next_open != NULL){
+ tmp = tmp->next_open;
+ }
+ tmp->next_open = tv;
+ tv->prev_open = tmp;
+ tv->next_open = NULL;
+ }
+ }
+}
+
+bool atari_treeview_is_open(struct core_window *cw)
+{
+ struct atari_treeview_window *tv = (struct atari_treeview_window*)cw;
+ return(tv->is_open);
+}
+
+void atari_treeview_set_user_data(struct core_window * cw,
+ void *user_data_ptr)
+{
+ struct atari_treeview_window *tv = (struct atari_treeview_window*)cw;
+ tv->user_data = user_data_ptr;
+}
+
+void * atari_treeview_get_user_data(struct core_window * cw)
+{
+ struct atari_treeview_window *tv = (struct atari_treeview_window*)cw;
+ return(tv->user_data);
+}
+
+void atari_treeview_close(struct core_window *cw)
+{
+ struct atari_treeview_window *tv = (struct atari_treeview_window*)cw;
+ if (tv->window != NULL) {
+ tv->is_open = false;
+ wind_close(gemtk_wm_get_handle(tv->window));
+ gemtk_wm_unlink(tv->window);
+ /* unlink the window: */
+ if (tv->prev_open != NULL) {
+ tv->prev_open->next_open = tv->next_open;
+ } else {
+ treeviews_open = tv->next_open;
+ }
+ if (tv->next_open != NULL) {
+ tv->next_open->prev_open = tv->prev_open;
+ }
+ }
+}
+
+
+/**
+ * Core Window Callbacks:
+ */
+
+/**
+ * Request a redraw of the window
+ *
+ * \param cw the core window object
+ * \param r rectangle to redraw
+ */
+void atari_treeview_redraw_request(struct core_window *cw, const struct rect *r)
+{
+ GRECT area;
+ struct gemtk_wm_scroll_info_s * slid;
+ struct atari_treeview_window * tv = (struct atari_treeview_window *)cw;
+
+ RECT_TO_GRECT(r, &area)
+
+ assert(tv);
+
+ slid = gemtk_wm_get_scroll_info(tv->window);
+
+ //dbg_rect("redraw rect request", r);
+
+ // treeview redraw is always full window width:
+ area.g_x = 0;
+ area.g_w = 8000;
+ // but vertical redraw region is clipped:
+ area.g_y = r->y0 - (slid->y_pos*slid->y_unit_px);
+ area.g_h = r->y1 - r->y0;
+ atari_treeview_redraw_grect_request(cw, &area);
+}
+
+/**
+ * Update the limits of the window
+ *
+ * \param cw the core window object
+ * \param width the width in px, or negative if don't care
+ * \param height the height in px, or negative if don't care
+ */
+void atari_treeview_update_size(struct core_window *cw, int width, int height)
+{
+ GRECT area;
+ struct gemtk_wm_scroll_info_s *slid;
+ struct atari_treeview_window *tv = (struct atari_treeview_window *)cw;
+
+ if (tv != NULL) {
+
+ if (tv->disposing)
+ return;
+
+ /* Get acces to the gemtk window slider settings: */
+ slid = gemtk_wm_get_scroll_info(tv->window);
+
+ /* recalculate and refresh sliders: */
+ atari_treeview_get_grect(cw, TREEVIEW_AREA_CONTENT, &area);
+ if (width > -1) {
+ slid->x_units = (width/slid->x_unit_px);
+ } else {
+ slid->x_units = 1;
+ }
+
+ if (height > -1) {
+ slid->y_units = (height/slid->y_unit_px);
+ } else {
+ slid->y_units = 1;
+ }
+
+ tv->extent.x = width;
+ tv->extent.y = height;
+
+
+ /*printf("units content: %d, units viewport: %d\n", (height/slid->y_unit_px),
+ (area.g_h/slid->y_unit_px));*/
+ gemtk_wm_update_slider(tv->window, GEMTK_WM_VH_SLIDER);
+ }
+}
+
+
+/**
+ * Scroll the window to make area visible
+ *
+ * \param cw the core window object
+ * \param r rectangle to make visible
+ */
+void atari_treeview_scroll_visible(struct core_window *cw, const struct rect *r)
+{
+ /* atari frontend doesn't support dragging outside the treeview */
+ /* so there is no need to implement this? */
+}
+
+
+/**
+ * Get window viewport dimensions
+ *
+ * \param cw the core window object
+ * \param width to be set to viewport width in px, if non NULL
+ * \param height to be set to viewport height in px, if non NULL
+ */
+void atari_treeview_get_window_dimensions(struct core_window *cw,
+ int *width, int *height)
+{
+ if (cw != NULL && (width != NULL || height != NULL)) {
+ GRECT work;
+ atari_treeview_get_grect(cw, TREEVIEW_AREA_CONTENT, &work);
+ *width = work.g_w;
+ *height = work.g_h;
+ }
+}
+
+
+/**
+ * Inform corewindow owner of drag status
+ *
+ * \param cw the core window object
+ * \param ds the current drag status
+ */
+void atari_treeview_drag_status(struct core_window *cw,
+ core_window_drag_status ds)
+{
+
+}
+
+void atari_treeview_flush_redraws(void)
+{
+ struct atari_treeview_window *tmp;
+
+ tmp = treeviews_open;
+
+ if(tmp){
+ while(tmp){
+ assert(tmp->is_open);
+ if(tmp->redraw){
+ if (atari_treeview_is_iconified((struct core_window *)tmp)) {
+ /* No content redraw for iconified windows */
+ /* because otherwise the icon draw function would */
+ /* have to deal with plot canvas coords */
+ continue;
+ }
+
+ atari_treeview_redraw((struct core_window *)tmp);
+ }
+ tmp = tmp->next_open;
+ }
+ }
+}
+
diff --git a/frontends/atari/treeview.h b/frontends/atari/treeview.h
new file mode 100644
index 000000000..a6b4a62e9
--- /dev/null
+++ b/frontends/atari/treeview.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2013 Ole Loots <ole@monochrom.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 NSATARI_TREEVIEW_H
+#define NSATARI_TREEVIEW_H
+
+#include "desktop/core_window.h"
+#include "atari/gui.h"
+#include "atari/gemtk/gemtk.h"
+
+/**
+ * Default AES Window widgets for a treeview window, can be passed to
+ * atari_treeview_create as the flags parameter to have an standardized treeview
+ * window.
+ */
+#define ATARI_TREEVIEW_WIDGETS (CLOSER | MOVER | SIZER| NAME | FULLER | \
+ SMALLER | VSLIDE | HSLIDE | UPARROW | DNARROW | \
+ LFARROW | RTARROW)
+
+enum treeview_area_e {
+ TREEVIEW_AREA_WORK = 0,
+ TREEVIEW_AREA_TOOLBAR,
+ TREEVIEW_AREA_CONTENT
+};
+
+struct core_window;
+struct atari_treeview_window;
+
+/**
+ * The atari treeview implementation wraps the core_window callbacks
+ * So that it can process parameters and then it passes the event further
+ * To the specific implementation window.
+ * These callbacks must be implemented by any atari treeview window.
+ */
+
+/** \todo atari add drag_status callback */
+typedef nserror (*atari_treeview_init2_callback)(struct core_window *cw, struct core_window_callback_table * default_callbacks);
+typedef void (*atari_treeview_finish_callback)(struct core_window *cw);
+typedef void (*atari_treeview_keypress_callback)(struct core_window *cw, uint32_t ucs4);
+typedef void (*atari_treeview_mouse_action_callback)(struct core_window *cw, browser_mouse_state mouse, int x, int y);
+typedef void (*atari_treeview_draw_callback)(struct core_window *cw, int x, int y, struct rect *clip, const struct redraw_context *ctx);
+
+struct atari_treeview_callbacks {
+ atari_treeview_init2_callback init_phase2;
+ atari_treeview_finish_callback finish;
+ atari_treeview_draw_callback draw;
+ atari_treeview_keypress_callback keypress;
+ atari_treeview_mouse_action_callback mouse_action;
+ gemtk_wm_event_handler_f gemtk_user_func;
+};
+
+/**
+ * Initalize an window to be an treeview window.
+ *
+*/
+struct core_window *atari_treeview_create(GUIWIN *win, struct atari_treeview_callbacks * callbacks, void * user_data, uint32_t flags);
+
+/**
+ * Free the Treeview, but not the gemtk window used for the treeview.
+ */
+void atari_treeview_delete(struct core_window *cw);
+
+/**
+ * Open the treeview window.
+ */
+void atari_treeview_open(struct core_window *cw, GRECT *pos);
+
+/**
+ * Returns the window "open" state.
+ */
+bool atari_treeview_is_open(struct core_window *cw);
+
+/**
+ * Closes (hides) the treeview window.
+ */
+void atari_treeview_close(struct core_window *cw);
+
+/**
+ * Get the window manager window handle
+ */
+
+GUIWIN * atari_treeview_get_gemtk_window(struct core_window *cw);
+
+/**
+ * Get an specific area inside the window.
+ */
+void atari_treeview_get_grect(struct core_window *cw, enum treeview_area_e mode, GRECT *dest);
+
+/**
+ * Process all pending redraw requests for a single treeview
+ */
+void atari_treeview_redraw(struct core_window *cw);
+
+/**
+ * Attach arbitary user data to the treeview.
+ */
+void atari_treeview_set_user_data(struct core_window *cw, void *user_data_ptr);
+
+/**
+ * Return the arbitary user data set by atari_treeview_set_user_data()
+ */
+void *atari_treeview_get_user_data(struct core_window *cw);
+
+/**
+ * Process all redraw request of all open Treeview windows
+ */
+void atari_treeview_flush_redraws(void);
+
+#endif //NSATARI_TREEVIEW_H
diff --git a/frontends/atari/verify_ssl.c b/frontends/atari/verify_ssl.c
new file mode 100644
index 000000000..cbd9d0bf6
--- /dev/null
+++ b/frontends/atari/verify_ssl.c
@@ -0,0 +1,269 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.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 <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <windom.h>
+
+#include "utils/errors.h"
+#include "utils/utils.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "content/urldb.h"
+#include "content/fetch.h"
+#include "atari/res/netsurf.rsh"
+#include "atari/verify_ssl.h"
+
+/*
+ todo: this file need to use the treeview api - complete rework,
+ current implementation is not used in any way.
+*/
+
+extern void * h_gem_rsrc;
+extern short atari_plot_vdi_handle;
+
+
+#define CERT_INF_LINES 8
+
+static struct ssl_info_draw_param
+{
+ struct ssl_cert_info * cert_infos_n;
+ unsigned long num_certs;
+ int current;
+ int scrollx;
+ int cols;
+ int scrolly;
+ int rows; /* assumed to be 8 */
+ OBJECT * tree;
+} dp;
+
+
+static int cert_display_width( struct ssl_cert_info * cert_info )
+{
+ int l1, l2;
+ int add = 16; /* strlen("Issuer: "); */
+
+ l1 = strlen(cert_info->issuer) + add;
+ l2 = strlen(cert_info->subject) + add;
+ return( MAX(l1, l2) );
+}
+
+
+static void __CDECL cert_info_draw( WINDOW * win, short buf[8], void * data)
+{
+ struct ssl_info_draw_param * dp = (struct ssl_info_draw_param *)data;
+ GRECT work;
+ short pxy[4];
+ int maxchars;
+ short d, cbh, cbw;
+ int i = 0;
+ short x,y,w,h;
+ int px_ypos;
+ char * line = malloc(512);
+ if( line == NULL )
+ return;
+
+ LOG("Cert info draw, win: %p, data: %p, scrollx: %d", win, data, dp->scrollx );
+
+ WindGet( win, WF_WORKXYWH, &x, &y, &w, &h );
+ /*using static values here, as RsrcUserDraw has mem leaks & a very small stack */
+ pxy[0] = work.g_x = x + 8;
+ pxy[1] = work.g_y = y + 80;
+ pxy[2] = x + 8 + 272;
+ pxy[3] = y + 80 + 176;
+ work.g_w = 272;
+ work.g_h = 176;
+
+ maxchars = (work.g_w / 8)+1;
+ vs_clip( atari_plot_vdi_handle, 1,(short*) &pxy );
+ vswr_mode( atari_plot_vdi_handle, MD_REPLACE );
+ vsf_interior( atari_plot_vdi_handle, 1 );
+ vsf_color( atari_plot_vdi_handle, LWHITE );
+ v_bar( atari_plot_vdi_handle, (short*)&pxy );
+ vst_height( atari_plot_vdi_handle, 16, &d, &d, &cbw, &cbh );
+ vst_alignment(atari_plot_vdi_handle, 0, 5, &d, &d );
+ vst_color( atari_plot_vdi_handle, BLACK );
+ vst_effects( atari_plot_vdi_handle, 0 );
+ px_ypos = 0;
+ for(i=0; i<CERT_INF_LINES; i++ ) {
+ switch( i ) {
+ case 0:
+ sprintf(line, "Cert Version: %d", dp->cert_infos_n[dp->current].version );
+ break;
+
+ case 1:
+ sprintf(line, "Invalid before: %s", &dp->cert_infos_n[dp->current].not_before );
+ break;
+
+ case 2:
+ sprintf(line, "Invalid after: %s", &dp->cert_infos_n[dp->current].not_after );
+ break;
+
+ case 3:
+ sprintf(line, "Signature type: %d", dp->cert_infos_n[dp->current].sig_type );
+ break;
+
+ case 4:
+ sprintf(line, "Serial: %d", dp->cert_infos_n[dp->current].serial );
+ break;
+
+ case 5:
+ sprintf(line, "Issuer: %s", &dp->cert_infos_n[dp->current].issuer );
+ break;
+
+ case 6:
+ sprintf(line, "Subject: %s", &dp->cert_infos_n[dp->current].subject );
+ break;
+
+ case 7:
+ sprintf(line, "Cert type: %d", dp->cert_infos_n[dp->current].cert_type );
+ break;
+
+ default:
+ break;
+ }
+ if( (int)strlen(line) > dp->scrollx ) {
+ if( dp->scrollx + maxchars < 511 && ( (signed int)strlen(line) - dp->scrollx) > maxchars )
+ line[dp->scrollx + maxchars] = 0;
+ v_gtext(atari_plot_vdi_handle, work.g_x + 1, work.g_y + px_ypos, &line[dp->scrollx]);
+ }
+ px_ypos += cbh;
+ }
+ vst_alignment(atari_plot_vdi_handle, 0, 0, &d, &d );
+ vs_clip( atari_plot_vdi_handle, 0, (short*)&pxy );
+ free( line );
+}
+
+
+static void do_popup( WINDOW *win, int index, int mode, void *data)
+{
+ struct ssl_info_draw_param * dp = (struct ssl_info_draw_param *)data;
+ char * items[dp->num_certs];
+ short x, y;
+ unsigned int i;
+ LOG("do_popup: num certs: %d", dp->num_certs);
+ for( i = 0; i<dp->num_certs; i++) {
+ items[i] = malloc( 48 );
+ strncpy(items[i], (char*)&dp->cert_infos_n[i].issuer, 46 );
+ }
+ objc_offset( FORM(win), index, &x, &y );
+ dp->current = MenuPopUp( items, x, y,
+ dp->num_certs, MIN( 3, dp->num_certs), 0,
+ P_LIST + P_WNDW + P_CHCK );
+ ObjcChange( OC_FORM, win, index, NORMAL, TRUE );
+ dp->cols = cert_display_width( &dp->cert_infos_n[dp->current] );
+ dp->rows = 8;
+ dp->scrollx = 0;
+ dp->scrolly = 0;
+
+ /* Send (!) redraw ( OC_MSG ) */
+ ObjcDrawParent( OC_FORM, FORM(win), VERIFY_BOX_DETAILS, 1, 7 | OC_MSG );
+ for( i = 0; i<dp->num_certs; i++) {
+ free( items[i] );
+ }
+}
+
+
+
+bool verify_ssl_form_do( const char * url, const struct ssl_cert_info * cert_infos_n ,
+ unsigned long num_certs )
+{
+ OBJECT *tree;
+ WINDOW * form;
+
+ bool bres = false;
+ bool cont = true;
+ int res = 0;
+ dp.cert_infos_n = (struct ssl_cert_info *)cert_infos_n;
+ dp.num_certs = num_certs;
+ dp.scrollx = 0;
+ dp.scrolly = 0;
+ dp.current = 0;
+ dp.cols = cert_display_width( &dp.cert_infos_n[dp.current] );
+ dp.rows = 8;
+ dp.tree = tree;
+
+ RsrcGaddr (h_gem_rsrc , R_TREE, VERIFY, &tree);
+ ObjcString( tree, VERIFY_LBL_HOST, (char*)url );
+ ObjcChange( OC_OBJC, tree, VERIFY_BT_ACCEPT, 0, 0 );
+ ObjcChange( OC_OBJC, tree, VERIFY_BT_REJECT, 0, 0 );
+ form = FormWindBegin( tree, (char*)"SSL Verify failed" );
+ EvntDataAdd( form, WM_REDRAW, cert_info_draw, (void*)&dp, EV_BOT );
+ /* this results in some extended objects which can not be freed: :( */
+ /* RsrcUserDraw( OC_FORM, tree, VERIFY_BOX_DETAILS, cert_info_draw,(void*)&dp ) ; */
+ ObjcAttachFormFunc( form, VERIFY_BT_NEXT_CERT, do_popup, &dp );
+ /*
+ ObjcAttachFormFunc( form, VERIFY_BT_NEXT_CERT, do_popup, &dp );
+ ObjcAttachFormFunc( form, VERIFY_BT_NEXT_CERT, do_popup, &dp );
+ */
+ while( cont ) {
+ res = FormWindDo( MU_MESAG );
+ cont = false;
+ switch( res ){
+ case VERIFY_BT_ACCEPT:
+ bres = true;
+ break;
+
+ case VERIFY_BT_NEXT_CERT:
+ /* select box clicked or dragged... */
+ cont = true;
+ break;
+
+ case VERIFY_BT_REJECT:
+ bres = false;
+ break;
+
+ case VERIFY_BT_SCROLL_D:
+ cont = true;
+ dp.scrolly += 1;
+ ObjcDrawParent( OC_FORM, form, VERIFY_BOX_DETAILS, 1, 7 | OC_MSG );
+ break;
+
+ case VERIFY_BT_SCROLL_U:
+ cont = true;
+ dp.scrolly -= 1;
+ ObjcDrawParent( OC_FORM, form, VERIFY_BOX_DETAILS, 1, 7 | OC_MSG );
+ break;
+
+ case VERIFY_BT_SCROLL_R:
+ LOG("scroll r!");
+ cont = true;
+ dp.scrollx += 1;
+ if( dp.scrollx > (dp.cols - (272 / 8 )) )
+ dp.scrollx -= 1;
+ ObjcDrawParent( OC_FORM, form, VERIFY_BOX_DETAILS, 1, 7 | OC_MSG);
+ break;
+
+ case VERIFY_BT_SCROLL_L:
+ cont = true;
+ dp.scrollx -= 1;
+ if( dp.scrollx < 0 )
+ dp.scrollx = 0;
+ ObjcDrawParent( OC_FORM, form, VERIFY_BOX_DETAILS, 1, 7 | OC_MSG );
+ break;
+
+ default:
+ break;
+ }
+ }
+ FormWindEnd( );
+ return( bres );
+}
diff --git a/frontends/atari/verify_ssl.h b/frontends/atari/verify_ssl.h
new file mode 100644
index 000000000..b69bc9cfb
--- /dev/null
+++ b/frontends/atari/verify_ssl.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.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 NS_VERIFY_SSL_H_INCLUDED
+#define NS_VERIFY_SSL_H_INCLUDED
+
+bool verify_ssl_form_do( const char * url, const struct ssl_cert_info * cert_infos_n , unsigned long num_certs );
+
+#endif