From d21447d096a320a08b3efb2b8768fad0dcdcfd64 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Thu, 5 May 2016 22:28:51 +0100 Subject: move frontends into sub directory --- frontends/atari/Makefile | 208 ++ frontends/atari/Makefile.defaults | 58 + frontends/atari/about.c | 206 ++ frontends/atari/about.h | 24 + frontends/atari/bitmap.c | 455 ++++ frontends/atari/bitmap.h | 137 ++ frontends/atari/certview.c | 296 +++ frontends/atari/certview.h | 51 + frontends/atari/clipboard.c | 88 + frontends/atari/clipboard.h | 25 + frontends/atari/cookies.c | 220 ++ frontends/atari/cookies.h | 39 + frontends/atari/ctxmenu.c | 321 +++ frontends/atari/ctxmenu.h | 24 + frontends/atari/deskmenu.c | 828 +++++++ frontends/atari/deskmenu.h | 11 + frontends/atari/doc/DejaVu.txt | 99 + frontends/atari/doc/bugs | 4 + frontends/atari/doc/changes.txt | 53 + frontends/atari/doc/faq.txt | 74 + frontends/atari/doc/readme.txt | 125 + frontends/atari/doc/todo.txt | 18 + frontends/atari/download.c | 453 ++++ frontends/atari/download.h | 63 + frontends/atari/encoding.c | 81 + frontends/atari/encoding.h | 35 + frontends/atari/extract.php | 10 + frontends/atari/file.c | 294 +++ frontends/atari/file.h | 27 + frontends/atari/filetype.c | 91 + frontends/atari/filetype.h | 24 + frontends/atari/findfile.c | 144 ++ frontends/atari/findfile.h | 26 + frontends/atari/font.c | 156 ++ frontends/atari/font.h | 25 + frontends/atari/gemtk/aestabs.c | 191 ++ frontends/atari/gemtk/aestabs.h | 56 + frontends/atari/gemtk/dragdrop.c | 515 +++++ frontends/atari/gemtk/dragdrop.h | 4 + frontends/atari/gemtk/gemtk.h | 298 +++ frontends/atari/gemtk/guiwin.c | 1430 ++++++++++++ frontends/atari/gemtk/guiwin.h | 4 + frontends/atari/gemtk/msgbox.c | 110 + frontends/atari/gemtk/msgbox.h | 5 + frontends/atari/gemtk/objc.c | 522 +++++ frontends/atari/gemtk/objc.h | 7 + frontends/atari/gemtk/redrawslots.c | 123 + frontends/atari/gemtk/redrawslots.h | 25 + frontends/atari/gemtk/utils.c | 144 ++ frontends/atari/gemtk/utils.h | 5 + frontends/atari/gemtk/vaproto.c | 170 ++ frontends/atari/gemtk/vaproto.h | 121 + frontends/atari/gui.c | 1217 ++++++++++ frontends/atari/gui.h | 183 ++ frontends/atari/history.c | 191 ++ frontends/atari/history.h | 39 + frontends/atari/hotlist.c | 315 +++ frontends/atari/hotlist.h | 52 + frontends/atari/login.c | 71 + frontends/atari/login.h | 26 + frontends/atari/misc.c | 408 ++++ frontends/atari/misc.h | 106 + frontends/atari/options.h | 48 + frontends/atari/osspec.c | 132 ++ frontends/atari/osspec.h | 45 + frontends/atari/plot/eddi.h | 54 + frontends/atari/plot/eddi.s | 42 + frontends/atari/plot/font_freetype.c | 714 ++++++ frontends/atari/plot/font_freetype.h | 52 + frontends/atari/plot/font_internal.c | 2386 ++++++++++++++++++++ frontends/atari/plot/font_internal.h | 37 + frontends/atari/plot/font_vdi.c | 310 +++ frontends/atari/plot/font_vdi.h | 26 + frontends/atari/plot/fontplot.c | 132 ++ frontends/atari/plot/fontplot.h | 86 + frontends/atari/plot/plot.c | 2247 ++++++++++++++++++ frontends/atari/plot/plot.h | 158 ++ frontends/atari/redrawslots.c | 125 + frontends/atari/redrawslots.h | 54 + frontends/atari/res/blank | 39 + frontends/atari/res/favicon.ico | Bin 0 -> 9862 bytes frontends/atari/res/icons/toolbar/atfact/main.png | Bin 0 -> 12555 bytes .../atari/res/icons/toolbar/atfact/throbber.png | Bin 0 -> 6135 bytes frontends/atari/res/icons/toolbar/default/main.png | Bin 0 -> 46417 bytes frontends/atari/res/icons/toolbar/default/main.xcf | Bin 0 -> 16404 bytes .../atari/res/icons/toolbar/default/throbber.png | Bin 0 -> 20960 bytes .../atari/res/icons/toolbar/default/throbber.xcf | Bin 0 -> 10231 bytes frontends/atari/res/languages | 261 +++ frontends/atari/res/netsurf.rsc | Bin 0 -> 38896 bytes frontends/atari/res/netsurf.rsh | 241 ++ frontends/atari/res/netsurf.rsm | 225 ++ frontends/atari/rootwin.c | 1540 +++++++++++++ frontends/atari/rootwin.h | 97 + frontends/atari/save.h | 22 + frontends/atari/schedule.c | 228 ++ frontends/atari/schedule.h | 48 + frontends/atari/scripts/env-v4e.sh | 7 + frontends/atari/scripts/env-x86.sh | 9 + frontends/atari/search.c | 303 +++ frontends/atari/search.h | 53 + frontends/atari/settings.c | 990 ++++++++ frontends/atari/settings.h | 26 + frontends/atari/statusbar.c | 232 ++ frontends/atari/statusbar.h | 40 + frontends/atari/toolbar.c | 1041 +++++++++ frontends/atari/toolbar.h | 96 + frontends/atari/treeview.c | 794 +++++++ frontends/atari/treeview.h | 124 + frontends/atari/verify_ssl.c | 269 +++ frontends/atari/verify_ssl.h | 24 + 110 files changed, 24488 insertions(+) create mode 100644 frontends/atari/Makefile create mode 100644 frontends/atari/Makefile.defaults create mode 100644 frontends/atari/about.c create mode 100644 frontends/atari/about.h create mode 100644 frontends/atari/bitmap.c create mode 100644 frontends/atari/bitmap.h create mode 100644 frontends/atari/certview.c create mode 100644 frontends/atari/certview.h create mode 100644 frontends/atari/clipboard.c create mode 100644 frontends/atari/clipboard.h create mode 100644 frontends/atari/cookies.c create mode 100644 frontends/atari/cookies.h create mode 100644 frontends/atari/ctxmenu.c create mode 100644 frontends/atari/ctxmenu.h create mode 100644 frontends/atari/deskmenu.c create mode 100644 frontends/atari/deskmenu.h create mode 100755 frontends/atari/doc/DejaVu.txt create mode 100755 frontends/atari/doc/bugs create mode 100755 frontends/atari/doc/changes.txt create mode 100755 frontends/atari/doc/faq.txt create mode 100755 frontends/atari/doc/readme.txt create mode 100755 frontends/atari/doc/todo.txt create mode 100644 frontends/atari/download.c create mode 100644 frontends/atari/download.h create mode 100644 frontends/atari/encoding.c create mode 100644 frontends/atari/encoding.h create mode 100755 frontends/atari/extract.php create mode 100644 frontends/atari/file.c create mode 100644 frontends/atari/file.h create mode 100644 frontends/atari/filetype.c create mode 100644 frontends/atari/filetype.h create mode 100644 frontends/atari/findfile.c create mode 100644 frontends/atari/findfile.h create mode 100644 frontends/atari/font.c create mode 100644 frontends/atari/font.h create mode 100644 frontends/atari/gemtk/aestabs.c create mode 100644 frontends/atari/gemtk/aestabs.h create mode 100755 frontends/atari/gemtk/dragdrop.c create mode 100755 frontends/atari/gemtk/dragdrop.h create mode 100644 frontends/atari/gemtk/gemtk.h create mode 100644 frontends/atari/gemtk/guiwin.c create mode 100644 frontends/atari/gemtk/guiwin.h create mode 100644 frontends/atari/gemtk/msgbox.c create mode 100644 frontends/atari/gemtk/msgbox.h create mode 100644 frontends/atari/gemtk/objc.c create mode 100644 frontends/atari/gemtk/objc.h create mode 100644 frontends/atari/gemtk/redrawslots.c create mode 100644 frontends/atari/gemtk/redrawslots.h create mode 100644 frontends/atari/gemtk/utils.c create mode 100644 frontends/atari/gemtk/utils.h create mode 100644 frontends/atari/gemtk/vaproto.c create mode 100644 frontends/atari/gemtk/vaproto.h create mode 100644 frontends/atari/gui.c create mode 100644 frontends/atari/gui.h create mode 100644 frontends/atari/history.c create mode 100644 frontends/atari/history.h create mode 100644 frontends/atari/hotlist.c create mode 100644 frontends/atari/hotlist.h create mode 100644 frontends/atari/login.c create mode 100644 frontends/atari/login.h create mode 100644 frontends/atari/misc.c create mode 100644 frontends/atari/misc.h create mode 100644 frontends/atari/options.h create mode 100644 frontends/atari/osspec.c create mode 100644 frontends/atari/osspec.h create mode 100644 frontends/atari/plot/eddi.h create mode 100644 frontends/atari/plot/eddi.s create mode 100644 frontends/atari/plot/font_freetype.c create mode 100644 frontends/atari/plot/font_freetype.h create mode 100644 frontends/atari/plot/font_internal.c create mode 100644 frontends/atari/plot/font_internal.h create mode 100644 frontends/atari/plot/font_vdi.c create mode 100644 frontends/atari/plot/font_vdi.h create mode 100644 frontends/atari/plot/fontplot.c create mode 100644 frontends/atari/plot/fontplot.h create mode 100644 frontends/atari/plot/plot.c create mode 100644 frontends/atari/plot/plot.h create mode 100644 frontends/atari/redrawslots.c create mode 100644 frontends/atari/redrawslots.h create mode 100644 frontends/atari/res/blank create mode 100644 frontends/atari/res/favicon.ico create mode 100644 frontends/atari/res/icons/toolbar/atfact/main.png create mode 100644 frontends/atari/res/icons/toolbar/atfact/throbber.png create mode 100644 frontends/atari/res/icons/toolbar/default/main.png create mode 100644 frontends/atari/res/icons/toolbar/default/main.xcf create mode 100644 frontends/atari/res/icons/toolbar/default/throbber.png create mode 100644 frontends/atari/res/icons/toolbar/default/throbber.xcf create mode 100644 frontends/atari/res/languages create mode 100755 frontends/atari/res/netsurf.rsc create mode 100755 frontends/atari/res/netsurf.rsh create mode 100755 frontends/atari/res/netsurf.rsm create mode 100644 frontends/atari/rootwin.c create mode 100644 frontends/atari/rootwin.h create mode 100644 frontends/atari/save.h create mode 100644 frontends/atari/schedule.c create mode 100644 frontends/atari/schedule.h create mode 100755 frontends/atari/scripts/env-v4e.sh create mode 100755 frontends/atari/scripts/env-x86.sh create mode 100644 frontends/atari/search.c create mode 100644 frontends/atari/search.h create mode 100644 frontends/atari/settings.c create mode 100644 frontends/atari/settings.h create mode 100644 frontends/atari/statusbar.c create mode 100644 frontends/atari/statusbar.h create mode 100644 frontends/atari/toolbar.c create mode 100644 frontends/atari/toolbar.h create mode 100644 frontends/atari/treeview.c create mode 100644 frontends/atari/treeview.h create mode 100644 frontends/atari/verify_ssl.c create mode 100644 frontends/atari/verify_ssl.h (limited to 'frontends/atari') 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 + * + * 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 . + */ + +#include +#include +#include +#include +#include +#include + +#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= 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 + * + * 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 . + */ + +#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 + * + * 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 . + */ + +#include +#include +#include +#include +#include + +#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 + * + * 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 . + */ + +/** + * \file + * Atari bitmap handling implementation. + */ + +#ifndef NS_ATARI_BITMAP_H +#define NS_ATARI_BITMAP_H + +#include +#include + +#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 + * + * 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 . + */ + +#include +#include +#include +#include +#include +#include + +#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 + * + * 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 . + */ + +#ifndef CERTVIEW_H_INCLUDED +#define CERTVIEW_H_INCLUDED + +#include +#include +#include + + +#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 + * + * 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 . + * + * Module Description: + * + * + * + */ + +#include +#include +#include +#include +#include +#include +#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 + * + * 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 . + */ + +#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 + * + * 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 . + */ + +#include + +#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 + * + * 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 . + */ + + #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 + * + * 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 . + */ + +#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 + * + * 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 . + */ + +#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 + * + * 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 . + */ + +#include +#include + +#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 + * + * 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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#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 + * + * 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 . + */ + +#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 + * + * 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 . + */ + +#include + +#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 + * + * 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 . + */ + +#ifndef NS_ATARI_ENCODING_H +#define NS_ATARI_ENCODING_H + +#include +#include +#include + +#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 + 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 + * + * 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 . + */ + + +#include +#include +#include +#include +#include +#include + +#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 + * + * 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 . + */ + +#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 + * + * 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 . + */ + +#include +#include +#include +#include + +#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 + * + * 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 . + */ + +#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 + * + * 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 . + */ + +#include + +#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 + * Copyright 2011 Ole Loots + * + * 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 . + */ + +#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 + * + * 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 . + */ + +#include +#include +#include +#include + +#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 + * + * 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 . + */ + +#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 + * + * 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 . + */ + +#include +#include +#include +#include +#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 +#else +#include +#include +#include +#endif + +#include +#include + +#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 +#include + +#include +#include + +#include +#include + + +/* -------------------------------------------------------------------------- */ +/* 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 + * + * 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 . + */ + +#include +#include +#include + +#include +#include +#include + +#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 + * + * 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 . + */ + +#include +#include +#include +#include +#include "gemtk.h" + +#ifndef min +# define min(x,y) ((x + * + * 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 . + * + * Module Description: + * + * AES Object tree tools. + * + */ + +#include +#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 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 + * + * 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 . + */ + +#include +#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; iareas_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; iareas_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 + * + * 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 . + */ + + +#ifndef ATARI_REDRAW_SLOTS_H +#define ATARI_REDRAW_SLOTS_H + +#include + +#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 + * + * 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 . + */ + +#include +#include +#include +#include +#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 +#include +#include +#include +#include +#include +#include +#include + +#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 + * + * 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 . + */ + +/** + * \file + * + * Provides all the mandatory functions prefixed with gui_ for atari + */ + +#include +#include +#include + +#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 + * + * 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 . + */ + +#ifndef NS_ATARI_GUI_H_ +#define NS_ATARI_GUI_H_ + +#include +#include + +#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 + * + * 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 . + */ + +#include +#include + +#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 + * + * 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 . + */ + +#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 + * + * 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 . + */ + +#include +#include +#include +#include +#include +#include + +#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 + * + * 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 . + */ + +#ifndef NS_ATARI_HOTLIST_H +#define NS_ATARI_HOTLIST_H + +#include + +#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 + * + * 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 . + */ + +#include "utils/config.h" +#include +#include +#include +#include +#include + +#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 + * + * 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 . + */ + +#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 + * + * 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 . + */ + +#include +#include +#include +#include +#include + +#include +#include + +#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 + * + * 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 . + */ + +#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 + * + * 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 . + */ + +#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 + * + * 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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 + * + * 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 . + */ + +#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 + * 2008 Vincent Sanders + * 2011 Ole Loots + * 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 . + */ + +#ifdef WITH_FREETYPE_FONT_DRIVER +#include +#include +#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; iadvance.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 + * 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 . + */ + +#ifndef FONT_PLOTTER_FREETYPE +#define FONT_PLOTTER_FREETYPE + +#include +#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 + * Copyright 2011 Ole Loots + * + * 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 . + */ + +#ifdef WITH_INTERNAL_FONT_DRIVER + +#include +#include + +#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 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 + * Copyright 2011 Ole Loots + * + * 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 . + */ + +#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 + * + * 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 . + */ + +#ifdef WITH_VDI_FONT_DRIVER + +#include + +#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; idtor = 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 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 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 + * + * 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 . + */ + +#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 + * + * 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 . + */ + +#include +#include +#include +#include + +#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 + * + * 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 . + */ + +#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 + * + * 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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 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; yg_h; y++ ){ + row = (uint32_t *)(img->pixdata + (img_stride * (y+clip->g_y))); + for( x=0; xg_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, ®ion ); + 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= 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 && istroke_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; ifill_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 + * + * 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 . + */ + +#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 + * + * 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 . + */ + +#include + +#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; iareas_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; iareas_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 + * + * 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 . + */ + + +#ifndef ATARI_REDRAW_SLOTS_H +#define ATARI_REDRAW_SLOTS_H + +#include + +#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 @@ + + + Blankpage + + +

Welcome to NetSurf!

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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 Binary files /dev/null and b/frontends/atari/res/favicon.ico 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 Binary files /dev/null and b/frontends/atari/res/icons/toolbar/atfact/main.png 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 Binary files /dev/null and b/frontends/atari/res/icons/toolbar/atfact/throbber.png 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 Binary files /dev/null and b/frontends/atari/res/icons/toolbar/default/main.png 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 Binary files /dev/null and b/frontends/atari/res/icons/toolbar/default/main.xcf 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 Binary files /dev/null and b/frontends/atari/res/icons/toolbar/default/throbber.png 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 Binary files /dev/null and b/frontends/atari/res/icons/toolbar/default/throbber.xcf 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 Binary files /dev/null and b/frontends/atari/res/netsurf.rsc 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 + * + * 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 . + * + * Module Description: + * + * This File implements the NetSurf Browser window, or passed functionality to + * the appropriate widget's. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#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; isymbol.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; iredraw_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 + * + * 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 . + */ + +#ifndef NS_ATARI_BROWSER_WIN_H +#define NS_ATARI_BROWSER_WIN_H + +#include + +#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 + * + * 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 . + */ + +#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 + * Copyright 2011 Ole Loots + * + * 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 . + */ + +#include +#include +#include + +#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 + * 2012 Ole Loots + * + * 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 . + */ + +#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 + * + * 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 . + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#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 + * + * 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 . + * + */ + +#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 + * + * 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 . + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 + * + * 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 . + * + */ + +#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 + * + * 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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 + * + * 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 . + */ + +#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 + * + * 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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 + * + * 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 . + */ + +#ifndef NS_ATARI_TOOLBAR_H +#define NS_ATARI_TOOLBAR_H + +#include +#include + +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 + * + * 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 . + */ + +#include +#include +#include + +#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 + * + * 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 . + */ + +#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 + * + * 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 . + */ + +#include +#include +#include +#include +#include +#include + +#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; icert_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; inum_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; inum_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 + * + * 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 . + */ + +#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 -- cgit v1.2.3