diff options
author | Vincent Sanders <vince@kyllikki.org> | 2016-05-05 22:28:51 +0100 |
---|---|---|
committer | Vincent Sanders <vince@kyllikki.org> | 2016-05-15 13:44:34 +0100 |
commit | d21447d096a320a08b3efb2b8768fad0dcdcfd64 (patch) | |
tree | 1a83814b7c9e94b2f13c473261f23dd3a17dee64 /frontends/atari | |
parent | 2cbb337756d9af5bda4d594964d446439f602551 (diff) | |
download | netsurf-d21447d096a320a08b3efb2b8768fad0dcdcfd64.tar.gz netsurf-d21447d096a320a08b3efb2b8768fad0dcdcfd64.tar.bz2 |
move frontends into sub directory
Diffstat (limited to 'frontends/atari')
110 files changed, 24488 insertions, 0 deletions
diff --git a/frontends/atari/Makefile b/frontends/atari/Makefile new file mode 100644 index 000000000..60b7f879c --- /dev/null +++ b/frontends/atari/Makefile @@ -0,0 +1,208 @@ +# ---------------------------------------------------------------------------- +# Atari target setup +# ---------------------------------------------------------------------------- + +# !!!IMPORTANT!!! +# On regular m68k-atari-mint installation, these must be set +# manually via env. variables, because the m68k-atari-mint +# toolchain is located in /usr/bin and the wildcard matching +# fails then. So this wildcard matches only works for +# the netsurf environment! +STRIP := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*strip) +STACK := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*stack) +FT2CF := $(GCCSDK_INSTALL_ENV)/bin/freetype-config + +ifeq ($(ATARIARCH),68000) +PRGSUFFIX := 000.app +PKGNAME := ns000.zip +endif + +ifeq ($(ATARIARCH),68020-60) +CFLAGS += -m68020-60 +LDFLAGS += -m68020-60 +PRGSUFFIX := 020.app +PKGNAME := ns020.zip +endif + +ifeq ($(ATARIARCH),v4e) +CFLAGS += -mcpu=5475 +LDFLAGS += -mcpu=5475 +PRGSUFFIX := v4e.app +PKGNAME := nsv4e.zip +endif + +# non-pkgconfig components + +FREETYPE_FONT_CFLAGS := $(shell $(FT2CF) --cflags) -DWITH_FREETYPE_FONT_DRIVER +SPIDERMONKEY_CFLAGS := -DXP_UNIX -DJS_HAS_FILE_OBJECT=0 -DJSOPTION_JIT=0 -DPOSIX_SOURCE -D_BSD_SOURCE + +$(eval $(call feature_enabled,ATARI_FREETYPE_FONT,$(FREETYPE_FONT_CFLAGS),-lfreetype,(Freetype))) +$(eval $(call feature_enabled,ATARI_NETSURF_FONT,-DWITH_INTERNAL_FONT_DRIVER,,(Internal Font))) +$(eval $(call feature_enabled,ATARI_VDI_FONT,-DWITH_VDI_FONT_DRIVER,,(VDI Font))) +$(eval $(call feature_enabled,ATARI_8BPP_SUPPORT,-DWITH_8BPP_SUPPORT,,(Indexed screen format support))) + +$(eval $(call pkg_config_find_and_add,libcares,Cares)) + +CFLAGS += -U__STRICT_ANSI__ -std=c99 -Dsmall -Dnsatari \ + -D_BSD_SOURCE \ + -D_XOPEN_SOURCE=600 \ + -D_POSIX_C_SOURCE=200112L \ + $(shell $(PKG_CONFIG) --cflags openssl ) \ + $(shell $(PKG_CONFIG) --cflags libcurl ) + +LDFLAGS += -lcflib -lcurl +LDFLAGS += -lssl -lcrypto +LDFLAGS += -lz -lHermes -lgem -lm +LDFLAGS += -L$(GCCSDK_INSTALL_ENV)/lib + + +# sources purely for the Atari FreeMiNT build +S_FRONTEND := \ + about.c \ + bitmap.c \ + clipboard.c \ + ctxmenu.c \ + cookies.c \ + certview.c \ + deskmenu.c \ + download.c \ + encoding.c \ + file.c \ + findfile.c \ + filetype.c \ + font.c \ + gui.c \ + hotlist.c \ + history.c \ + login.c \ + misc.c \ + osspec.c \ + redrawslots.c \ + rootwin.c \ + schedule.c \ + search.c \ + statusbar.c \ + settings.c \ + toolbar.c \ + treeview.c \ + plot/plot.c \ + plot/fontplot.c \ + plot/eddi.s \ + plot/font_freetype.c \ + plot/font_internal.c \ + plot/font_vdi.c \ + gemtk/aestabs.c \ + gemtk/dragdrop.c \ + gemtk/guiwin.c \ + gemtk/msgbox.c \ + gemtk/utils.c \ + gemtk/objc.c + + +# This is the final source build list +# Note this is deliberately *not* expanded here as common and image +# are not yet available +SOURCES = $(S_COMMON) $(S_IMAGE) $(S_BROWSER) $(S_FRONTEND) +EXETARGET := ns$(SUBTARGET)$(PRGSUFFIX) + +# ---------------------------------------------------------------------------- +# Install target +# ---------------------------------------------------------------------------- + +ATARI_TARGET_DIR := netsurf/ +ATARI_RES_DIR := $(FRONTEND_RESOURCES_DIR)/ +ATARI_DOC_DIR := $(FRONTEND_SOURCE_DIR)/doc/ +ATARI_FONT_NAME := ttf-bitstream-vera-1.10 +ATARI_FONT_SOURCE_URL := http://ftp.gnome.org/pub/GNOME/sources/ttf-bitstream-vera/1.10/$(ATARI_FONT_NAME).tar.gz +#ATARI_FONT_SOURCE_URL := http://localhost/$(ATARI_FONT_NAME).tar.gz +ATARI_FONT_TMP_DIR := $(DEPROOT)/../ +ATARI_FONT_SOURCE_DIR := $(ATARI_FONT_TMP_DIR)$(ATARI_FONT_NAME)/ +ATARI_GENERIC_RESOURCES := de en it ja +ATARI_RESOURCES := $(addprefix \!NetSurf/Resources/,$(ATARI_GENERIC_RESOURCES)) + +# ---------------------------------------------------------------------------- +# Install target +# ---------------------------------------------------------------------------- + +install-atari: + +# ---------------------------------------------------------------------------- +# Package target +# ---------------------------------------------------------------------------- + +$(ATARI_FONT_TMP_DIR)$(ATARI_FONT_NAME): + $(Q)wget $(ATARI_FONT_SOURCE_URL) -O $(ATARI_FONT_TMP_DIR)$(ATARI_FONT_NAME).tar.gz + tar xfz $(ATARI_FONT_TMP_DIR)/$(ATARI_FONT_NAME).tar.gz -C $(ATARI_FONT_TMP_DIR) + +package-atari: $(ATARI_FONT_TMP_DIR)$(ATARI_FONT_NAME) $(PKGNAME) + $(VQ)echo Creating $(PKGNAME) + +$(PKGNAME): $(EXETARGET) +ifneq ($(strip $(STRIP)),) + $(Q)echo Stripping symbols from $(EXETARGET) with $(STRIP) + $(Q)$(STRIP) $(EXETARGET) +endif +ifneq ($(strip $(STACK)),) + $(Q)$(STACK) -S 256k $(EXETARGET) +endif + $(Q)rm -rf $(ATARI_TARGET_DIR) + $(Q)rm -rf $(PKGNAME) + $(Q)mkdir $(ATARI_TARGET_DIR) + $(Q)mkdir $(ATARI_TARGET_DIR)doc + $(Q)mkdir $(ATARI_TARGET_DIR)downloads + $(Q)mkdir $(ATARI_TARGET_DIR)res + $(Q)mkdir $(ATARI_TARGET_DIR)res/fonts + $(Q)mkdir $(ATARI_TARGET_DIR)res/icons + $(Q)mkdir $(ATARI_TARGET_DIR)res/cache + $(Q)touch $(ATARI_TARGET_DIR)cookies + $(Q)touch $(ATARI_TARGET_DIR)url.db + + $(Q)cp $(ATARI_DOC_DIR)bugs $(ATARI_TARGET_DIR)doc/ + $(Q)cp $(ATARI_DOC_DIR)faq.txt $(ATARI_TARGET_DIR)doc/ + $(Q)cp $(ATARI_DOC_DIR)readme.txt $(ATARI_TARGET_DIR)doc/ + $(Q)cp $(ATARI_DOC_DIR)todo.txt $(ATARI_TARGET_DIR)doc/ + +# GUI resources: + $(Q)cp -r $(ATARI_RESOURCES) $(ATARI_TARGET_DIR)res/ + $(Q)cp $(ATARI_RES_DIR)/netsurf.rsc $(ATARI_TARGET_DIR)res/netsurf.rsc + $(Q)cp $(ATARI_RES_DIR)/languages $(ATARI_TARGET_DIR)res/languages + $(Q)cp $(ATARI_RES_DIR)/icons/toolbar -R $(ATARI_TARGET_DIR)res/icons + $(Q)cp \!NetSurf/Resources/Icons/* -R $(ATARI_TARGET_DIR)res/icons/ + + $(Q)cp \!NetSurf/Resources/netsurf.png,b60 $(ATARI_TARGET_DIR)res/netsurf.png + $(Q)cp \!NetSurf/Resources/AdBlock,f79 $(ATARI_TARGET_DIR)res/adblock.css + $(Q)cp \!NetSurf/Resources/CSS,f79 $(ATARI_TARGET_DIR)res/default.css + $(Q)cp \!NetSurf/Resources/Quirks,f79 $(ATARI_TARGET_DIR)res/quirks.css + $(Q)cp \!NetSurf/Resources/internal.css,f79 $(ATARI_TARGET_DIR)res/internal.css + $(Q)cp \!NetSurf/Resources/SearchEngines $(ATARI_TARGET_DIR)res/search + $(Q)cp \!NetSurf/Resources/ca-bundle $(ATARI_TARGET_DIR)res/cabundle + $(Q)cp \!NetSurf/Resources/ca-bundle $(ATARI_TARGET_DIR)res/cabundle + $(Q)$(SPLIT_MESSAGES) -l en -p atari -f messages resources/FatMessages > $(ATARI_TARGET_DIR)res/messages + $(Q)cp \!NetSurf/Resources/en/welcome.html,faf $(ATARI_TARGET_DIR)res/welcome.html + $(Q)cp \!NetSurf/Resources/en/maps.html,faf $(ATARI_TARGET_DIR)res/maps.html + $(Q)cp \!NetSurf/Resources/en/licence.html,faf $(ATARI_TARGET_DIR)res/licence.html + $(Q)cp \!NetSurf/Resources/en/credits.html,faf $(ATARI_TARGET_DIR)res/credits.html + +# copy "Bitstream Vera" font: + $(Q)cp $(ATARI_FONT_SOURCE_DIR)RELEASENOTES.TXT $(ATARI_TARGET_DIR)res/fonts/ + $(Q)cp $(ATARI_FONT_SOURCE_DIR)README.TXT $(ATARI_TARGET_DIR)res/fonts/ + $(Q)cp $(ATARI_FONT_SOURCE_DIR)COPYRIGHT.TXT $(ATARI_TARGET_DIR)res/fonts/ + + $(Q)cp $(ATARI_FONT_SOURCE_DIR)Vera.ttf $(ATARI_TARGET_DIR)res/fonts/ss.ttf + $(Q)cp $(ATARI_FONT_SOURCE_DIR)VeraBd.ttf $(ATARI_TARGET_DIR)res/fonts/ssb.ttf + $(Q)cp $(ATARI_FONT_SOURCE_DIR)VeraIt.ttf $(ATARI_TARGET_DIR)res/fonts/ssi.ttf + $(Q)cp $(ATARI_FONT_SOURCE_DIR)VeraBI.ttf $(ATARI_TARGET_DIR)res/fonts/ssib.ttf + $(Q)cp $(ATARI_FONT_SOURCE_DIR)VeraSe.ttf $(ATARI_TARGET_DIR)res/fonts/s.ttf + $(Q)cp $(ATARI_FONT_SOURCE_DIR)VeraSeBd.ttf $(ATARI_TARGET_DIR)res/fonts/sb.ttf + $(Q)cp $(ATARI_FONT_SOURCE_DIR)VeraMono.ttf $(ATARI_TARGET_DIR)res/fonts/mono.ttf + $(Q)cp $(ATARI_FONT_SOURCE_DIR)VeraMoBd.ttf $(ATARI_TARGET_DIR)res/fonts/monob.ttf + $(Q)cp $(ATARI_FONT_SOURCE_DIR)VeraMoIt.ttf $(ATARI_TARGET_DIR)res/fonts/cursive.ttf + $(Q)cp $(ATARI_FONT_SOURCE_DIR)VeraMoBI.ttf $(ATARI_TARGET_DIR)res/fonts/fantasy.ttf + + $(Q)cp $(EXETARGET) $(ATARI_TARGET_DIR)$(EXETARGET) + +# zip files + $(Q)zip $(PKGNAME) -9 -r ./$(ATARI_TARGET_DIR) + +# delete temporary folders + $(Q)rm -rf $(ATARI_TARGET_DIR) diff --git a/frontends/atari/Makefile.defaults b/frontends/atari/Makefile.defaults new file mode 100644 index 000000000..b738b48a2 --- /dev/null +++ b/frontends/atari/Makefile.defaults @@ -0,0 +1,58 @@ +# ---------------------------------------------------------------------------- +# Atari-specific options +# ---------------------------------------------------------------------------- + +# Force using glibc internal iconv implementation instead of external libiconv +# Valid options: YES, NO +NETSURF_USE_LIBICONV_PLUG := NO + +# Enable NetSurf's use of librosprite for displaying RISC OS Sprites +# Valid options: YES, NO, AUTO +NETSURF_USE_ROSPRITE := NO + +# Enable NetSurf's use of librsvg in conjunction with Cairo to display SVGs +# Valid options: YES, NO, AUTO +NETSURF_USE_RSVG := AUTO + +# Enable NetSurf's use of libsvgtiny for displaying SVGs +# Valid options: YES, NO, AUTO +NETSURF_USE_NSSVG := AUTO + +# Enable Spidermonkey JavaScript engine +# Valid options: YES, NO +NETSURF_USE_MOZJS := NO + +# Enable building the source object cache filesystem based backing store. +# implementation. +# Valid options: YES, NO +NETSURF_FS_BACKING_STORE := YES + +# enable true type fonts via freetype2 +# Valid options: YES, NO +NETSURF_USE_ATARI_FREETYPE_FONT := YES + +# Enable use of netsurf embedded font +# Valid options: YES, NO +NETSURF_USE_ATARI_NETSURF_FONT := YES + +# Enable VDI Font rendering +# Valid options: YES, NO +NETSURF_USE_ATARI_VDI_FONT := NO + +# Configure support for screen drivers with no true colour mode +# Valid options: YES, NO +NETSURF_USE_ATARI_8BPP_SUPPORT := NO + +# Configure the CPU target +# Valid options: 68000, 68020-60, 5475 (coldfire) +ATARIARCH = 68020-60 + +# enable optimizations +# -O2 is currently broken with m68000 / m68020-60 builds +CFLAGS += -O3 + +# override warning flags removing -Wall +WARNFLAGS = -W -Wundef -Wpointer-arith \ + -Wcast-align -Wwrite-strings -Wstrict-prototypes \ + -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls \ + -Wnested-externs -Wuninitialized -Wl,-t diff --git a/frontends/atari/about.c b/frontends/atari/about.c new file mode 100644 index 000000000..105037aab --- /dev/null +++ b/frontends/atari/about.c @@ -0,0 +1,206 @@ +/* + * Copyright 2013 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <limits.h> +#include <unistd.h> +#include <string.h> +#include <stdlib.h> +#include <stdbool.h> +#include <stdint.h> + +#include "testament.h" +#include "utils/useragent.h" +#include "utils/nsurl.h" +#include "utils/messages.h" +#include "desktop/version.h" +#include "desktop/browser.h" + +#include "curl/curlver.h" + +#include "cflib.h" +#include "atari/gui.h" +#include "atari/misc.h" +#include "atari/plot/plot.h" +#include "atari/gemtk/gemtk.h" +#include "atari/res/netsurf.rsh" +#include "atari/about.h" + +static OBJECT * about_form = NULL; +static char * infocontent; +static char version[32]; +VdiHdl vdihandle; + +static short __CDECL about_userdraw(PARMBLK *parmblock) +{ + short pxy[8]; + short dummy; + short cheight = 8, cwidth = gl_wchar; + char c[2] = {0,0}; + + /* Setup area to the full area...: */ + GRECT area = { + .g_x = parmblock->pb_x, + .g_y = parmblock->pb_y, + .g_w = parmblock->pb_w-8, + .g_h = parmblock->pb_h + }; + + /* Setup clip: */ + GRECT clip = { + .g_x = parmblock->pb_xc, + .g_y = parmblock->pb_yc, + .g_w = parmblock->pb_wc, + .g_h = parmblock->pb_hc + }; + + if(parmblock->pb_currstate == parmblock->pb_prevstate){ + short cur_x, cur_y; + char *content; + int content_len; + + content = (char*)parmblock->pb_parm; + content_len = strlen(content); + cur_x = area.g_x; + cur_y = area.g_y; + + + if(!rc_intersect(&area, &clip)){ + return (0); + } + + pxy[0] = clip.g_x; + pxy[1] = clip.g_y; + pxy[2] = pxy[0] + clip.g_w-1; + pxy[3] = pxy[1] + clip.g_h-1; + vs_clip(vdihandle, 1, pxy); + vst_alignment(vdihandle, 0, 5, &dummy, &dummy); + vst_height(vdihandle, sys_sml_height, &dummy, &dummy, &dummy, &cheight); + vswr_mode(vdihandle, 2); + + for (int i=0; i<content_len; i++) { + if (content[i] == '\n') { + cur_y += cheight; + cur_x = area.g_x; + } else { + if (cur_x >= clip.g_x + && cur_x < (clip.g_x + clip.g_w) + && cur_y > clip.g_y + && cur_y < (clip.g_w + clip.g_h)) { + c[0] = content[i]; + v_gtext(vdihandle, cur_x, cur_y, c); + } + cur_x += cwidth; + } + } + + vs_clip(vdihandle, 0, pxy); + } + return(0); +} + +void atari_about_show(void) +{ + static USERBLK userblk; + short elem = 0; + const char * goto_url = NULL; + nserror nserr; + nsurl *url; + + vdihandle = plot_get_vdi_handle(); + + infocontent = malloc(8000); + memset(infocontent, 0, 8000); + + snprintf(infocontent, 8000, + "Netsurf : %s\n" + "Build ID : %s\n" + "Date : %s\n" + "MiNTLib : %d.%d-%d%s\n" + "GEMLib : %d.%d-%d%s\n" + "CFLib : %d.%d-%d%s\n" + "cURL : %s\n", + user_agent_string(), + WT_REVID, + WT_COMPILEDATE, + __MINTLIB_MAJOR__, __MINTLIB_MINOR__, __MINTLIB_REVISION__, + __MINTLIB_BETATAG__, + __GEMLIB_MAJOR__, __GEMLIB_MINOR__, __GEMLIB_REVISION__, + __GEMLIB_BETATAG__, + __CFLIB_MAJOR__, __CFLIB_MINOR__, __CFLIB_REVISION__, + __CFLIB_BETATAG__, + LIBCURL_VERSION); + + about_form = gemtk_obj_get_tree(ABOUT); + snprintf(version, 32, "%s%s", "NetSurf ", (char*)netsurf_version); + set_string(about_form, ABOUT_LBL_VERSION, version); + + userblk.ub_code = about_userdraw; + userblk.ub_parm = (long) infocontent; + about_form[ABOUT_CONTENT].ob_spec.userblk = &userblk; + + elem = simple_dial(about_form, 0); + switch (elem) { + case ABOUT_CREDITS: + goto_url = "about:credits"; + break; + + case ABOUT_LICENSE: + goto_url = "about:licence"; + break; + }; + + free(infocontent); + + if (goto_url != NULL) { + nserr = nsurl_create(goto_url, &url); + if (nserr == NSERROR_OK) { + nserr = browser_window_create(BW_CREATE_HISTORY, + url, + NULL, + NULL, + NULL); + nsurl_unref(url); + } + if (nserr != NSERROR_OK) { + atari_warn_user(messages_get_errorcode(nserr), 0); + } + } +/* + dlg = open_mdial(about_form, 0); + do { + elem = do_mdial(dlg); + printf ("elem: %d\n", elem); + switch (elem) { + case ABOUT_OK: + close_dlg = true; + break; + + case ABOUT_CREDITS: + close_dlg = true; + break; + + case ABOUT_LICENSE: + close_dlg = true; + break; + } + } while (close_dlg == false); + + close_mdial(dlg); +*/ + +} diff --git a/frontends/atari/about.h b/frontends/atari/about.h new file mode 100644 index 000000000..dff6eaeee --- /dev/null +++ b/frontends/atari/about.h @@ -0,0 +1,24 @@ +/* + * Copyright 2013 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef NS_ATARI_ABOUT_H_INCLUDED +#define NS_ATARI_ABOUT_H_INCLUDED + +void atari_about_show(void); + +#endif // NS_ATARI_ABOUT_H_INCLUDED diff --git a/frontends/atari/bitmap.c b/frontends/atari/bitmap.c new file mode 100644 index 000000000..a159a6659 --- /dev/null +++ b/frontends/atari/bitmap.c @@ -0,0 +1,455 @@ +/* + * Copyright 2010 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <inttypes.h> +#include <sys/types.h> +#include <string.h> +#include <assert.h> +#include <stdlib.h> + +#include "utils/nsoption.h" +#include "utils/log.h" +#include "image/bitmap.h" +#include "desktop/mouse.h" + +#include "atari/bitmap.h" +#include "atari/plot/plot.h" + + +/* + * param bpp bits per pixel, + * param w width of the buffer (in pixel) + * param h height of the buffer (in pixel) + * param flags MFDB_FLAG_NOALLOC | MFDB_FLAG_ZEROMEM | MFDB_FLAG_STAND + * returns size of the fd_addr buffer required or allocated +*/ +int init_mfdb(int bpp, int w, int h, uint32_t flags, MFDB * out ) +{ + int dststride; + dststride = MFDB_STRIDE( w ); + int size = MFDB_SIZE( bpp, dststride, h ); + if( bpp > 0 ) { + if( (flags & MFDB_FLAG_NOALLOC) == 0 ) { + out->fd_addr = malloc( size ); + if( out->fd_addr == NULL ){ + return( 0 ); + } + if( (flags & MFDB_FLAG_ZEROMEM) ){ + memset( out->fd_addr, 0, size ); + } + } + out->fd_stand = (flags & MFDB_FLAG_STAND) ? 1 : 0; + out->fd_nplanes = (short)bpp; + out->fd_r1 = out->fd_r2 = out->fd_r3 = 0; + } else { + memset( out, 0, sizeof(MFDB) ); + } + out->fd_w = dststride; + out->fd_h = h; + out->fd_wdwidth = dststride >> 4; + return( size ); +} + + +/** + * Create a bitmap. + * + * \param w width of image in pixels + * \param h height of image in pixels + * \param bpp number of BYTES per pixel + * \param rowstride linewidth in bytes + * \param state a flag word indicating the initial state + * \param pixdata NULL or an memory address to use as the bitmap pixdata + * \return an opaque struct bitmap, or NULL on memory exhaustion + */ +static void *atari_bitmap_create_ex( int w, int h, short bpp, int rowstride, unsigned int state, void * pixdata ) +{ + struct bitmap * bitmap; + + LOG("width %d (rowstride: %d, bpp: %d), height %d, state %u", w, rowstride, bpp, h, state); + + if( rowstride == 0) { + rowstride = bpp * w; + } + + assert( rowstride >= (w * bpp) ); + bitmap = calloc(1 , sizeof(struct bitmap) ); + if (bitmap) { + if( pixdata == NULL) { + bitmap->pixdata = calloc(1, (rowstride * h)+128); + } + else { + bitmap->pixdata = pixdata; + } + + if (bitmap->pixdata != NULL) { + bitmap->width = w; + bitmap->height = h; + bitmap->opaque = (state & BITMAP_OPAQUE) ? true : false; + bitmap->bpp = bpp; + bitmap->resized = NULL; + bitmap->rowstride = rowstride; + } else { + free(bitmap); + bitmap=NULL; + LOG("Out of memory!"); + } + } + LOG("bitmap %p", bitmap); + return bitmap; +} + + +/* exported interface documented in atari/bitmap.h */ +void *atari_bitmap_create(int w, int h, unsigned int state) +{ + return atari_bitmap_create_ex( w, h, NS_BMP_DEFAULT_BPP, w * NS_BMP_DEFAULT_BPP, state, NULL ); +} + +/** + * The bitmap image has changed, so flush any persistant cache. + * + * \param bitmap a bitmap, as returned by bitmap_create() + */ +static void bitmap_modified(void *bitmap) +{ + struct bitmap *bm = bitmap; + if( bm->resized != NULL ) { + atari_bitmap_destroy( bm->resized ); + bm->resized = NULL; + } + if( bm->converted ){ + if( bm->pixdata != bm->native.fd_addr ){ + free( bm->native.fd_addr ); + } + bm->native.fd_addr = NULL; + bm->converted = false; + } +} + + +/* exported interface documented in atari/bitmap.h */ +void *atari_bitmap_realloc( int w, int h, short bpp, int rowstride, unsigned int state, void * bmp ) +{ + struct bitmap * bitmap = bmp; + int newsize = rowstride * h; + + if( bitmap == NULL ) { + return( NULL ); + } + + assert( bitmap->pixdata != NULL ); + int oldsize = bitmap->rowstride * bitmap->height; + bool doalloc = (state & BITMAP_GROW) ? (newsize > oldsize) : (newsize != oldsize); + if( newsize > oldsize ) + assert( doalloc == true ); + if( doalloc ) { + // TODO: set red band to a specific value and check the red band + // on bitmap_destroy() + bitmap->pixdata = realloc( bitmap->pixdata, newsize + 128 ); + if( bitmap->pixdata == NULL ) + return( NULL ); + } + + if( state & BITMAP_CLEAR ){ + memset( bitmap->pixdata, 0x00, newsize + 128 ); + } + + bitmap->width = w; + bitmap->height = h; + bitmap->bpp = bpp; + bitmap->resized = NULL; + bitmap->rowstride = rowstride; + bitmap_modified( bitmap ); + return( bitmap ); +} + + +/** + * Return a pointer to the pixel data in a bitmap. + * + * \param bitmap a bitmap, as returned by bitmap_create() + * \return pointer to the pixel buffer + * + * The pixel data is packed as BITMAP_FORMAT, possibly with padding at the end + * of rows. The width of a row in bytes is given by bitmap_get_rowstride(). + */ +static unsigned char *bitmap_get_buffer(void *bitmap) +{ + struct bitmap *bm = bitmap; + + if (bitmap == NULL) { + LOG("NULL bitmap!"); + return NULL; + } + + return bm->pixdata; +} + + +/* exported interface documented in atari/bitmap.h */ +size_t atari_bitmap_buffer_size(void *bitmap) +{ + struct bitmap * bm = bitmap; + if( bm == NULL ) + return 0; + return( bm->rowstride * bm->height ); +} + + +/* exported interface documented in atari/bitmap.h */ +size_t atari_bitmap_get_rowstride(void *bitmap) +{ + struct bitmap *bm = bitmap; + + if (bitmap == NULL) { + LOG("NULL bitmap!"); + return 0; + } + return bm->rowstride; +} + + +/* exported interface documented in atari/bitmap.h */ +void atari_bitmap_destroy(void *bitmap) +{ + struct bitmap *bm = bitmap; + + if (bitmap == NULL) { + LOG("NULL bitmap!"); + return; + } + + if( bm->resized != NULL ) { + atari_bitmap_destroy(bm->resized); + } + if( bm->converted && ( bm->native.fd_addr != bm->pixdata ) ) { + free( bm->native.fd_addr ); + } + free(bm->pixdata); + free(bm); +} + + +/** + * Save a bitmap in the platform's native format. + * + * \param bitmap a bitmap, as returned by bitmap_create() + * \param path pathname for file + * \param flags flags controlling how the bitmap is saved. + * \return true on success, false on error and error reported + */ + +static bool bitmap_save(void *bitmap, const char *path, unsigned flags) +{ + return true; +} + + +/** + * Sets whether a bitmap should be plotted opaque + * + * \param bitmap a bitmap, as returned by bitmap_create() + * \param opaque whether the bitmap should be plotted opaque + */ +static void bitmap_set_opaque(void *bitmap, bool opaque) +{ + struct bitmap *bm = bitmap; + + if (bitmap == NULL) { + LOG("NULL bitmap!"); + return; + } + + LOG("setting bitmap %p to %s", bm, opaque ? "opaque" : "transparent"); + bm->opaque = opaque; +} + + +/** + * Tests whether a bitmap has an opaque alpha channel + * + * \param bitmap a bitmap, as returned by bitmap_create() + * \return whether the bitmap is opaque + */ +static bool bitmap_test_opaque(void *bitmap) +{ + int tst; + struct bitmap *bm = bitmap; + + if (bitmap == NULL) { + LOG("NULL bitmap!"); + return false; + } + + if( nsoption_int(atari_transparency) == 0 ){ + return( true ); + } + + tst = bm->width * bm->height; + + while (tst-- > 0) { + if (bm->pixdata[(tst << 2) + 3] != 0xff) { + LOG("bitmap %p has transparency", bm); + return false; + } + } + LOG("bitmap %p is opaque", bm); + return true; +} + + +/* exported interface documented in atari/bitmap.h */ +bool atari_bitmap_get_opaque(void *bitmap) +{ + struct bitmap *bm = bitmap; + + if (bitmap == NULL) { + LOG("NULL bitmap!"); + return false; + } + + return bm->opaque; +} + + +/* exported interface documented in atari/bitmap.h */ +int atari_bitmap_get_width(void *bitmap) +{ + struct bitmap *bm = bitmap; + + if (bitmap == NULL) { + LOG("NULL bitmap!"); + return 0; + } + + return(bm->width); +} + + +/* exported interface documented in atari/bitmap.h */ +int atari_bitmap_get_height(void *bitmap) +{ + struct bitmap *bm = bitmap; + + if (bitmap == NULL) { + LOG("NULL bitmap!"); + return 0; + } + return(bm->height); +} + + +/** + * Gets the number of BYTES per pixel. + */ +static size_t bitmap_get_bpp(void *bitmap) +{ + struct bitmap *bm = bitmap; + return bm->bpp; +} + +/* exported interface documented in atari/bitmap.h */ +bool atari_bitmap_resize(struct bitmap *img, HermesHandle hermes_h, + HermesFormat *fmt, int nw, int nh) +{ + unsigned int state = 0; + short bpp = bitmap_get_bpp( img ); + int stride = atari_bitmap_get_rowstride( img ); + int err; + + if( img->resized != NULL ) { + if( img->resized->width != nw || img->resized->height != nh ) { + atari_bitmap_destroy( img->resized ); + img->resized = NULL; + } else { + /* the bitmap is already resized */ + return(true); + } + } + + /* allocate the mem for resized bitmap */ + if (img->opaque == true) { + state |= BITMAP_OPAQUE; + } + img->resized = atari_bitmap_create_ex( nw, nh, bpp, nw*bpp, state, NULL ); + if( img->resized == NULL ) { + printf("W: %d, H: %d, bpp: %d\n", nw, nh, bpp); + assert(img->resized); + return(false); + } + + /* allocate an converter, only for resizing */ + err = Hermes_ConverterRequest( hermes_h, + fmt, + fmt + ); + if( err == 0 ) { + return(false); + } + + err = Hermes_ConverterCopy( hermes_h, + img->pixdata, + 0, /* x src coord of top left in pixel coords */ + 0, /* y src coord of top left in pixel coords */ + atari_bitmap_get_width( img ), + atari_bitmap_get_height( img ), + stride, /* stride as bytes */ + img->resized->pixdata, + 0, /* x dst coord of top left in pixel coords */ + 0, /* y dst coord of top left in pixel coords */ + nw, nh, + atari_bitmap_get_rowstride(img->resized) /* stride as bytes */ + ); + if( err == 0 ) { + atari_bitmap_destroy( img->resized ); + img->resized = NULL; + return(false); + } + + return(true); +} + +static nserror bitmap_render(struct bitmap *bitmap, struct hlcache_handle *content) +{ + return NSERROR_NOT_IMPLEMENTED; +} + +static struct gui_bitmap_table bitmap_table = { + .create = atari_bitmap_create, + .destroy = atari_bitmap_destroy, + .set_opaque = bitmap_set_opaque, + .get_opaque = atari_bitmap_get_opaque, + .test_opaque = bitmap_test_opaque, + .get_buffer = bitmap_get_buffer, + .get_rowstride = atari_bitmap_get_rowstride, + .get_width = atari_bitmap_get_width, + .get_height = atari_bitmap_get_height, + .get_bpp = bitmap_get_bpp, + .save = bitmap_save, + .modified = bitmap_modified, + .render = bitmap_render, +}; + +struct gui_bitmap_table *atari_bitmap_table = &bitmap_table; + +/* + * Local Variables: + * c-basic-offset:8 + * End: + */ diff --git a/frontends/atari/bitmap.h b/frontends/atari/bitmap.h new file mode 100644 index 000000000..b0fa18069 --- /dev/null +++ b/frontends/atari/bitmap.h @@ -0,0 +1,137 @@ +/* + * Copyright 2010 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * \file + * Atari bitmap handling implementation. + */ + +#ifndef NS_ATARI_BITMAP_H +#define NS_ATARI_BITMAP_H + +#include <gem.h> +#include <Hermes/Hermes.h> + +#define NS_BMP_DEFAULT_BPP 4 + +/* Flags for init_mfdb function: */ +#define MFDB_FLAG_STAND 0x01 +#define MFDB_FLAG_ZEROMEM 0x02 +#define MFDB_FLAG_NOALLOC 0x04 + +#define BITMAP_SHRINK 0 +#define BITMAP_GROW 1024 /* Don't realloc when bitmap size shrinks */ +#define BITMAP_CLEAR 2048 /* Zero bitmap memory */ + + +/** + * Calculates MFDB compatible rowstride (in number of bits) + */ +#define MFDB_STRIDE( w ) (((w & 15) != 0) ? (w | 15)+1 : w) + + +/** + * Calculate size of an mfdb, + * + * \param bpp Bits per pixel. + * \param stride Word aligned rowstride (width) as returned by MFDB_STRIDE, + * \param h Height in pixels. +*/ +#define MFDB_SIZE( bpp, stride, h ) ( ((stride >> 3) * h) * bpp ) + +struct gui_bitmap_table *atari_bitmap_table; + +struct bitmap { + int width; + int height; + uint8_t *pixdata; + bool opaque; + short bpp; /* number of BYTES! per pixel */ + size_t rowstride; + struct bitmap * resized; + MFDB native; + bool converted; +}; + + + +/** + * setup an MFDB struct and allocate memory for it when it is needed. + * + * If bpp == 0, this function assumes that the MFDB shall point to the + * screen and will not allocate any memory (mfdb.fd_addr == 0). + * + * \return 0 when the memory allocation fails (out of memory), + * otherwise it returns the size of the mfdb.fd_addr as number + * of bytes. + */ +int init_mfdb(int bpp, int w, int h, uint32_t flags, MFDB * out ); + +/** + * Create a bitmap. + * + * \param w width of image in pixels + * \param h width of image in pixels + * \param state a flag word indicating the initial state + * \return an opaque struct bitmap, or NULL on memory exhaustion + */ +void *atari_bitmap_create(int w, int h, unsigned int state); + +/** + * Find the width of a pixel row in bytes. + * + * \param bitmap a bitmap, as returned by bitmap_create() + * \return width of a pixel row in the bitmap + */ +size_t atari_bitmap_get_rowstride(void *bitmap); + +/** + * Free a bitmap. + * + * \param bitmap a bitmap, as returned by bitmap_create() + */ +void atari_bitmap_destroy(void *bitmap); + +/** + * Get bitmap width + * + * \param bitmap a bitmap, as returned by bitmap_create() + */ +int atari_bitmap_get_width(void *bitmap); + +/** + * Get bitmap height + * + * \param bitmap a bitmap, as returned by bitmap_create() + */ +int atari_bitmap_get_height(void *bitmap); + +/** + * Gets whether a bitmap should be plotted opaque + * + * \param bitmap a bitmap, as returned by bitmap_create() + */ +bool atari_bitmap_get_opaque(void *bitmap); + +size_t atari_bitmap_buffer_size(void *bitmap); + +bool atari_bitmap_resize(struct bitmap *img, HermesHandle hermes_h, HermesFormat *fmt, int nw, int nh); + +void *atari_bitmap_realloc( int w, int h, short bpp, int rowstride, unsigned int state, void * bmp ); + +#endif diff --git a/frontends/atari/certview.c b/frontends/atari/certview.c new file mode 100644 index 000000000..7f0a29528 --- /dev/null +++ b/frontends/atari/certview.c @@ -0,0 +1,296 @@ +/* + * Copyright 2013 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <ctype.h> +#include <string.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <time.h> + +#include "utils/nsoption.h" +#include "utils/log.h" +#include "utils/messages.h" +#include "utils/utils.h" +#include "content/urldb.h" +#include "content/hlcache.h" +#include "desktop/sslcert_viewer.h" +#include "desktop/core_window.h" + +#include "atari/gui.h" +#include "atari/misc.h" +#include "atari/treeview.h" +#include "atari/certview.h" +#include "atari/findfile.h" +#include "atari/gemtk/gemtk.h" +#include "atari/res/netsurf.rsh" + +extern GRECT desk_area; + + +/* Setup Atari Treeview Callbacks: */ +static nserror atari_sslcert_viewer_init_phase2(struct core_window *cw, + struct core_window_callback_table * default_callbacks); +static void atari_sslcert_viewer_finish(struct core_window *cw); +static void atari_sslcert_viewer_keypress(struct core_window *cw, + uint32_t ucs4); +static void atari_sslcert_viewer_mouse_action(struct core_window *cw, + browser_mouse_state mouse, + int x, int y); +static void atari_sslcert_viewer_draw(struct core_window *cw, int x, + int y, struct rect *clip, + const struct redraw_context *ctx); +static short handle_event(GUIWIN *win, EVMULT_OUT *ev_out, short msg[8]); + +static struct atari_treeview_callbacks atari_sslcert_viewer_treeview_callbacks = { + .init_phase2 = atari_sslcert_viewer_init_phase2, + .finish = atari_sslcert_viewer_finish, + .draw = atari_sslcert_viewer_draw, + .keypress = atari_sslcert_viewer_keypress, + .mouse_action = atari_sslcert_viewer_mouse_action, + .gemtk_user_func = handle_event +}; + +/* static functions */ +static void atari_sslcert_viewer_destroy(struct atari_sslcert_viewer_s * cvwin); + + +static nserror atari_sslcert_viewer_init_phase2(struct core_window *cw, + struct core_window_callback_table *cb_t) +{ + struct atari_sslcert_viewer_s *cvwin; + struct sslcert_session_data *ssl_d; + + cvwin = (struct atari_sslcert_viewer_s *)atari_treeview_get_user_data(cw); + + assert(cvwin); + + ssl_d = cvwin->ssl_session_data; + + assert(ssl_d); + + LOG("cw %p", cw); + + return(sslcert_viewer_init(cb_t, cw, ssl_d)); +} + +static void atari_sslcert_viewer_finish(struct core_window *cw) +{ + struct atari_sslcert_viewer_s *cvwin; + + assert(cw); + + cvwin = (struct atari_sslcert_viewer_s *)atari_treeview_get_user_data(cw); + + /* This will also free the session data: */ + sslcert_viewer_fini(cvwin->ssl_session_data); + + LOG("cw %p", cw); +} + +static void atari_sslcert_viewer_draw(struct core_window *cw, int x, + int y, struct rect *clip, + const struct redraw_context *ctx) +{ + struct atari_sslcert_viewer_s *cvwin; + + assert(cw); + + cvwin = (struct atari_sslcert_viewer_s *)atari_treeview_get_user_data(cw); + + assert(cvwin); + + sslcert_viewer_redraw(cvwin->ssl_session_data, x, y, clip, ctx); +} + +static void atari_sslcert_viewer_keypress(struct core_window *cw, uint32_t ucs4) +{ + struct atari_sslcert_viewer_s *cvwin; + + assert(cw); + + cvwin = (struct atari_sslcert_viewer_s *)atari_treeview_get_user_data(cw); + + LOG("ucs4: %"PRIu32, ucs4); + sslcert_viewer_keypress(cvwin->ssl_session_data, ucs4); +} + +static void atari_sslcert_viewer_mouse_action(struct core_window *cw, + browser_mouse_state mouse, + int x, int y) +{ + struct atari_sslcert_viewer_s *cvwin; + + assert(cw); + + cvwin = (struct atari_sslcert_viewer_s *)atari_treeview_get_user_data(cw); + + sslcert_viewer_mouse_action(cvwin->ssl_session_data, mouse, x, y); +} + + +static short handle_event(GUIWIN *win, EVMULT_OUT *ev_out, short msg[8]) +{ + struct core_window *tv=NULL; + GRECT tb_area; + GUIWIN * gemtk_win; + struct atari_sslcert_viewer_s *cvwin = NULL; + short retval = 0; + OBJECT *toolbar; + + LOG("win %p", win); + + if(ev_out->emo_events & MU_MESAG){ + switch (msg[0]) { + + case WM_TOOLBAR: + toolbar = gemtk_obj_get_tree(TOOLBAR_SSL_CERT); + LOG("CERTVIEWER WM_TOOLBAR"); + tv = (struct core_window*) gemtk_wm_get_user_data(win); + assert(tv); + cvwin = (struct atari_sslcert_viewer_s *) + atari_treeview_get_user_data(tv); + switch (msg[4]) { + + case TOOLBAR_SSL_CERT_TRUSTED: + + if (toolbar[msg[4]].ob_state & OS_SELECTED) { + + } else { + + } + break; + } + + + gemtk_win = atari_treeview_get_gemtk_window(tv); + assert(gemtk_win); + //gemtk_obj_get_tree(TOOLBAR_HOTLIST)[msg[4]].ob_state &= ~OS_SELECTED; + atari_treeview_get_grect(tv, TREEVIEW_AREA_TOOLBAR, &tb_area); + evnt_timer(150); + gemtk_wm_exec_redraw(gemtk_win, &tb_area); + retval = 1; + break; + + case WM_CLOSED: + // TODO set perrmissions + toolbar = gemtk_obj_get_tree(TOOLBAR_SSL_CERT); + tv = (struct core_window*) gemtk_wm_get_user_data(win); + assert(tv); + cvwin = (struct atari_sslcert_viewer_s *) + atari_treeview_get_user_data(tv); + if (toolbar[TOOLBAR_SSL_CERT_TRUSTED].ob_state & OS_SELECTED) { + sslcert_viewer_accept(cvwin->ssl_session_data); + } else { + sslcert_viewer_reject(cvwin->ssl_session_data); + } + atari_sslcert_viewer_destroy(cvwin); + retval = 1; + break; + + default: break; + } + } + + return(retval); +} + +static void atari_sslcert_viewer_init(struct atari_sslcert_viewer_s * cvwin, + struct sslcert_session_data *ssl_d) +{ + assert(cvwin->init == false); + assert(cvwin->window == NULL); + assert(cvwin->tv == NULL); + + int flags = ATARI_TREEVIEW_WIDGETS; + short handle = -1; + OBJECT * tree = gemtk_obj_get_tree(TOOLBAR_SSL_CERT); + assert( tree ); + + handle = wind_create(flags, 0, 0, desk_area.g_w, desk_area.g_h); + cvwin->window = gemtk_wm_add(handle, + GEMTK_WM_FLAG_DEFAULTS, NULL); + if (cvwin->window == NULL ) { + gemtk_msg_box_show(GEMTK_MSG_BOX_ALERT, + "Failed to allocate Treeview:\nCertviewer"); + return; + } + wind_set_str(handle, WF_NAME, (char*)"SSL Certificate"); + gemtk_wm_set_toolbar(cvwin->window, tree, 0, 0); + gemtk_wm_unlink(cvwin->window); + + cvwin->ssl_session_data = ssl_d; + cvwin->tv = atari_treeview_create(cvwin->window, + &atari_sslcert_viewer_treeview_callbacks, + cvwin, flags); + + if (cvwin->tv == NULL) { + /* handle it properly, clean up previous allocs */ + LOG("Failed to allocate treeview"); + return; + } + + cvwin->init = true; +} + +/* + * documented in certview.h + */ +void atari_sslcert_viewer_open(struct sslcert_session_data *ssl_d) +{ + struct atari_sslcert_viewer_s * cvwin; + + cvwin = calloc(1, sizeof(struct atari_sslcert_viewer_s)); + + assert(cvwin); + + atari_sslcert_viewer_init(cvwin, ssl_d); + + if (atari_treeview_is_open(cvwin->tv) == false) { + + GRECT pos; + pos.g_x = desk_area.g_w - desk_area.g_w / 4; + pos.g_y = desk_area.g_y; + pos.g_w = desk_area.g_w / 4; + pos.g_h = desk_area.g_h; + + atari_treeview_open(cvwin->tv, &pos); + } else { + wind_set(gemtk_wm_get_handle(cvwin->window), WF_TOP, 1, 0, + 0, 0); + } +} + + +static void atari_sslcert_viewer_destroy(struct atari_sslcert_viewer_s * cvwin) +{ + assert(cvwin); + assert(cvwin->init); + assert(cvwin->window); + + LOG("cvwin %p", cvwin); + + if (atari_treeview_is_open(cvwin->tv)) + atari_treeview_close(cvwin->tv); + wind_delete(gemtk_wm_get_handle(cvwin->window)); + gemtk_wm_remove(cvwin->window); + cvwin->window = NULL; + atari_treeview_delete(cvwin->tv); + free(cvwin); + LOG("done"); +} diff --git a/frontends/atari/certview.h b/frontends/atari/certview.h new file mode 100644 index 000000000..ff15d8076 --- /dev/null +++ b/frontends/atari/certview.h @@ -0,0 +1,51 @@ +/* + * Copyright 2013 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef CERTVIEW_H_INCLUDED +#define CERTVIEW_H_INCLUDED + +#include <inttypes.h> +#include <sys/types.h> +#include <string.h> + + +#include "assert.h" +#include "utils/nsoption.h" +#include "utils/log.h" +#include "desktop/sslcert_viewer.h" + +struct core_window; + +struct atari_sslcert_viewer_s { + GUIWIN * window; + //struct atari_treeview_window *tv;/*< The hotlist treeview handle. */ + struct core_window *tv; + struct sslcert_session_data *ssl_session_data; + bool init; +}; + +/** + * Initializes and opens an certificate inspector window + * \param ssl_d ssl session data created by sslcert_viewer_create_session_data + * + * The window takes ownership of the session data and free's the memory on exit. + */ +void atari_sslcert_viewer_open(struct sslcert_session_data *ssl_d); + + +#endif // CERTVIEW_H_INCLUDED diff --git a/frontends/atari/clipboard.c b/frontends/atari/clipboard.c new file mode 100644 index 000000000..3464e4bca --- /dev/null +++ b/frontends/atari/clipboard.c @@ -0,0 +1,88 @@ +/* + * Copyright 2013 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Module Description: + * + * + * + */ + +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <stdio.h> +#include <mint/osbind.h> +#include <cflib.h> +#include "atari/clipboard.h" +#include "atari/gemtk/gemtk.h" + + +static int filesize(char * path) +{ + FILE *f; + int fs; + + f = fopen( path, "r+b"); + if(!f) + return(-1); + + fseek(f, 0L, SEEK_END); + fs = ftell(f); + fclose(f); + + return(fs); +} + +int scrap_txt_write(char *str) +{ + scrap_wtxt(str); + + + // Send SC_CHANGED message: + gemtk_send_msg(SC_CHANGED, 0, 2, 0, 0, 0, 0); + + return(0); + +} + +char *scrap_txt_read(void) +{ + char * buf = NULL; + char path[80]; + + if (get_scrapdir (path)) + { + int len; + strcat (path, "scrap.txt"); + len = filesize(path); + if(len > 0){ + int file; + if ((file = (int) Fopen (path, 0)) >= 0) + { + buf = malloc(len); + if(buf){ + len = Fread (file, len, buf); + Fclose (file); + buf[len] = '\0'; + return buf; + } + } + } + } + return buf; +} + diff --git a/frontends/atari/clipboard.h b/frontends/atari/clipboard.h new file mode 100644 index 000000000..aeecc9a5f --- /dev/null +++ b/frontends/atari/clipboard.h @@ -0,0 +1,25 @@ +/* + * Copyright 2010 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef NS_ATARI_CLIPBOARD_H +#define NS_ATARI_CLIPBOARD_H + +int scrap_txt_write(char *str); +char *scrap_txt_read(void); + +#endif diff --git a/frontends/atari/cookies.c b/frontends/atari/cookies.c new file mode 100644 index 000000000..6019b4730 --- /dev/null +++ b/frontends/atari/cookies.c @@ -0,0 +1,220 @@ +/* + * Copyright 2013 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <assert.h> + +#include "utils/log.h" +#include "utils/messages.h" +#include "desktop/mouse.h" +#include "desktop/plotters.h" +#include "desktop/cookie_manager.h" +#include "desktop/core_window.h" + +#include "atari/treeview.h" +#include "atari/cookies.h" +#include "atari/gemtk/gemtk.h" +#include "atari/res/netsurf.rsh" + +extern GRECT desk_area; + +struct atari_cookie_manager_s atari_cookie_manager; + + +/* Setup Atari Treeview Callbacks: */ +static nserror atari_cookie_manager_init_phase2(struct core_window *cw, + struct core_window_callback_table * default_callbacks); +static void atari_cookie_manager_finish(struct core_window *cw); +static void atari_cookie_manager_keypress(struct core_window *cw, + uint32_t ucs4); +static void atari_cookie_manager_mouse_action(struct core_window *cw, + browser_mouse_state mouse, + int x, int y); +static void atari_cookie_manager_draw(struct core_window *cw, int x, + int y, struct rect *clip, + const struct redraw_context *ctx); +static short handle_event(GUIWIN *win, EVMULT_OUT *ev_out, short msg[8]); + +static struct atari_treeview_callbacks atari_cookie_manager_treeview_callbacks = { + .init_phase2 = atari_cookie_manager_init_phase2, + .finish = atari_cookie_manager_finish, + .draw = atari_cookie_manager_draw, + .keypress = atari_cookie_manager_keypress, + .mouse_action = atari_cookie_manager_mouse_action, + .gemtk_user_func = handle_event +}; + + +static nserror +atari_cookie_manager_init_phase2(struct core_window *cw, + struct core_window_callback_table *cb_t) +{ + LOG("cw %p",cw); + return(cookie_manager_init(cb_t, cw)); +} + + +static void +atari_cookie_manager_finish(struct core_window *cw) +{ + LOG("cw %p",cw); + cookie_manager_fini(); +} + + +static void +atari_cookie_manager_draw(struct core_window *cw, + int x, int y, + struct rect *clip, + const struct redraw_context *ctx) +{ + cookie_manager_redraw(x, y, clip, ctx); +} + + +static void +atari_cookie_manager_keypress(struct core_window *cw, uint32_t ucs4) +{ + LOG("ucs4: %"PRIu32, ucs4); + cookie_manager_keypress(ucs4); +} + + +static void +atari_cookie_manager_mouse_action(struct core_window *cw, + browser_mouse_state mouse, + int x, int y) +{ + cookie_manager_mouse_action(mouse, x, y); +} + + + +static short handle_event(GUIWIN *win, EVMULT_OUT *ev_out, short msg[8]) +{ + short retval = 0; + + LOG("win %p", win); + + if (ev_out->emo_events & MU_MESAG) { + switch (msg[0]) { + + case WM_TOOLBAR: + LOG("WM_TOOLBAR"); + break; + + case WM_CLOSED: + atari_cookie_manager_close(); + retval = 1; + break; + + default: break; + } + } + + return(retval); +} + +void atari_cookie_manager_init(void) +{ + if (atari_cookie_manager.init == false) { + + if (atari_cookie_manager.window == NULL) { + int flags = ATARI_TREEVIEW_WIDGETS; + short handle = -1; + OBJECT * tree = gemtk_obj_get_tree(TOOLBAR_COOKIES); + assert( tree ); + + handle = wind_create(flags, 0, 0, desk_area.g_w, desk_area.g_h); + atari_cookie_manager.window = gemtk_wm_add(handle, + GEMTK_WM_FLAG_DEFAULTS, NULL); + if( atari_cookie_manager.window == NULL ) { + gemtk_msg_box_show(GEMTK_MSG_BOX_ALERT, + "Failed to allocate Treeview:\nCookies"); + return; + } + wind_set_str(handle, WF_NAME, (char*)messages_get("Cookies")); + gemtk_wm_set_toolbar(atari_cookie_manager.window, tree, 0, 0); + gemtk_wm_unlink(atari_cookie_manager.window); + + atari_cookie_manager.tv = atari_treeview_create( + atari_cookie_manager.window, + &atari_cookie_manager_treeview_callbacks, + NULL, flags); + + if (atari_cookie_manager.tv == NULL) { + /* handle it properly, clean up previous allocs */ + LOG("Failed to allocate treeview"); + return; + } + + } else { + + } + } + atari_cookie_manager.init = true; +} + +void atari_cookie_manager_open(void) +{ + assert(atari_cookie_manager.init); + + if (atari_treeview_is_open(atari_cookie_manager.tv) == false) { + + GRECT pos; + pos.g_x = desk_area.g_w - desk_area.g_w / 4; + pos.g_y = desk_area.g_y; + pos.g_w = desk_area.g_w / 4; + pos.g_h = desk_area.g_h; + + atari_treeview_open(atari_cookie_manager.tv, &pos); + } else { + wind_set(gemtk_wm_get_handle(atari_cookie_manager.window), WF_TOP, 1, 0, + 0, 0); + } +} + + +void atari_cookie_manager_close(void) +{ + atari_treeview_close(atari_cookie_manager.tv); +} + + +void atari_cookie_manager_destroy(void) +{ + if( atari_cookie_manager.init == false) { + return; + } + if( atari_cookie_manager.window != NULL ) { + if (atari_treeview_is_open(atari_cookie_manager.tv)) + atari_cookie_manager_close(); + wind_delete(gemtk_wm_get_handle(atari_cookie_manager.window)); + gemtk_wm_remove(atari_cookie_manager.window); + atari_cookie_manager.window = NULL; + atari_treeview_delete(atari_cookie_manager.tv); + atari_cookie_manager.init = false; + } + LOG("done"); + +} + + +void atari_cookie_manager_redraw(void) +{ + atari_treeview_redraw(atari_cookie_manager.tv); +} diff --git a/frontends/atari/cookies.h b/frontends/atari/cookies.h new file mode 100644 index 000000000..3649c8c60 --- /dev/null +++ b/frontends/atari/cookies.h @@ -0,0 +1,39 @@ +/* + * Copyright 2013 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + #ifndef NS_ATARI_COOKIE_MANAGER_H + #define NS_ATARI_COOKIE_MANAGER_H + +struct core_window; + +struct atari_cookie_manager_s { + GUIWIN * window; + //struct atari_treeview_window * tv;/*< The hotlist treeview handle. */ + struct core_window *tv; + bool init; +}; + +extern struct atari_cookie_manager_s atari_cookie_manager; + +void atari_cookie_manager_init(void); +void atari_cookie_manager_open(void); +void atari_cookie_manager_close(void); +void atari_cookie_manager_destroy(void); +void atari_cookie_manager_redraw(void); + +#endif diff --git a/frontends/atari/ctxmenu.c b/frontends/atari/ctxmenu.c new file mode 100644 index 000000000..0343b20c7 --- /dev/null +++ b/frontends/atari/ctxmenu.c @@ -0,0 +1,321 @@ +/* + * Copyright 2010 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "utils/log.h" +#include "utils/messages.h" +#include "utils/nsoption.h" +#include "desktop/browser.h" +#include "desktop/textinput.h" +#include "content/hlcache.h" + +#include "atari/gui.h" +#include "atari/misc.h" +#include "atari/rootwin.h" +#include "atari/clipboard.h" +#include "atari/gemtk/gemtk.h" +#include "atari/res/netsurf.rsh" +#include "atari/ctxmenu.h" + + +#define CNT_INVALID 0 +#define CNT_BROWSER 64 +#define CNT_HREF 128 +#define CNT_SELECTION 256 +#define CNT_INTERACTIVE 512 +#define CNT_IMG 1024 + +bool gui_window_get_scroll(struct gui_window *w, int *sx, int *sy); + +struct s_context_info { + unsigned long flags; + struct browser_window_features ccdata; +}; + +struct s_context_info ctxinfo; + +static struct s_context_info * get_context_info( struct gui_window * gw, short mx, short my ) +{ + hlcache_handle *h; + GRECT area; + struct browser_window * bw = gw->browser->bw; + int sx, sy; + + h = browser_window_get_content(bw); + ctxinfo.flags = 0; + + window_get_grect(gw->root, BROWSER_AREA_CONTENT, &area); + if (POINT_WITHIN(mx, my, area)) { + + mx -= area.g_x; + my -= area.g_y; + + if (browser_window_has_content(bw) == false || + content_get_type(h) != CONTENT_HTML){ + return(&ctxinfo); + } + + ctxinfo.flags |= CNT_BROWSER; + + gui_window_get_scroll(gw, &sx, &sy); + + browser_window_get_features( gw->browser->bw, mx+sx, my+sy, + &ctxinfo.ccdata); + + if( ctxinfo.ccdata.link ){ + ctxinfo.flags |= CNT_HREF; + } + if( ctxinfo.ccdata.object) { + if( content_get_type(ctxinfo.ccdata.object) == CONTENT_IMAGE ){ + ctxinfo.flags |= CNT_IMG; + } + } + if ( ctxinfo.ccdata.form_features == CTX_FORM_TEXT ) + ctxinfo.flags |= (CNT_INTERACTIVE | CNT_SELECTION); + } + + return(&ctxinfo); + + +} + +/*** + * Generates an unique filename for temp. files + * The generated filename includes the path. + * If TMPDIR environmenrt vairable is set, this will be used as path, + * otherwise U:\tmp\ + * \param prefix + * \param sufffix + * \return pointer to static buffer owned by get_tmpfilename() + */ +static char * get_tmpfilename(const char * prefix, const char * suffix) +{ + int i=0; + static char tmpfilename[PATH_MAX]; + char * tmpdir; + const char * tmp_path_suffix = ""; + + // TODO: make function public? + tmpdir = getenv("TMPDIR"); + if(tmpdir == NULL){ + tmpdir = (char*)"u:\\tmp\\"; + } + + if(tmpdir[strlen(tmpdir)-1] != '\\'){ + tmp_path_suffix = "\\"; + } + + do{ + /* generate a new filename: */ + snprintf(tmpfilename, PATH_MAX, "%s%s%s%d%s", tmpdir, + tmp_path_suffix, prefix, i++, suffix); + /* check with cflib: */ + } while(file_exists(tmpfilename)); + + return(tmpfilename); +} + +//TODO: do not open popup for gui_window, but for a rootwin? +void context_popup(struct gui_window * gw, short x, short y) +{ + +#define POP_FIRST_ITEM POP_CTX_CUT_SEL +#define POP_LAST_ITEM POP_CTX_SAVE_LINK_AS + + OBJECT * pop; + int choice; + struct s_context_info * ctx; + unsigned long size; + const char * data; + FILE * fp_tmpfile; + char cmdline[128]; + /* skip first byte, which must hold length of commandline: */ + char * tempfile = &cmdline[1]; + char * editor; + MENU pop_menu, me_data; + + pop = gemtk_obj_get_tree( POP_CTX ); + if (pop == NULL) + return; + ctx = get_context_info(gw, x, y); + + /* + Disable all items by default: + */ + for( choice = POP_FIRST_ITEM; choice<=POP_LAST_ITEM; choice++ ){ + SET_BIT(pop[ choice ].ob_state, OS_DISABLED, 1); + } + + if( ctx->flags & CNT_INTERACTIVE ){ + SET_BIT(pop[ POP_CTX_PASTE_SEL ].ob_state, OS_DISABLED, 0); + } + + if( (ctx->flags & CNT_BROWSER) ){ + SET_BIT(pop[ POP_CTX_SELECT_ALL ].ob_state, OS_DISABLED, 0); + SET_BIT(pop[ POP_CTX_COPY_SEL ].ob_state, OS_DISABLED, 0); + SET_BIT(pop[ POP_CTX_VIEW_SOURCE ].ob_state, OS_DISABLED, 0); + } + + if( ctx->flags & CNT_HREF ){ + SET_BIT(pop[ POP_CTX_COPY_LINK ].ob_state, OS_DISABLED, 0); + SET_BIT(pop[ POP_CTX_OPEN_NEW ].ob_state, OS_DISABLED, 0); + SET_BIT(pop[ POP_CTX_SAVE_LINK_AS ].ob_state, OS_DISABLED, 0); + } + + if( ctx->flags & CNT_IMG ){ + SET_BIT(pop[ POP_CTX_SAVE_AS ].ob_state, OS_DISABLED, 0); + SET_BIT(pop[ POP_CTX_COPY_URL ].ob_state, OS_DISABLED, 0); + SET_BIT(pop[ POP_CTX_OPEN_NEW ].ob_state, OS_DISABLED, 0); + } + + // point mn_tree tree to states popup: + pop_menu.mn_tree = gemtk_obj_get_tree(POP_CTX); + pop_menu.mn_menu = 0; + pop_menu.mn_item = POP_CTX_CUT_SEL; + pop_menu.mn_scroll = SCROLL_NO; + pop_menu.mn_keystate = 0; + + menu_popup(&pop_menu, x, y, &me_data); + choice = me_data.mn_item; + + switch( choice ){ + case POP_CTX_COPY_SEL: + browser_window_key_press(gw->browser->bw, NS_KEY_COPY_SELECTION); + break; + + case POP_CTX_CUT_SEL: + browser_window_key_press(gw->browser->bw, NS_KEY_CUT_SELECTION); + break; + + case POP_CTX_PASTE_SEL: + browser_window_key_press(gw->browser->bw, NS_KEY_PASTE); + break; + + case POP_CTX_SELECT_ALL: + browser_window_key_press(gw->browser->bw, NS_KEY_SELECT_ALL); + break; + + case POP_CTX_SAVE_AS: + if (ctx->ccdata.object != NULL) { + if( hlcache_handle_get_url(ctx->ccdata.object) != NULL ) { + browser_window_navigate( + gw->browser->bw, + hlcache_handle_get_url(ctx->ccdata.object), + browser_window_get_url(gw->browser->bw), + BW_NAVIGATE_DOWNLOAD, + NULL, + NULL, + NULL + ); + } + } + + case POP_CTX_SAVE_LINK_AS: + if (ctx->ccdata.link != NULL) { + nserror error; + + error = browser_window_navigate( + gw->browser->bw, + ctx->ccdata.link, + browser_window_get_url(gw->browser->bw), + BW_NAVIGATE_DOWNLOAD, + NULL, + NULL, + NULL); + + if (error != NSERROR_OK) { + atari_warn_user(messages_get_errorcode(error), 0); + } + } + + break; + + case POP_CTX_COPY_URL: + if ((ctx->flags & CNT_IMG) && (ctx->ccdata.object != NULL)) { + if( hlcache_handle_get_url(ctx->ccdata.object) != NULL ){ + scrap_txt_write((char*)nsurl_access( + hlcache_handle_get_url(ctx->ccdata.object))); + } + } + break; + + case POP_CTX_COPY_LINK: + if ((ctx->flags & CNT_HREF) && + (ctx->ccdata.link != NULL)) { + scrap_txt_write((char*)nsurl_access(ctx->ccdata.link)); + } + break; + + case POP_CTX_OPEN_NEW: + if ((ctx->flags & CNT_HREF) && + (ctx->ccdata.link != NULL)) { + nserror error; + + error = browser_window_create( + BW_CREATE_HISTORY | BW_CREATE_CLONE, + ctx->ccdata.link, + browser_window_get_url(gw->browser->bw), + gw->browser->bw, + NULL); + if (error != NSERROR_OK) { + atari_warn_user(messages_get_errorcode(error), 0); + } + } + break; + + case POP_CTX_VIEW_SOURCE: + editor = nsoption_charp(atari_editor); + if (editor != NULL && strlen(editor)>0) { + data = content_get_source_data(browser_window_get_content(gw->browser->bw), + &size); + if (size > 0 && data != NULL){ + snprintf(tempfile, 127, "%s", get_tmpfilename("ns-", ".html")); + /* the GEMDOS cmdline contains the length of the commandline + in the first byte: */ + cmdline[0] = (unsigned char)strlen(tempfile); + LOG("Creating temporay source file: %s\n", tempfile); + fp_tmpfile = fopen(tempfile, "w"); + if (fp_tmpfile != NULL){ + fwrite(data, size, 1, fp_tmpfile); + fclose(fp_tmpfile); + + // Send SH_WDRAW to notify files changed: + gemtk_send_msg(SH_WDRAW, 0, -1, 0, 0, 0, 0); + + // start application: + if(strlen(tempfile)<=125){ + shel_write(1, 1, 1, editor, cmdline); + } + } else { + printf("Could not open temp file: %s!\n", tempfile ); + } + + } else { + LOG("Invalid content!"); + } + } else { + form_alert(0, "[1][Set option \"atari_editor\".][OK]"); + } + break; + + default: break; + } + +#undef POP_FIRST_ITEM +#undef POP_LAST_ITEM + +} diff --git a/frontends/atari/ctxmenu.h b/frontends/atari/ctxmenu.h new file mode 100644 index 000000000..73a96637a --- /dev/null +++ b/frontends/atari/ctxmenu.h @@ -0,0 +1,24 @@ +/* + * Copyright 2012 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef CTXMENU_H_INCLUDED +#define CTXMENU_H_INCLUDED + +void context_popup( struct gui_window * gw, short x, short y ); + +#endif // CTXMENU_H_INCLUDED diff --git a/frontends/atari/deskmenu.c b/frontends/atari/deskmenu.c new file mode 100644 index 000000000..723835873 --- /dev/null +++ b/frontends/atari/deskmenu.c @@ -0,0 +1,828 @@ +/* + * Copyright 2010 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <cflib.h> + +#include "utils/log.h" +#include "utils/nsurl.h" +#include "utils/messages.h" +#include "utils/nsoption.h" +#include "desktop/browser.h" +#include "desktop/save_complete.h" +#include "desktop/textinput.h" + +#include "atari/res/netsurf.rsh" +#include "atari/gemtk/gemtk.h" +#include "atari/deskmenu.h" +#include "atari/hotlist.h" +#include "atari/history.h" +#include "atari/cookies.h" +#include "atari/toolbar.h" +#include "atari/settings.h" +#include "atari/misc.h" +#include "atari/gui.h" +#include "atari/findfile.h" +#include "atari/about.h" +#include "atari/plot/plot.h" +#include "atari/rootwin.h" + +typedef void __CDECL (*menu_evnt_func)(short item, short title, void * data); + +struct s_accelerator +{ + char ascii; /* either ascii or */ + long keycode; /* normalised keycode is valid */ + short mod; /* shift / ctrl etc */ +}; + +struct s_menu_item_evnt { + short title; /* to which menu this item belongs */ + short rid; /* resource ID */ + menu_evnt_func menu_func; /* click handler */ + struct s_accelerator accel; /* accelerator info */ + char * menustr; +}; + +static void register_menu_str(struct s_menu_item_evnt * mi); +//static void __CDECL evnt_menu(WINDOW * win, short buff[8]); + +extern void *h_gem_rsrc; +extern bool html_redraw_debug; +extern struct gui_window * input_window; +extern char options[PATH_MAX]; +extern const char * option_homepage_url; +extern int option_window_width; +extern int option_window_height; +extern int option_window_x; +extern int option_window_y; + +static OBJECT * h_gem_menu; + + +/* Zero based resource tree ids: */ +#define T_ABOUT 0 +#define T_FILE MAINMENU_T_FILE - MAINMENU_T_FILE + 1 +#define T_EDIT MAINMENU_T_EDIT - MAINMENU_T_FILE + 1 +#define T_VIEW MAINMENU_T_VIEW - MAINMENU_T_FILE + 1 +#define T_NAV MAINMENU_T_NAVIGATE - MAINMENU_T_FILE + 1 +#define T_UTIL MAINMENU_T_UTIL - MAINMENU_T_FILE + 1 +#define T_HELP MAINMENU_T_NAVIGATE - MAINMENU_T_FILE + 1 +/* Count of the above defines: */ +#define NUM_MENU_TITLES 7 + + +static void __CDECL menu_about(short item, short title, void *data); +static void __CDECL menu_new_win(short item, short title, void *data); +static void __CDECL menu_open_url(short item, short title, void *data); +static void __CDECL menu_open_file(short item, short title, void *data); +static void __CDECL menu_close_win(short item, short title, void *data); +static void __CDECL menu_save_page(short item, short title, void *data); +static void __CDECL menu_quit(short item, short title, void *data); +static void __CDECL menu_cut(short item, short title, void *data); +static void __CDECL menu_copy(short item, short title, void *data); +static void __CDECL menu_paste(short item, short title, void *data); +static void __CDECL menu_find(short item, short title, void *data); +static void __CDECL menu_choices(short item, short title, void *data); +static void __CDECL menu_stop(short item, short title, void *data); +static void __CDECL menu_reload(short item, short title, void *data); +static void __CDECL menu_dec_scale(short item, short title, void *data); +static void __CDECL menu_inc_scale(short item, short title, void *data); +static void __CDECL menu_toolbars(short item, short title, void *data); +static void __CDECL menu_savewin(short item, short title, void *data); +static void __CDECL menu_debug_render(short item, short title, void *data); +static void __CDECL menu_fg_images(short item, short title, void *data); +static void __CDECL menu_bg_images(short item, short title, void *data); +static void __CDECL menu_back(short item, short title, void *data); +static void __CDECL menu_forward(short item, short title, void *data); +static void __CDECL menu_home(short item, short title, void *data); +static void __CDECL menu_lhistory(short item, short title, void *data); +static void __CDECL menu_ghistory(short item, short title, void *data); +static void __CDECL menu_add_bookmark(short item, short title, void *data); +static void __CDECL menu_bookmarks(short item, short title, void *data); +static void __CDECL menu_cookies(short item, short title, void *data); +static void __CDECL menu_vlog(short item, short title, void *data); +static void __CDECL menu_help_content(short item, short title, void *data); + +struct s_menu_item_evnt menu_evnt_tbl[] = +{ + {T_ABOUT,MAINMENU_M_ABOUT, menu_about, {0,0,0}, NULL }, + {T_FILE, MAINMENU_M_NEWWIN, menu_new_win, {0,0,0}, NULL}, + {T_FILE, MAINMENU_M_OPENURL, menu_open_url, {'G',0,K_CTRL}, NULL}, + {T_FILE, MAINMENU_M_OPENFILE, menu_open_file, {'O',0,K_CTRL}, NULL}, + {T_FILE, MAINMENU_M_CLOSEWIN, menu_close_win, {0,0,0}, NULL}, + {T_FILE, MAINMENU_M_SAVEPAGE, menu_save_page, {0,NK_F3,0}, NULL}, + {T_FILE, MAINMENU_M_QUIT, menu_quit, {'Q',0,K_CTRL}, NULL}, + {T_EDIT, MAINMENU_M_CUT, menu_cut, {'X',0,K_CTRL}, NULL}, + {T_EDIT, MAINMENU_M_COPY, menu_copy, {'C',0,K_CTRL}, NULL}, + {T_EDIT, MAINMENU_M_PASTE, menu_paste, {'V',0,K_CTRL}, NULL}, + {T_EDIT, MAINMENU_M_FIND, menu_find, {0,NK_F4,0}, NULL}, + {T_VIEW, MAINMENU_M_RELOAD, menu_reload, {0,NK_F5,0}, NULL}, + {T_VIEW, MAINMENU_INC_SCALE, menu_inc_scale, {'+',0,K_CTRL}, NULL}, + {T_VIEW, MAINMENU_DEC_SCALE, menu_dec_scale, {'-',0,K_CTRL}, NULL}, + {T_VIEW, MAINMENU_M_TOOLBARS, menu_toolbars, {0,NK_F1,K_CTRL}, NULL}, + {T_VIEW, MAINMENU_M_SAVEWIN, menu_savewin, {0,0,0}, NULL}, + {T_VIEW, MAINMENU_M_DEBUG_RENDER, menu_debug_render, {0,0,0}, NULL}, + {T_VIEW, MAINMENU_M_FG_IMAGES, menu_fg_images, {0,0,0}, NULL}, + {T_VIEW, MAINMENU_M_BG_IMAGES, menu_bg_images, {0,0,0}, NULL}, + {T_VIEW, MAINMENU_M_STOP, menu_stop, {0,NK_ESC,K_ALT}, NULL}, + {T_NAV, MAINMENU_M_BACK, menu_back, {0,NK_LEFT,K_ALT}, NULL}, + {T_NAV, MAINMENU_M_FORWARD, menu_forward, {0,NK_RIGHT,K_ALT}, NULL}, + {T_NAV, MAINMENU_M_HOME, menu_home, {0,0,0}, NULL}, + {T_UTIL, MAINMENU_M_LHISTORY,menu_lhistory, {0,NK_F7,0}, NULL}, + {T_UTIL, MAINMENU_M_GHISTORY, menu_ghistory, {0,NK_F7,K_CTRL}, NULL}, + {T_UTIL, MAINMENU_M_ADD_BOOKMARK, menu_add_bookmark, {'D',0,K_CTRL}, NULL}, + {T_UTIL, MAINMENU_M_BOOKMARKS, menu_bookmarks, {0,NK_F6,0}, NULL}, + {T_UTIL, MAINMENU_M_COOKIES, menu_cookies, {0,0,0}, NULL}, + {T_UTIL, MAINMENU_M_CHOICES, menu_choices, {0,0,0}, NULL}, + {T_UTIL, MAINMENU_M_VLOG, menu_vlog, {'V',0,K_ALT}, NULL}, + {T_HELP, MAINMENU_M_HELP_CONTENT, menu_help_content, {0,NK_F1,0}, NULL}, + {-1, -1, NULL,{0,0,0}, NULL } +}; + + +/* + static void __CDECL evnt_menu(WINDOW * win, short buff[8]) + { + int title = buff[3]; + INT16 x,y; + char *str; + struct gui_window * gw = window_list; + int i=0; + + deskmenu_dispatch_item(buff[3], buff[4]); + } +*/ + +/* + Menu item event handlers: +*/ + +static void __CDECL menu_about(short item, short title, void *data) +{ + /* + nsurl *url; + nserror error; + char buf[PATH_MAX]; + + LOG("%s", __FUNCTION__); + strcpy((char*)&buf, "file://"); + strncat((char*)&buf, (char*)"./doc/README.TXT", + PATH_MAX - (strlen("file://")+1) ); + + error = nsurl_create(buf, &url); + if (error == NSERROR_OK) { + error = browser_window_create(BW_CREATE_HISTORY, + url, + NULL, + NULL, + NULL); + nsurl_unref(url); + } + if (error != NSERROR_OK) { + atari_warn_user(messages_get_errorcode(error), 0); + } + */ + atari_about_show(); +} + +static void __CDECL menu_new_win(short item, short title, void *data) +{ + nsurl *url; + nserror error; + const char *addr; + + LOG("%s", __FUNCTION__); + + if (nsoption_charp(homepage_url) != NULL) { + addr = nsoption_charp(homepage_url); + } else { + addr = NETSURF_HOMEPAGE; + } + + /* create an initial browser window */ + error = nsurl_create(addr, &url); + if (error == NSERROR_OK) { + error = browser_window_create(BW_CREATE_HISTORY, + url, + NULL, + NULL, + NULL); + nsurl_unref(url); + + } + if (error != NSERROR_OK) { + atari_warn_user(messages_get_errorcode(error), 0); + } +} + +static void __CDECL menu_open_url(short item, short title, void *data) +{ + struct gui_window * gw; + struct browser_window * bw ; + LOG("%s", __FUNCTION__); + + gw = input_window; + if( gw == NULL ) { + browser_window_create(BW_CREATE_HISTORY, + NULL, + NULL, + NULL, + &bw); + } +} + +static void __CDECL menu_open_file(short item, short title, void *data) +{ + + LOG("%s", __FUNCTION__); + + const char * filename = file_select(messages_get("OpenFile"), ""); + if( filename != NULL ){ + char * urltxt = local_file_to_url( filename ); + if( urltxt ){ + nsurl *url; + nserror error; + + error = nsurl_create(urltxt, &url); + if (error == NSERROR_OK) { + error = browser_window_create(BW_CREATE_HISTORY, + url, + NULL, + NULL, + NULL); + nsurl_unref(url); + + } + if (error != NSERROR_OK) { + atari_warn_user(messages_get_errorcode(error), 0); + } + free( urltxt ); + } + } +} + +static void __CDECL menu_close_win(short item, short title, void *data) +{ + LOG("%s", __FUNCTION__); + if( input_window == NULL ) + return; + gui_window_destroy( input_window ); +} + +static void __CDECL menu_save_page(short item, short title, void *data) +{ + LOG("%s", __FUNCTION__); + static bool init = true; + bool is_folder=false; + const char * path; + + if( !input_window ) + return; + + if( init ){ + init = false; + save_complete_init(); + } + + do { + // TODO: localize string + path = file_select("Select folder", ""); + if (path) + is_folder = is_dir(path); + } while ((is_folder == false) && (path != NULL)); + + if( path != NULL ){ + save_complete(browser_window_get_content( + input_window->browser->bw), path, NULL); + } + +} + +static void __CDECL menu_quit(short item, short title, void *data) +{ + short buff[8]; + memset( &buff, 0, sizeof(short)*8 ); + LOG("%s", __FUNCTION__); + gemtk_wm_send_msg(NULL, AP_TERM, 0, 0, 0, 0); +} + +static void __CDECL menu_cut(short item, short title, void *data) +{ + if( input_window != NULL ) + browser_window_key_press( input_window->browser->bw, NS_KEY_CUT_SELECTION); +} + +static void __CDECL menu_copy(short item, short title, void *data) +{ + LOG("%s", __FUNCTION__); + if( input_window != NULL ) + browser_window_key_press( input_window->browser->bw, NS_KEY_COPY_SELECTION); +} + +static void __CDECL menu_paste(short item, short title, void *data) +{ + LOG("%s", __FUNCTION__); + if( input_window != NULL ) + browser_window_key_press( input_window->browser->bw, NS_KEY_PASTE); +} + +static void __CDECL menu_find(short item, short title, void *data) +{ + LOG("%s", __FUNCTION__); + if (input_window != NULL) { + if (input_window->search) { + window_close_search(input_window->root); + } + else { + window_open_search(input_window->root, true); + } + } +} + +static void __CDECL menu_choices(short item, short title, void *data) +{ + LOG("%s", __FUNCTION__); + open_settings(); +} + +static void __CDECL menu_stop(short item, short title, void *data) +{ + LOG("%s", __FUNCTION__); + if( input_window == NULL ) + return; + + assert(input_window && input_window->root); + toolbar_stop_click(input_window->root->toolbar); + +} + +static void __CDECL menu_reload(short item, short title, void *data) +{ + if(input_window == NULL) + return; + toolbar_reload_click(input_window->root->toolbar); + LOG("%s", __FUNCTION__); +} + + +static void __CDECL menu_inc_scale(short item, short title, void *data) +{ + if(input_window == NULL) + return; + + browser_window_set_scale(input_window->browser->bw, + browser_window_get_scale(input_window->browser->bw) + 0.25, + true); +} + + +static void __CDECL menu_dec_scale(short item, short title, void *data) +{ + if(input_window == NULL) + return; + + browser_window_set_scale(input_window->browser->bw, + browser_window_get_scale(input_window->browser->bw) - 0.25, + true); +} + + + +static void __CDECL menu_toolbars(short item, short title, void *data) +{ + static int state = 0; + LOG("%s", __FUNCTION__); + if( input_window != null && input_window->root->toolbar != null ){ + state = !state; + // TODO: implement toolbar hide + //toolbar_hide(input_window->root->toolbar, state ); + } +} + +static void __CDECL menu_savewin(short item, short title, void *data) +{ + LOG("%s", __FUNCTION__); + if (input_window && input_window->browser) { + GRECT rect; + wind_get_grect(gemtk_wm_get_handle(input_window->root->win), WF_CURRXYWH, + &rect); + option_window_width = rect.g_w; + option_window_height = rect.g_h; + option_window_x = rect.g_x; + option_window_y = rect.g_y; + nsoption_set_int(window_width, rect.g_w); + nsoption_set_int(window_height, rect.g_h); + nsoption_set_int(window_x, rect.g_x); + nsoption_set_int(window_y, rect.g_y); + nsoption_write((const char*)&options, NULL, NULL); + } + +} + +static void __CDECL menu_debug_render(short item, short title, void *data) +{ + LOG("%s", __FUNCTION__); + html_redraw_debug = !html_redraw_debug; + if( input_window != NULL ) { + if ( input_window->browser != NULL + && input_window->browser->bw != NULL) { + GRECT rect; + window_get_grect(input_window->root, BROWSER_AREA_CONTENT, &rect); + browser_window_reformat(input_window->browser->bw, false, + rect.g_w, rect.g_h ); + menu_icheck(h_gem_menu, MAINMENU_M_DEBUG_RENDER, + (html_redraw_debug) ? 1 : 0); + } + } +} + +static void __CDECL menu_fg_images(short item, short title, void *data) +{ + nsoption_set_bool(foreground_images, !nsoption_bool(foreground_images)); + menu_icheck(h_gem_menu, MAINMENU_M_FG_IMAGES, + (nsoption_bool(foreground_images)) ? 1 : 0); +} + +static void __CDECL menu_bg_images(short item, short title, void *data) +{ + nsoption_set_bool(background_images, !nsoption_bool(background_images)); + menu_icheck(h_gem_menu, MAINMENU_M_BG_IMAGES, + (nsoption_bool(background_images)) ? 1 : 0); +} + +static void __CDECL menu_back(short item, short title, void *data) +{ + LOG("%s", __FUNCTION__); + if( input_window == NULL ) + return; + toolbar_back_click(input_window->root->toolbar); +} + +static void __CDECL menu_forward(short item, short title, void *data) +{ + LOG("%s", __FUNCTION__); + if( input_window == NULL ) + return; + toolbar_forward_click(input_window->root->toolbar); +} + +static void __CDECL menu_home(short item, short title, void *data) +{ + LOG("%s", __FUNCTION__); + if( input_window == NULL ) + return; + toolbar_home_click(input_window->root->toolbar); +} + +static void __CDECL menu_lhistory(short item, short title, void *data) +{ + LOG("%s", __FUNCTION__); + if( input_window == NULL ) + return; +} + +static void __CDECL menu_ghistory(short item, short title, void *data) +{ + LOG("%s", __FUNCTION__); + atari_global_history_open(); +} + +static void __CDECL menu_add_bookmark(short item, short title, void *data) +{ + LOG("%s", __FUNCTION__); + if (input_window) { + if( browser_window_has_content(input_window->browser->bw) ){ + atari_hotlist_add_page( + nsurl_access(browser_window_get_url(input_window->browser->bw)), + NULL + ); + } + } +} + +static void __CDECL menu_bookmarks(short item, short title, void *data) +{ + LOG("%s", __FUNCTION__); + atari_hotlist_open(); +} + +static void __CDECL menu_cookies(short item, short title, void *data) +{ + LOG("%s", __FUNCTION__); + atari_cookie_manager_open(); +} + +static void __CDECL menu_vlog(short item, short title, void *data) +{ + LOG("%s", __FUNCTION__); + verbose_log = !verbose_log; + menu_icheck(h_gem_menu, MAINMENU_M_VLOG, (verbose_log) ? 1 : 0); +} + +static void __CDECL menu_help_content(short item, short title, void *data) +{ + LOG("%s", __FUNCTION__); +} + +/* + Public deskmenu interface: +*/ + + +/* + Parse encoded menu key shortcut + + The format is: + + "[" - marks start of the shortcut + "@,^,<" - If the keyshortcut is only valid + with modifier keys, one of these characters must directly + follow the start mark. + Meaning: + @ -> Alternate + ^ -> Control + "#" - keycode or ascii character. + The value is handled as keycode if the character value + is <= 28 ( Atari chracter table ) + or if it is interpreted as function key string. + (strings: F1 - F10) + +*/ +static void register_menu_str( struct s_menu_item_evnt * mi ) +{ + assert(h_gem_menu != NULL); + + struct s_accelerator * accel = &mi->accel; + int i, l=0, x=-1; + char str[255]; + bool is_std_shortcut = false; + + get_string(h_gem_menu, mi->rid, str); + + i = l = strlen(str); + while (i > 2) { + if ((strncmp(" ", &str[i], 2) == 0) && (strlen(&str[i]) > 2)) { + // "Standard" Keyboard Shortcut Element found: + LOG("Standard Keyboard Shortcut: \"%s\"\n", &str[i]); + x = i+2; + is_std_shortcut = true; + break; + } + + if( str[i] == '['){ + LOG("Keyboard Shortcut: \"%s\"\n", &str[i]); + // "Custom" Keyboard Shortcut Element found (identified by [): + x = i; + break; + } + i--; + } + + // Parse keyboard shortcut value: + if( x > -1 ){ + + if (is_std_shortcut == false) { + // create a new menu string to hide the "[" mark: + mi->menustr = malloc( l+1 ); + strcpy(mi->menustr, str); + mi->menustr[x]=' '; + x++; + } + + // find & register modifiers: + if (str[x] == '@') { + accel->mod = K_ALT; + if (is_std_shortcut == false) { + // only modify menu items when it is malloc'd: + mi->menustr[x] = 0x07; + } + x++; + } + else if (str[x] == '^') { + accel->mod = K_CTRL; + x++; + } + else if (str[x] == 0x01) { // the arrow up chracter (atari-st encoding) + accel->mod = K_LSHIFT; + x++; + } + + // find keycodes / chracters: + if( str[x] <= 28 ){ + // parse symbol + switch( str[x] ){ + case 0x03: + accel->keycode = NK_RIGHT; + break; + case 0x04: + accel->keycode = NK_LEFT; + break; + case 0x1B: + accel->keycode = NK_ESC; + break; + default: + break; + } + } else { + if(str[x] == 'F' && ( str[x+1] >= '1' && str[x+1] <= '9') ){ + // parse function key + short fkey = atoi( &str[x+1] ); + if( (fkey >= 0) && (fkey <= 10) ){ + accel->keycode = NK_F1 - 1 + fkey; + } + } + else if (strncmp(&str[x], "Home", 4) == 0) { + accel->keycode = NK_CLRHOME; + } + else if (strncmp(&str[x], "Undo", 4) == 0) { + accel->keycode = NK_UNDO; + } + else if (strncmp(&str[x], "Help", 4) == 0) { + accel->keycode = NK_HELP; + } + else { + accel->ascii = str[x]; + } + } + + LOG("Registered keyboard shortcut for \"%s\" => mod: %d, ""keycode: %ld, ascii: %c\n", + str, accel->mod, accel->keycode, accel->ascii); + } +} + +/** + * Setup & display an desktop menu. + */ + +void deskmenu_init(void) +{ + int i; + + h_gem_menu = gemtk_obj_get_tree(MAINMENU); + + + /* Install menu: */ + menu_bar(h_gem_menu, MENU_INSTALL); + + /* parse and update menu items: */ + i = 0; + while (menu_evnt_tbl[i].rid != -1) { + if(menu_evnt_tbl[i].rid > 0 && menu_evnt_tbl[i].title > 0){ + register_menu_str( &menu_evnt_tbl[i] ); + /* Update menu string if not null: */ + if( menu_evnt_tbl[i].menustr != NULL ){ + menu_text(h_gem_menu, menu_evnt_tbl[i].rid, + menu_evnt_tbl[i].menustr); + } + } + i++; + } + deskmenu_update(); + /* Redraw menu: */ + menu_bar(h_gem_menu, MENU_UPDATE); +} + +/** + * Uninstall the desktop menu + */ +void deskmenu_destroy(void) +{ + int i; + + /* Remove menu from desktop: */ + menu_bar(h_gem_menu, MENU_REMOVE); + + /* Free modified menu titles: */ + i=0; + while(menu_evnt_tbl[i].rid != -1) { + if( menu_evnt_tbl[i].menustr != NULL ) + free(menu_evnt_tbl[i].menustr); + i++; + } +} + +/** + * Return the deskmenu AES OBJECT tree + */ +OBJECT * deskmenu_get_obj_tree(void) +{ + return(h_gem_menu); +} + +/** + * Handle an menu item event + */ +int deskmenu_dispatch_item(short title, short item) +{ + int i=0; + int retval = 0; + OBJECT * menu_root = deskmenu_get_obj_tree(); + + menu_tnormal(menu_root, item, 1); + menu_tnormal(menu_root, title, 1); + menu_bar(menu_root, 1); + + // legacy code, is this sensible?: + /* + while( gw ) { + window_set_focus( gw, WIDGET_NONE, NULL ); + gw = gw->next; + } + */ + + + while (menu_evnt_tbl[i].rid != -1) { + if (menu_evnt_tbl[i].rid == item) { + if (menu_evnt_tbl[i].menu_func != NULL) { + menu_evnt_tbl[i].menu_func(item, title, NULL); + } + break; + } + i++; + } + + return(retval); +} + +/** + * Handle an keypress (check for accelerator) + */ +int deskmenu_dispatch_keypress(unsigned short kcode, unsigned short kstate, + unsigned short nkc) +{ + char sascii; + bool done = 0; + int i = 0; + + sascii = gemtk_keybd2ascii(kcode, 0); + if(sascii >= 'a' && sascii <= 'z'){ + sascii = gemtk_keybd2ascii(kcode, K_LSHIFT); + } + + /* Iterate through the menu function table: */ + while( menu_evnt_tbl[i].rid != -1 && done == false) { + if( kstate == menu_evnt_tbl[i].accel.mod + && menu_evnt_tbl[i].accel.ascii != 0) { + if( menu_evnt_tbl[i].accel.ascii == sascii) { + if (menu_evnt_tbl[i].title > 0 && menu_evnt_tbl[i].rid > 0) { + deskmenu_dispatch_item(menu_evnt_tbl[i].title, + menu_evnt_tbl[i].rid); + } + else { + /* Keyboard shortcut not displayed within menu: */ + menu_evnt_tbl[i].menu_func(0, 0, NULL); + } + done = true; + break; + } + } else { + /* the accel code hides in the keycode: */ + if( menu_evnt_tbl[i].accel.keycode != 0) { + if( menu_evnt_tbl[i].accel.keycode == (nkc & 0xFF) && + kstate == menu_evnt_tbl[i].accel.mod) { + if (menu_evnt_tbl[i].title > 0 && menu_evnt_tbl[i].rid > 0) { + deskmenu_dispatch_item(menu_evnt_tbl[i].title, + menu_evnt_tbl[i].rid); + } + else { + /* Keyboard shortcut not displayed within menu: */ + menu_evnt_tbl[i].menu_func(0, 0, NULL); + } + done = true; + break; + } + } + } + i++; + } + return((done==true) ? 1 : 0); +} + +/** + * Refresh the desk menu, reflecting netsurf current state. + */ +void deskmenu_update(void) +{ + menu_icheck(h_gem_menu, MAINMENU_M_DEBUG_RENDER, (html_redraw_debug) ? 1 : 0); + menu_icheck(h_gem_menu, MAINMENU_M_FG_IMAGES, + (nsoption_bool(foreground_images)) ? 1 : 0); + menu_icheck(h_gem_menu, MAINMENU_M_BG_IMAGES, + (nsoption_bool(background_images)) ? 1 : 0); + menu_icheck(h_gem_menu, MAINMENU_M_VLOG, ((verbose_log == true) ? 1 : 0)); +} diff --git a/frontends/atari/deskmenu.h b/frontends/atari/deskmenu.h new file mode 100644 index 000000000..d1b157a2d --- /dev/null +++ b/frontends/atari/deskmenu.h @@ -0,0 +1,11 @@ +#ifndef DESKMENU_H_INCLUDED +#define DESKMENU_H_INCLUDED + +void deskmenu_init(void); +void deskmenu_destroy(void); +int deskmenu_dispatch_item(short title, short item); +int deskmenu_dispatch_keypress(unsigned short kcode, unsigned short kstate, unsigned short nkc); +OBJECT * deskmenu_get_obj_tree(void); +void deskmenu_update( void ); + +#endif // DESKMENU_H_INCLUDED diff --git a/frontends/atari/doc/DejaVu.txt b/frontends/atari/doc/DejaVu.txt new file mode 100755 index 000000000..254e2cc42 --- /dev/null +++ b/frontends/atari/doc/DejaVu.txt @@ -0,0 +1,99 @@ +Fonts are (c) Bitstream (see below). DejaVu changes are in public domain. +Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below) + +Bitstream Vera Fonts Copyright +------------------------------ + +Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is +a trademark of Bitstream, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of the fonts accompanying this license ("Fonts") and associated +documentation files (the "Font Software"), to reproduce and distribute the +Font Software, including without limitation the rights to use, copy, merge, +publish, distribute, and/or sell copies of the Font Software, and to permit +persons to whom the Font Software is furnished to do so, subject to the +following conditions: + +The above copyright and trademark notices and this permission notice shall +be included in all copies of one or more of the Font Software typefaces. + +The Font Software may be modified, altered, or added to, and in particular +the designs of glyphs or characters in the Fonts may be modified and +additional glyphs or characters may be added to the Fonts, only if the fonts +are renamed to names not containing either the words "Bitstream" or the word +"Vera". + +This License becomes null and void to the extent applicable to Fonts or Font +Software that has been modified and is distributed under the "Bitstream +Vera" names. + +The Font Software may be sold as part of a larger software package but no +copy of one or more of the Font Software typefaces may be sold by itself. + +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, +TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME +FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING +ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE +FONT SOFTWARE. + +Except as contained in this notice, the names of Gnome, the Gnome +Foundation, and Bitstream Inc., shall not be used in advertising or +otherwise to promote the sale, use or other dealings in this Font Software +without prior written authorization from the Gnome Foundation or Bitstream +Inc., respectively. For further information, contact: fonts at gnome dot +org. + +Arev Fonts Copyright +------------------------------ + +Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of the fonts accompanying this license ("Fonts") and +associated documentation files (the "Font Software"), to reproduce +and distribute the modifications to the Bitstream Vera Font Software, +including without limitation the rights to use, copy, merge, publish, +distribute, and/or sell copies of the Font Software, and to permit +persons to whom the Font Software is furnished to do so, subject to +the following conditions: + +The above copyright and trademark notices and this permission notice +shall be included in all copies of one or more of the Font Software +typefaces. + +The Font Software may be modified, altered, or added to, and in +particular the designs of glyphs or characters in the Fonts may be +modified and additional glyphs or characters may be added to the +Fonts, only if the fonts are renamed to names not containing either +the words "Tavmjong Bah" or the word "Arev". + +This License becomes null and void to the extent applicable to Fonts +or Font Software that has been modified and is distributed under the +"Tavmjong Bah Arev" names. + +The Font Software may be sold as part of a larger software package but +no copy of one or more of the Font Software typefaces may be sold by +itself. + +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL +TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. + +Except as contained in this notice, the name of Tavmjong Bah shall not +be used in advertising or otherwise to promote the sale, use or other +dealings in this Font Software without prior written authorization +from Tavmjong Bah. For further information, contact: tavmjong @ free +. fr. + +$Id: LICENSE 2133 2007-11-28 02:46:28Z lechimp $ diff --git a/frontends/atari/doc/bugs b/frontends/atari/doc/bugs new file mode 100755 index 000000000..74576f67d --- /dev/null +++ b/frontends/atari/doc/bugs @@ -0,0 +1,4 @@ +KNOWN BUGS
+
+- "View Source" only works when the configured editor is already launched.
+- Wrong redraw area when parts of the window move out of the screen area.
diff --git a/frontends/atari/doc/changes.txt b/frontends/atari/doc/changes.txt new file mode 100755 index 000000000..969a44bff --- /dev/null +++ b/frontends/atari/doc/changes.txt @@ -0,0 +1,53 @@ + + + =========================== + FreeMiNT Frontend Changelog + =========================== + + + NetSurf 3.1 +======================================== + +As there was no atari NetSurf 3.0 Release FreeMiNT, this Changelog contains +the FreeMint specific changes from +NetSurf 2.9-PL1 Release (Sunday, April 15 2012) to Netsurf 3.1 Release. + + + - Removed WinDom dependency (heavy GUI code change) + - Implemented "paste clipboard" for toolbar URL textbox. + - Implemented file drop on browser window handling when netsurf core + ignores the file drop event. + - Implemented basic browser window scaling + - Integrated "search page" dialog into browser window + - New settings dialog + - New treeview implementation + - Added global history window. + - Added SSL information treeview + - Added about dialog + - Improved keyboard-shortcut handling + - Improved caret redraw + - Improved favicon display + - Improved warning display (now shows a message box) + - Improved bitmap blitting + - Fixed FreeMiNT's unified filesystem handling (it's not Linux! - but DOS!) + - Fixed default download directoy + - Fixed integer overflow in download completed calculation + - Fixed commandline filepath handling + + + NetSurf 2.9 +======================================== + - Fixed redraw of rectangle outlines. + - Fixed redraw of Hotlist, looks better now. + - Use netsurfs textarea implementation for URL, to reduce code size. + - Fixed several redraw glitches. + - Added a context menu, offering some handy functions. + - NetSurf core now supports frames & iframes. + - Debug rendering works now ( fixed redraw of rectangle outlines ) + - process commandline parameter w (width) / h (height) for default window size + - improved mouse drag within treeview, browser win, toolbar. + - Fixed file drop in frames + - Implemented option dialog + - Improved GUI speed by fixing throbber code. + - Implemented "Save as" ( no improvements where made to core-functions ). + - Implemented settings dialog diff --git a/frontends/atari/doc/faq.txt b/frontends/atari/doc/faq.txt new file mode 100755 index 000000000..53dbe81f2 --- /dev/null +++ b/frontends/atari/doc/faq.txt @@ -0,0 +1,74 @@ +
+NETSURF ATARI FAQ
+
+Date: 12.04.2012
+
+01.) CAN NETSURF ALSO BE RUN WITHIN AN TOS ENVIRONMENT?
+02.) I DON'T HAVE AN 15 BIT GRAPHICS CARD, HOW TO RUN NETSURF ANYWAY?
+03.) WHEN I WANT TO RUN NETSURF IT SAYS: "SOCKET NOT CONNECTED".
+04.) I'M GETTING "INSUFFICENT MEMORY" MESSAGES WHEN RUNNING NETSURF.
+05.) SSL DOES NOT WORK - WHAT'S WRONG? +06.) I'M GETTING THE ERROR: "BASE STYLESHEET FAILED TO LOAD" - WHAT'S WRONG?
+05.) A PAGE CRASHES - WHAT CAN I DO? +
+1.) Question:
+ CAN NETSURF ALSO BE RUN WITHIN AN TOS ENVIRONMENT?
+
+ Answer:
+ Yes NS can run on classic TOS. More or less.
+ It is intended to run within the FreeMint environment.
+ However there is no support for networking
+ right now. Networking support for FireTOS is maybe possible
+ in the future.
+ NS also has problems with Path conversions on all FileSystems
+ running under TOS. Try setting full paths within the Choices file.
+
+
+2.) Question:
+ I DON'T HAVE AN 15 BIT GRAPHICS CARD, HOW TO RUN NETSURF ANYWAY?
+
+ Answer:
+ You need to trigger the config a bit.
+ enable the following Choices settings:
+
+ atari_font_driver:vdi
+ atari_transparency:0
+ suppress_images:1
+
+ This will run netsurf as a bloat textmode browser :)
+
+3.) Question:
+ WHEN I WANT TO RUN NETSURF IT SAYS: "SOCKET NOT CONNECTED"
+
+ Answer:
+ Take a look at the system requirements! I statet NetSurf needs
+ the latest FreeMiNT 1.17 RELEASE. There was a bug within previous
+ Versions. Please update your kernel. OR install polipo proxy
+ provided as RPM within sparemint distribution. This is an
+ workaround, it should work out of the box. But if you want to
+ use the polipo disk-cache you should edit the config file.
+
+4.) Question:
+ I'M GETTING "INSUFFICENT MEMORY" MESSAGES WHEN RUNNING NETSURF.
+
+ Answer:
+ Try to increase the TPA_INITIALMEM Configuration value within MINT.CNF
+
+5.) Question:
+ SSL DOES NOT WORK - WHAT TO DO?
+
+ Answer:
+ Try to move the shipped cabundle.crt file to the path where NetSurf
+ looks for the SSL certificates (Displayed within statusbar and also + verbose log). + +6.) Question: + I'M GETTING THE ERROR: "BASE STYLESHEET FAILED TO LOAD" - WHAT'S WRONG? + + Answer: + NetSurf checks if the base stylesheet is modified. For that - it + requires that the system clock is returning reasonable valid values. + Make your your system clock is set. (Rember empty NVRAM....) + If that doesn't help - make sure the netsurf package was unpacked + completly and that all files can be read. +
diff --git a/frontends/atari/doc/readme.txt b/frontends/atari/doc/readme.txt new file mode 100755 index 000000000..829b59ec8 --- /dev/null +++ b/frontends/atari/doc/readme.txt @@ -0,0 +1,125 @@ +
+
+ NETSURF
+
+ -
+
+ NATIVE ATARI ALPHA
+
+ Version 2.9 (Release Version)
+
+Ported by: m0n0
+Release date: xx.xx.xx
+Contact: ole@monochrom.net
+WWW: http://netsurf-browser.org
+
+
+Table of Contents:
+------------------
+
+0x01 - What is it?
+0x02 - System Requirements
+0x03 - Features
+0x04 - Missing features
+0x05 - Things to test
+0x06 - Additional Notes
+0x07 - Known bugs
+0x08 - Technical information
+
+
+What is it? A web browser!
+--------------------------
+
+ NetSurf is a multi-platform web browser which is written with
+ portability and speed in mind.
+ This is the native Port for the FreeMiNT OS.
+ More info at project website: www.netsurf-browser.org
+
+
+Minimum System Requirements:
+----------------------------
+
+ - 32 MB RAM ( 48 MB recommended for demanding websites )
+ - 32 MHz ( 60 Mhz recommended )
+ - At least 15 Bit Graphics card.
+ - FreeMiNT 1.17.0 release kernel (Please look at FAQ to read
+ about TOS support) for full & correct network support.
+
+
+Main Features:
+--------------
+
+ - Very good HTML 4 & CSS 2.1 rendering
+ - HTTPS
+ - Freetype2 font rendering
+
+
+Missing Features:
+-----------------
+
+ This section describes Features that NetSurf-Core offers but which are not
+ handled by the GEM frontend currently.
+
+ - Grapical website history dialog
+
+
+Installation Notes:
+-------------------
+
+ Unpack the compressed archive that you downloaded,
+ change into the new directory and run ns.prg.
+ If something isn't working - run ns.prg within an console and
+ enable logging:
+
+ ./ns.prg -v
+
+ that makes it possible, that you can identify the problem.
+
+
+Additional Notes
+----------------
+
+ If you would like to see the above mentioned features or
+ can't run NetSurf because you only have a 16 or 256 Color system
+ get in contact.
+
+ Please also check the FAQ document.
+
+ Want to have other software ported? Get in contact and make me rich >;-)
+ If you want to help with netsurf, contact me for further info
+ or visit the netsurf svn and add something usefull :)
+
+ This is "just an early" alpha release. I wanted to get things moving on
+ and I think it is good to show the Atari-Users what has been archived
+ so far. This release lacks some features and some of the code written
+ was just coded with an "I have to get this done quickly" attitude.
+ This is especially true for the drawin routines... It doesn't offer
+ offscreen bitmaps, which was one of my goals for a release. But
+ I dropped that in favor of an not-so-delayed release.
+
+
+Known Bugs
+----------
+ + - "View Source" only works when the configured editor is already launched.
+ - Wrong redraw area when parts of the window move out of the screen area. +
+Technical info & outlook
+------------------------
+
+
+Greetings & Thanks
+------------------
+
+ - AtFact for providing help with resource files & images
+ - The MiNT Mailing list, they all helped me a lot!
+ - The NetSurf Mailing list guys, especially the Amiga guys.
+ - The NetSurf developers that did a great job!
+ - Everyone that tested this Browser!
+ - Everyone that provides feedback!
+ - The forum.atari-home.de members for giving me much help
+ during setup of my atari!
+
+
+----
+M0N0 - 09.09.2011
diff --git a/frontends/atari/doc/todo.txt b/frontends/atari/doc/todo.txt new file mode 100755 index 000000000..49f8e6570 --- /dev/null +++ b/frontends/atari/doc/todo.txt @@ -0,0 +1,18 @@ +TODO's (no priority order) for NetSurf 3.1 - 4.0
+
+ - Optimize drawing of bitmaps on Low-Memory machines
+ - Restore the Palette when Windows get's the Focus
+ -> only needed for <= 256 colors
+ - Make drawing of tiled bitmaps optional ( they are slooow )
+ -> already optimized, still needed? + - Make context menu more stable (grab all available context data at popup display)
+ - Implement SystemColor Choices dialog
+ - Add at least one offscreen plotter implementation + - Fix utf8 to atari character conversion (legacy VDI text plotter + must be able to handle the text argument characters correctly) + - Add URL history when typing URL's into url textarea
+ - Have browser_window specific cursor, window specifc cursor
+ - When minimized (not iconyfied) NetSurf doesn't recognize that.
+ - Implement Tabs (up to 4 tab favicons when iconyfied)
+ - merge treeview and gui_window handling
+
diff --git a/frontends/atari/download.c b/frontends/atari/download.c new file mode 100644 index 000000000..9ebe78751 --- /dev/null +++ b/frontends/atari/download.c @@ -0,0 +1,453 @@ +/* + * Copyright 2010 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <stdbool.h> + +#include "utils/log.h" +#include "utils/messages.h" +#include "utils/utils.h" +#include "utils/nsoption.h" +#include "utils/string.h" +#include "content/urldb.h" +#include "content/fetch.h" +#include "desktop/save_complete.h" +#include "desktop/textinput.h" +#include "desktop/download.h" +#include "desktop/browser.h" +#include "desktop/gui_download.h" + +#include "atari/gui.h" +#include "atari/misc.h" +#include "atari/res/netsurf.rsh" +#include "atari/download.h" +#include "atari/osspec.h" + +extern struct gui_window * input_window; +extern GRECT desk_area; + +static void gui_download_window_destroy( struct gui_download_window * gdw ); +static void on_abort_click(struct gui_download_window *dw); +static void on_cbrdy_click(struct gui_download_window *dw); +static void on_close(struct gui_download_window * dw); +static void on_redraw(struct gui_download_window *dw, GRECT *clip); + +static void toolbar_redraw_cb(GUIWIN *win, uint16_t msg, GRECT *clip) +{ + struct gui_download_window *data; + + if (msg != WM_REDRAW) { + data = gemtk_wm_get_user_data(win); + + assert(data); + + on_redraw(data, clip); + } +} + +static short on_aes_event(GUIWIN *win, EVMULT_OUT *ev_out, short msg[8]) +{ + short retval = 0; + struct gui_download_window *data; + + GRECT clip; + + data = gemtk_wm_get_user_data(win); + + if ((ev_out->emo_events & MU_MESAG) != 0) { + // handle message + //printf("download win msg: %d\n", msg[0]); + switch (msg[0]) { + + case WM_REDRAW: + clip.g_x = msg[4]; + clip.g_y = msg[5]; + clip.g_w = msg[6]; + clip.g_h = msg[7]; + on_redraw(data, &clip); + break; + + case WM_CLOSED: + // TODO: this needs to iterate through all gui windows and + // check if the rootwin is this window... + on_close(data); + break; + + case WM_TOOLBAR: + switch(msg[4]){ + + case DOWNLOAD_BT_ABORT: + on_abort_click(data); + break; + + case DOWNLOAD_CB_CLOSE_RDY: + on_cbrdy_click(data); + break; + + default: break; + } + break; + + default: + break; + } + } + if ((ev_out->emo_events & MU_KEYBD) != 0) { + + + } + if ((ev_out->emo_events & MU_BUTTON) != 0) { + + } + + return(retval); +} + +static void on_redraw(struct gui_download_window *dw, GRECT *clip) +{ + OBJECT *tree = dw->tree; + GRECT work, visible; + uint32_t p = 0; + + gemtk_wm_get_grect(dw->guiwin, GEMTK_WM_AREA_TOOLBAR, &work); + tree->ob_x = work.g_x; + tree->ob_y = work.g_y; + + if(!rc_intersect(clip, &work)){ + return; + } + + /* + Update the AES Object to reflect current state of download: + */ + ((TEDINFO *)get_obspec(tree, DOWNLOAD_FILENAME))->te_ptext = dw->lbl_file; + ((TEDINFO *)get_obspec(tree, DOWNLOAD_LBL_BYTES))->te_ptext = dw->lbl_done; + ((TEDINFO *)get_obspec(tree, DOWNLOAD_LBL_PERCENT))->te_ptext = dw->lbl_percent; + ((TEDINFO *)get_obspec(tree, DOWNLOAD_LBL_SPEED))->te_ptext = dw->lbl_speed; + + if (dw->size_total > 0 ) { + p = ((double)dw->size_downloaded / (double)dw->size_total * 100); + } + tree[DOWNLOAD_PROGRESS_DONE].ob_width = MAX( MIN( p*(DOWNLOAD_BAR_MAX/100), + DOWNLOAD_BAR_MAX ), 1); + if (dw->close_on_finish) { + tree[DOWNLOAD_CB_CLOSE_RDY].ob_state |= (OS_SELECTED | OS_CROSSED); + } else { + tree[DOWNLOAD_CB_CLOSE_RDY].ob_state &= ~(OS_SELECTED | OS_CROSSED); + } + tree[DOWNLOAD_BT_ABORT].ob_state &= ~OS_SELECTED; + + /*Walk the AES rectangle list and redraw the visible areas of the window: */ + wind_get_grect(dw->aes_handle, WF_FIRSTXYWH, &visible); + while (visible.g_x && visible.g_y) { + if (rc_intersect(&work, &visible)) { + objc_draw_grect(tree, 0, 8, &visible); + } + wind_get_grect(dw->aes_handle, WF_NEXTXYWH, &visible); + } +} + +static void on_abort_click(struct gui_download_window *dw) +{ + if( dw->status == NSATARI_DOWNLOAD_COMPLETE + || dw->status == NSATARI_DOWNLOAD_ERROR ) { + gemtk_wm_send_msg(dw->guiwin, WM_CLOSED, 0,0,0,0); + } + else if( dw->status != NSATARI_DOWNLOAD_CANCELED ){ + dw->abort = true; + } +} + +static void on_cbrdy_click(struct gui_download_window *dw) +{ + dw->close_on_finish = !dw->close_on_finish; + if (dw->close_on_finish && dw->status == NSATARI_DOWNLOAD_COMPLETE) { + gemtk_wm_send_msg(dw->guiwin, WM_CLOSED, 0,0,0,0); + } + gemtk_wm_exec_redraw(dw->guiwin, NULL); + evnt_timer(250); +} + +static void on_close(struct gui_download_window * dw) +{ + gui_download_window_destroy(dw); +} + +static void gui_download_window_destroy( struct gui_download_window * gdw) +{ + LOG("gdw %p", gdw); + + if (gdw->status == NSATARI_DOWNLOAD_WORKING) { + download_context_abort(gdw->ctx); + } + + download_context_destroy(gdw->ctx); + + if (gdw->destination) { + free( gdw->destination ); + } + if (gdw->fd != NULL) { + fclose(gdw->fd); + gdw->fd = NULL; + } + if (gdw->fbuf != NULL) { + free( gdw->fbuf ); + } + gemtk_wm_remove(gdw->guiwin); + wind_close(gdw->aes_handle); + wind_delete(gdw->aes_handle); + free(gdw); +} + +static char * select_filepath( const char * path, const char * filename ) +{ + char tmp[PATH_MAX]; + char res_path[PATH_MAX]; + char res_file[PATH_MAX]; + char * ret = NULL; + + strncpy(res_path, path, PATH_MAX); + strncpy(res_file, filename, PATH_MAX); + res_file[PATH_MAX-1] = 0; + res_path[PATH_MAX-1] = 0; + + if(select_file(res_path, res_file, (char*)"*", + (char*)messages_get("SaveAsNS"), NULL)) { + snprintf(tmp, PATH_MAX, "%s%s", res_path, res_file); + ret = malloc(strlen(tmp)+1); + strcpy(ret, tmp); + } + + printf("download file: %s\n", ret); + return(ret); +} + +static struct gui_download_window * +gui_download_window_create(download_context *ctx, struct gui_window *parent) +{ + const char *filename; + char *destination; + char gdos_path[PATH_MAX]; + struct gui_download_window * gdw; + int dlgres = 0; + OBJECT * tree = gemtk_obj_get_tree(DOWNLOAD); + char alert[200]; + + + LOG("Creating download window for gui window: %p", parent); + + /* TODO: Implement real form and use messages file strings! */ + + if (tree == NULL){ + die("Couldn't find AES Object tree for download window!"); + return(NULL); + } + + filename = download_context_get_filename((const download_context*)ctx); + snprintf(alert, 200, "[2][Accept download?|%.*s][Yes|Save as...|No]", + 40,filename); + dlgres = form_alert(2, alert); + if( dlgres == 3){ + return( NULL ); + } + else if( dlgres == 2 ){ + gemdos_realpath(nsoption_charp(downloads_path), gdos_path); + char * tmp = select_filepath( gdos_path, filename ); + if( tmp == NULL ) + return( NULL ); + destination = tmp; + } else { + int dstsize=0; + gemdos_realpath(nsoption_charp(downloads_path), gdos_path); + dstsize = strlen(gdos_path) + strlen(filename) + 2; + destination = malloc( dstsize ); + snprintf(destination, dstsize, "%s/%s", gdos_path, filename); + } + + gdw = calloc(1, sizeof(struct gui_download_window)); + if( gdw == NULL ){ + atari_warn_user(NULL, "Out of memory!"); + free( destination ); + return( NULL ); + } + + gdw->ctx = ctx; + gdw->abort = false; + gdw->start = clock() / CLOCKS_PER_SEC; + gdw->lastrdw = 0; + gdw->status = NSATARI_DOWNLOAD_WORKING; + gdw->parent = parent; + gdw->fbufsize = MAX(BUFSIZ, 48000); + gdw->size_downloaded = 0; + gdw->size_total = download_context_get_total_length(ctx); + gdw->destination = destination; + gdw->tree = tree; + + gdw->fd = fopen(gdw->destination, "wb"); + if( gdw->fd == NULL ){ + char spare[200]; + snprintf(spare, 200, "Couldn't open %s for writing!", gdw->destination); + gemtk_msg_box_show(GEMTK_MSG_BOX_ALERT, spare); + gui_download_window_destroy(gdw); + return( NULL ); + } + + gdw->fbuf = malloc( gdw->fbufsize+1 ); + if( gdw->fbuf != NULL ){ + setvbuf( gdw->fd, gdw->fbuf, _IOFBF, gdw->fbufsize ); + } + + gdw->aes_handle = wind_create_grect(CLOSER | NAME | MOVER, &desk_area); + wind_set_str(gdw->aes_handle, WF_NAME, "Download"); + unsigned long gwflags = GEMTK_WM_FLAG_DEFAULTS; + gdw->guiwin = gemtk_wm_add(gdw->aes_handle, gwflags, on_aes_event); + if( gdw->guiwin == NULL || gdw->fd == NULL ){ + die("could not create guiwin"); + gui_download_window_destroy(gdw); + return( NULL ); + } + gemtk_wm_set_user_data(gdw->guiwin, gdw); + gemtk_wm_set_toolbar(gdw->guiwin, tree, 0, 0); + gemtk_wm_set_toolbar_redraw_func(gdw->guiwin, toolbar_redraw_cb); + + strncpy((char*)&gdw->lbl_file, filename, MAX_SLEN_LBL_FILE-1); + LOG("created download: %s (total size: %d)", gdw->destination, gdw->size_total); + + GRECT work, curr; + work.g_x = 0; + work.g_y = 0; + work.g_w = tree->ob_width; + work.g_h = tree->ob_height; + + wind_calc_grect(WC_BORDER, CLOSER | MOVER | NAME, &work, &curr); + + curr.g_x = (desk_area.g_w / 2) - (curr.g_w / 2); + curr.g_y = (desk_area.g_h / 2) - (curr.g_h / 2); + + wind_open_grect(gdw->aes_handle, &curr); + gdw->lastrdw = clock() / (CLOCKS_PER_SEC >> 3); + + return(gdw); +} + + +static nserror gui_download_window_data(struct gui_download_window *dw, + const char *data, unsigned int size) +{ + uint32_t clck = clock(); + uint32_t tnow = clck / (CLOCKS_PER_SEC>>3); + uint32_t sdiff = (clck / (CLOCKS_PER_SEC)) - dw->start; + + LOG("dw %p",dw); + + if (dw->abort == true){ + dw->status = NSATARI_DOWNLOAD_CANCELED; + dw->abort = false; + download_context_abort(dw->ctx); + gemtk_wm_exec_redraw(dw->guiwin, NULL); + return(NSERROR_OK); + } + + /* save data */ + fwrite( data , size, sizeof(unsigned char),dw->fd ); + dw->size_downloaded += size; + + /* Update GUI */ + if ((tnow - dw->lastrdw) > 1) { + float speed; + + dw->lastrdw = tnow; + speed = dw->size_downloaded / sdiff; + + if( dw->size_total > 0 ){ + uint32_t p = 0; + p = ((double)dw->size_downloaded / (double)dw->size_total * 100); + snprintf( (char*)&dw->lbl_percent, MAX_SLEN_LBL_PERCENT, + "%"PRIu32"%s", p, "%" + ); + } else { + snprintf( (char*)&dw->lbl_percent, MAX_SLEN_LBL_PERCENT, + "%s", "?%" + ); + } + snprintf( (char*)&dw->lbl_speed, MAX_SLEN_LBL_SPEED, "%s/s", + human_friendly_bytesize(speed) + ); + snprintf( (char*)&dw->lbl_done, MAX_SLEN_LBL_DONE, "%s / %s", + human_friendly_bytesize(dw->size_downloaded), + (dw->size_total>0) ? human_friendly_bytesize(dw->size_total) : "?" + ); + + gemtk_wm_exec_redraw(dw->guiwin, NULL); + } + return NSERROR_OK; +} + +static void gui_download_window_error(struct gui_download_window *dw, + const char *error_msg) +{ + LOG("%s", error_msg); + + strncpy((char*)&dw->lbl_file, error_msg, MAX_SLEN_LBL_FILE-1); + dw->status = NSATARI_DOWNLOAD_ERROR; + gemtk_wm_exec_redraw(dw->guiwin, NULL); + atari_window_set_status(input_window, messages_get("Done") ); + // TODO: change abort to close +} + +static void gui_download_window_done(struct gui_download_window *dw) +{ + LOG("dw %p", dw); + +// TODO: change abort to close + dw->status = NSATARI_DOWNLOAD_COMPLETE; + + if( dw->fd != NULL ) { + fclose( dw->fd ); + dw->fd = NULL; + } + + if (dw->close_on_finish) { + gemtk_wm_send_msg(dw->guiwin, WM_CLOSED, 0, 0, 0, 0); + } else { + snprintf( (char*)&dw->lbl_percent, MAX_SLEN_LBL_PERCENT, + "%u%s", 100, "%" + ); + snprintf( (char*)&dw->lbl_done, MAX_SLEN_LBL_DONE, "%s / %s", + human_friendly_bytesize(dw->size_downloaded), + (dw->size_total>0) ? human_friendly_bytesize(dw->size_total) : human_friendly_bytesize(dw->size_downloaded) + ); + gemtk_wm_exec_redraw(dw->guiwin, NULL); + } + atari_window_set_status(input_window, messages_get("Done") ); +} + +static struct gui_download_table download_table = { + .create = gui_download_window_create, + .data = gui_download_window_data, + .error = gui_download_window_error, + .done = gui_download_window_done, +}; + +struct gui_download_table *atari_download_table = &download_table; diff --git a/frontends/atari/download.h b/frontends/atari/download.h new file mode 100644 index 000000000..a5be3257e --- /dev/null +++ b/frontends/atari/download.h @@ -0,0 +1,63 @@ +/* + * Copyright 2010 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef NS_ATARI_DOWNLOAD_H +#define NS_ATARI_DOWNLOAD_H + +extern struct gui_download_table *atari_download_table; + +#define MAX_SLEN_LBL_DONE 64 +#define MAX_SLEN_LBL_PERCENT 5 +#define MAX_SLEN_LBL_SPEED 13 +#define MAX_SLEN_LBL_FILE 256 +#define MAX_SLEN_BT_ABORT 5 + +#define DOWNLOAD_BAR_MAX 300 + +typedef enum { + NSATARI_DOWNLOAD_NONE, + NSATARI_DOWNLOAD_WORKING, + NSATARI_DOWNLOAD_ERROR, + NSATARI_DOWNLOAD_COMPLETE, + NSATARI_DOWNLOAD_CANCELED +} nsatari_download_status; + +struct gui_download_window { + struct download_context *ctx; + struct gui_window * parent; + GUIWIN *guiwin; + short aes_handle; + OBJECT *tree; + nsatari_download_status status; + char *destination; + FILE * fd; + char lbl_done[MAX_SLEN_LBL_DONE]; + char lbl_percent[MAX_SLEN_LBL_PERCENT]; + char lbl_speed[MAX_SLEN_LBL_SPEED]; + char lbl_file[MAX_SLEN_LBL_FILE]; + uint32_t start; + uint32_t lastrdw; + uint32_t size_total; + uint32_t size_downloaded; + char * fbuf; + size_t fbufsize; + bool abort; + bool close_on_finish; +}; + +#endif diff --git a/frontends/atari/encoding.c b/frontends/atari/encoding.c new file mode 100644 index 000000000..9a16cbd4e --- /dev/null +++ b/frontends/atari/encoding.c @@ -0,0 +1,81 @@ +/* + * Copyright 2012 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> + +#include "utils/errors.h" +#include "desktop/gui_utf8.h" + +#include "atari/encoding.h" + + +/* TODO: this need a rework..., encoding to atari st doesn|t always work. +( gui_add_to_clipboard...) */ +nserror utf8_to_local_encoding(const char *string, + size_t len, + char **result) +{ + nserror r; + r = utf8_to_enc(string, "ATARIST", len, result); + if (r != NSERROR_OK) { + r = utf8_to_enc(string, "UTF-8", len, result); + assert( r == NSERROR_OK ); + } + return r; +} + + +nserror utf8_from_local_encoding(const char *string, size_t len, char **result) +{ + return utf8_from_enc(string, "ATARIST", len, result, NULL); +} + + +/* borrowed from highwire project: */ +static const uint16_t Atari_to_Unicode[] = { + /* .0 .1 .2 .3 .4 .5 .6 .7 .8 .9 .A .B .C .D .E .F */ + /* 7F */ 0x0394, + /* 8. */ 0x00C7,0x00FC,0x00E9,0x00E2,0x00E4,0x00E0,0x00E5,0x00E7,0x00EA,0x00EB,0x00E8,0x00EF,0x00EE,0x00EC,0x00C4,0x00C5, + /* 9. */ 0x00C9,0x00E6,0x00C6,0x00F4,0x00F6,0x00F2,0x00FB,0x00F9,0x00FF,0x00D6,0x00DC,0x00A2,0x00A3,0x00A5,0x00DF,0x0192, + /* A. */ 0x00E1,0x00ED,0x00F3,0x00FA,0x00F1,0x00D1,0x00AA,0x00BA,0x00BF,0x2310,0x00AC,0x00BD,0x00BC,0x00A1,0x00AB,0x00BB, + /* B. */ 0x00C3,0x00F5,0x00D8,0x00F8,0x0153,0x0152,0x00C0,0x00C3,0x00D5,0x00A8,0x00B4,0x2020,0x00B6,0x00A9,0x00AE,0x2122, + /* C. */ 0x0133,0x0132,0x05D0,0x05D1,0x05D2,0x05D3,0x05D4,0x05D5,0x05D6,0x05D7,0x05D8,0x05D9,0x05DB,0x05DC,0x05DE,0x05E0, + /* D. */ 0x05E1,0x05E2,0x05E4,0x05E6,0x05E7,0x05E8,0x05E9,0x05EA,0x05DF,0x05DA,0x05DD,0x05E3,0x05E5,0x00A7,0x2038,0x221E, + /* E. */ 0x03B1,0x03B2,0x0393,0x03C0,0x03A3,0x03C3,0x00B5,0x03C4,0x03A6,0x0398,0x03A9,0x03B4,0x222E,0x03C6,0x2208,0x2229, + /* F. */ 0x2261,0x00B1,0x2265,0x2264,0x2320,0x2321,0x00F7,0x2248,0x00B0,0x2022,0x00B7,0x221A,0x207F,0x00B2,0x00B3,0x00AF +}; +#define BEG_Atari_to_Unicode 0x7F + +int atari_to_ucs4(unsigned char atari) +{ + uint32_t ucs4 = 0xfffd; + if ( atari >= BEG_Atari_to_Unicode && atari <= 0xFE ) { + ucs4 = (int)Atari_to_Unicode[(short)atari - BEG_Atari_to_Unicode]; + } else { + ucs4 = (int)atari; + } + return( ucs4 ); +} + + +static struct gui_utf8_table utf8_table = { + .utf8_to_local = utf8_to_local_encoding, + .local_to_utf8 = utf8_from_local_encoding, +}; + +struct gui_utf8_table *atari_utf8_table = &utf8_table; diff --git a/frontends/atari/encoding.h b/frontends/atari/encoding.h new file mode 100644 index 000000000..784aa8273 --- /dev/null +++ b/frontends/atari/encoding.h @@ -0,0 +1,35 @@ +/* + * Copyright 2012 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef NS_ATARI_ENCODING_H +#define NS_ATARI_ENCODING_H + +#include <inttypes.h> +#include <assert.h> +#include <stdbool.h> + +#include "utils/utf8.h" + +struct gui_utf8_table *atari_utf8_table; + +nserror utf8_to_local_encoding(const char *string, size_t len, char **result); +nserror utf8_from_local_encoding(const char *string, size_t len, char **result); + +int atari_to_ucs4( unsigned char atarichar); + +#endif diff --git a/frontends/atari/extract.php b/frontends/atari/extract.php new file mode 100755 index 000000000..865b70ed7 --- /dev/null +++ b/frontends/atari/extract.php @@ -0,0 +1,10 @@ +#!/usr/bin/php +<? +$lines = file("deskmenu.c"); + +foreach($lines as $line){ + if(stripos($line, "static void __CDECL menu_") === 0){ + echo $line; + } +} +?> diff --git a/frontends/atari/file.c b/frontends/atari/file.c new file mode 100644 index 000000000..499edd627 --- /dev/null +++ b/frontends/atari/file.c @@ -0,0 +1,294 @@ +/* + * Copyright 2014 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include <stdarg.h> +#include <string.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + +#include "utils/utils.h" +#include "utils/corestrings.h" +#include "utils/url.h" +#include "utils/nsurl.h" +#include "utils/file.h" +#include "utils/string.h" + +/** + * \file + * Atari file handling callbacks. + * + * Most of this code was taken from windows/gui.c + */ + +/** + * Generate a GEMDOS path from one or more component elemnts. + * + * If a string is allocated it must be freed by the caller. + * + * @param[in,out] str pointer to string pointer if this is NULL enough + * storage will be allocated for the complete path. + * @param[in,out] size The size of the space available if \a str not + * NULL on input and if not NULL set to the total + * output length on output. + * @param[in] nelm The number of elements. + * @param[in] ap The elements of the path as string pointers. + * @return NSERROR_OK and the complete path is written to str + * or error code on faliure. + */ +static nserror atari_mkpath(char **str, size_t *size, size_t nelm, va_list ap) +{ + return vsnstrjoin(str, size, '\\', nelm, ap); +} + +/** + * Get the basename of a file using GEMDOS path handling. + * + * This gets the last element of a path and returns it. + * + * @param[in] path The path to extract the name from. + * @param[in,out] str Pointer to string pointer if this is NULL enough + * storage will be allocated for the path element. + * @param[in,out] size The size of the space available if \a + * str not NULL on input and set to the total + * output length on output. + * @return NSERROR_OK and the complete path is written to str + * or error code on faliure. + */ +static nserror atari_basename(const char *path, char **str, size_t *size) +{ + const char *leafname; + char *fname; + + if (path == NULL) { + return NSERROR_BAD_PARAMETER; + } + + leafname = strrchr(path, '\\'); + if (!leafname) { + leafname = path; + } else { + leafname += 1; + } + + fname = strdup(leafname); + if (fname == NULL) { + return NSERROR_NOMEM; + } + + *str = fname; + if (size != NULL) { + *size = strlen(fname); + } + return NSERROR_OK; +} + +/** + * Create a path from a nsurl using GEMDOS file handling. + * + * @param[in] url The url to encode. + * @param[out] path_out A string containing the result path which should + * be freed by the caller. + * @return NSERROR_OK and the path is written to \a path or error code + * on faliure. + */ +static nserror atari_nsurl_to_path(struct nsurl *url, char **path_out) +{ + lwc_string *urlpath; + char *path; + bool match; + lwc_string *scheme; + nserror res; + + if ((url == NULL) || (path_out == NULL)) { + return NSERROR_BAD_PARAMETER; + } + + scheme = nsurl_get_component(url, NSURL_SCHEME); + + if (lwc_string_caseless_isequal(scheme, corestring_lwc_file, + &match) != lwc_error_ok) + { + return NSERROR_BAD_PARAMETER; + } + lwc_string_unref(scheme); + if (match == false) { + return NSERROR_BAD_PARAMETER; + } + + urlpath = nsurl_get_component(url, NSURL_PATH); + if (urlpath == NULL) { + return NSERROR_BAD_PARAMETER; + } + + res = url_unescape(lwc_string_data(urlpath), &path); + lwc_string_unref(urlpath); + if (res != NSERROR_OK) { + return res; + } + + /* if there is a drive: prefix treat path as DOS filename */ + if ((path[2] == ':') || (path[2] == '|')) { + + /* move the string down to remove leading / note the + * strlen is *not* copying too much data as we are + * moving the null too! + */ + memmove(path, path + 1, strlen(path)); + } + /* if the path does not have a drive letter we return the + * complete path. + */ + /** @todo Need to check returning the unaltered path in this + * case is correct + */ + + *path_out = path; + + return NSERROR_OK; +} + +/** + * Create a nsurl from a path using GEMDOS file handling. + * + * Perform the necessary operations on a path to generate a nsurl. + * + * @param[in] path The path to convert. + * @param[out] url_out pointer to recive the nsurl, The returned url + * should be unreferenced by the caller. + * @return NSERROR_OK and the url is placed in \a url or error code on + * faliure. + */ +static nserror atari_path_to_nsurl(const char *path, struct nsurl **url_out) +{ + nserror ret; + int urllen; + char *urlstr; + char *escpath; /* escaped version of the path */ + char *escpaths; + + if ((path == NULL) || (url_out == NULL) || (*path == 0)) { + return NSERROR_BAD_PARAMETER; + } + + /* escape the path so it can be placed in a url */ + ret = url_escape(path, 0, false, "/", &escpath); + if (ret != NSERROR_OK) { + return ret; + } + /* remove unecessary / as file: paths are already absolute */ + escpaths = escpath; + while (*escpaths == '/') { + escpaths++; + } + + /* build url as a string for nsurl constructor */ + urllen = strlen(escpaths) + FILE_SCHEME_PREFIX_LEN + 1; + urlstr = malloc(urllen); + if (urlstr == NULL) { + free(escpath); + return NSERROR_NOMEM; + } + + snprintf(urlstr, urllen, "%s%s", FILE_SCHEME_PREFIX, escpaths); + free(escpath); + + ret = nsurl_create(urlstr, url_out); + free(urlstr); + + return ret; +} + +/** + * Ensure that all directory elements needed to store a filename exist. + * + * @param fname The filename to ensure the path to exists. + * @return NSERROR_OK on success or error code on failure. + */ +static nserror atari_mkdir_all(const char *fname) +{ + char *dname; + char *sep; + struct stat sb; + + dname = strdup(fname); + + sep = strrchr(dname, '/'); + if (sep == NULL) { + /* no directory separator path is just filename so its ok */ + free(dname); + return NSERROR_OK; + } + + *sep = 0; /* null terminate directory path */ + + if (stat(dname, &sb) == 0) { + free(dname); + if (S_ISDIR(sb.st_mode)) { + /* path to file exists and is a directory */ + return NSERROR_OK; + } + return NSERROR_NOT_DIRECTORY; + } + *sep = '/'; /* restore separator */ + + sep = dname; + while (*sep == '/') { + sep++; + } + while ((sep = strchr(sep, '/')) != NULL) { + *sep = 0; + if (stat(dname, &sb) != 0) { + if (nsmkdir(dname, S_IRWXU) != 0) { + /* could not create path element */ + free(dname); + return NSERROR_NOT_FOUND; + } + } else { + if (! S_ISDIR(sb.st_mode)) { + /* path element not a directory */ + free(dname); + return NSERROR_NOT_DIRECTORY; + } + } + *sep = '/'; /* restore separator */ + /* skip directory separators */ + while (*sep == '/') { + sep++; + } + } + + free(dname); + return NSERROR_OK; +} + + +/* atari file handling table */ +static struct gui_file_table file_table = { + .mkpath = atari_mkpath, + .basename = atari_basename, + .nsurl_to_path = atari_nsurl_to_path, + .path_to_nsurl = atari_path_to_nsurl, + .mkdir_all = atari_mkdir_all, +}; + +struct gui_file_table *atari_file_table = &file_table; + + diff --git a/frontends/atari/file.h b/frontends/atari/file.h new file mode 100644 index 000000000..b368567c7 --- /dev/null +++ b/frontends/atari/file.h @@ -0,0 +1,27 @@ +/* + * Copyright 2014 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FILE_C_INCLUDED +#define FILE_C_INCLUDED + +#include "utils/file.h" + +struct gui_file_table *atari_file_table; + + +#endif /* FILE_C_INCLUDED */ diff --git a/frontends/atari/filetype.c b/frontends/atari/filetype.c new file mode 100644 index 000000000..1cce6fc18 --- /dev/null +++ b/frontends/atari/filetype.c @@ -0,0 +1,91 @@ +/* + * Copyright 2010 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <sys/types.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "utils/messages.h" +#include "utils/utils.h" +#include "utils/log.h" +#include "content/fetch.h" + +#include "atari/filetype.h" + +/** + * filetype -- determine the MIME type of a local file + */ +const char *fetch_filetype(const char *unix_path) +{ + int l; + char * res = (char*)"text/html"; + l = strlen(unix_path); + + LOG("unix path: %s", unix_path); + + /* This line is added for devlopment versions running from the root dir: */ + if( strchr( unix_path, (int)'.' ) ){ + if (2 < l && strcasecmp(unix_path + l - 3, "f79") == 0) + res = (char*)"text/css"; + else if (2 < l && strcasecmp(unix_path + l - 3, "css") == 0) + res = (char*)"text/css"; + else if (2 < l && strcasecmp(unix_path + l - 3, "jpg") == 0) + res = (char*)"image/jpeg"; + else if (3 < l && strcasecmp(unix_path + l - 4, "jpeg") == 0) + res = (char*)"image/jpeg"; + else if (2 < l && strcasecmp(unix_path + l - 3, "gif") == 0) + res = (char*)"image/gif"; + else if (2 < l && strcasecmp(unix_path + l - 3, "png") == 0) + res = (char*)"image/png"; + else if (2 < l && strcasecmp(unix_path + l - 3, "jng") == 0) + res = (char*)"image/jng"; + else if (2 < l && strcasecmp(unix_path + l - 3, "svg") == 0) + res = (char*)"image/svg"; + else if (2 < l && strcasecmp(unix_path + l - 3, "txt") == 0) + res = (char*)"text/plain"; + } else { + FILE * fp; + char buffer[16]; + fp = fopen( unix_path, "r" ); + if( fp ){ + int n=0; + int c; + do { + c = fgetc (fp); + if( c != EOF ) + buffer[n] = (char)c; + else + buffer[n] = 0; + n++; + } while (c != EOF && n<15); + fclose( fp ); + if( n > 0 ){ + if( n > 5 && strncasecmp("GIF89", buffer, 5) == 0 ) + res = (char*)"image/gif"; + else if( n > 4 && strncasecmp("PNG", &buffer[1], 3) ==0 ) + res = (char*)"image/png"; + else if( n > 10 && strncasecmp("JFIF", &buffer[5], 4) == 0 ) + res = (char*)"image/jpeg"; + } + } + } + + LOG("mime type: %s", res); + return( res ); +} diff --git a/frontends/atari/filetype.h b/frontends/atari/filetype.h new file mode 100644 index 000000000..97ba75b80 --- /dev/null +++ b/frontends/atari/filetype.h @@ -0,0 +1,24 @@ +/* + * Copyright 2010 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef NS_ATARI_FILETYPE_H_ +#define NS_ATARI_FILETYPE_H_ + +const char *fetch_filetype(const char *unix_path); + +#endif diff --git a/frontends/atari/findfile.c b/frontends/atari/findfile.c new file mode 100644 index 000000000..45ca6d916 --- /dev/null +++ b/frontends/atari/findfile.c @@ -0,0 +1,144 @@ +/* + * Copyright 2010 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <unistd.h> + +#include "utils/log.h" +#include "utils/corestrings.h" + +#include "atari/gemtk/gemtk.h" +#include "atari/findfile.h" +#include "atari/gui.h" +#include "atari/osspec.h" + +char * local_file_to_url( const char * filename ) +{ + #define BACKSLASH 0x5C + char * url; + + LOG("in: %s", filename); + + if( strlen(filename) <= 2){ + return( NULL ); + } + + char * fname_local = malloc( strlen(filename)+1 ); + char * start = (char*)fname_local; + strcpy( start, filename ); + + /* convert backslashes: */ + for( unsigned int i=0; i<strlen(start); i++ ){ + if( start[i] == BACKSLASH ){ + start[i] = '/'; + } + } + + // TODO: make file path absolute if it isn't yet. + url = malloc( strlen(start) + FILE_SCHEME_PREFIX_LEN + 1); + strcpy(url, FILE_SCHEME_PREFIX ); + strcat(url, start ); + + free(fname_local); + + LOG("out: %s", url); + + return( url ); + #undef BACKSLASH +} + + +/** + * Locate a shared resource file by searching known places in order. + * Search order is: ./, NETSURF_GEM_RESPATH, ./$HOME/.netsurf/, $NETSURFRES/ + * (where NETSURFRES is an environment variable) + * + * \param buf buffer to write to. must be at least PATH_MAX chars + * \param filename file to look for + * \param def default to return if file not found + * \return buf + * + */ +#ifndef NETSURF_GEM_RESPATH + #define NETSURF_GEM_RESPATH "./res/" +#endif + +char * atari_find_resource(char *buf, const char *filename, const char *def) +{ + char *cdir = NULL; + char t[PATH_MAX]; + LOG("%s (def: %s)", filename, def); + strcpy(t, NETSURF_GEM_RESPATH); + strcat(t, filename); + LOG("checking %s", (char *)&t); + if (gemdos_realpath(t, buf) != NULL) { + if (access(buf, R_OK) == 0) { + return buf; + } + } + strcpy(t, "./"); + strcat(t, filename); + LOG("checking %s", (char *)&t); + if (gemdos_realpath(t, buf) != NULL) { + if (access(buf, R_OK) == 0) { + return buf; + } + } + + cdir = getenv("HOME"); + if (cdir != NULL) { + strcpy(t, cdir); + strcat(t, "/.netsurf/"); + strcat(t, filename); + LOG("checking %s", (char *)&t); + if (gemdos_realpath(t, buf) != NULL) { + if (access(buf, R_OK) == 0) + return buf; + } + } + + cdir = getenv("NETSURFRES"); + if (cdir != NULL) { + if (gemdos_realpath(cdir, buf) != NULL) { + strcat(buf, "/"); + strcat(buf, filename); + LOG("checking %s", (char *)&t); + if (access(buf, R_OK) == 0) + return buf; + } + } + if (def[0] == '~') { + snprintf(t, PATH_MAX, "%s%s", getenv("HOME"), def + 1); + LOG("checking %s", (char *)&t); + if (gemdos_realpath(t, buf) == NULL) { + strcpy(buf, t); + } + } else { + LOG("checking %s", (char *)def); + if (gemdos_realpath(def, buf) == NULL) { + strcpy(buf, def); + } + } + + return buf; +} + +/* + * Local Variables: + * c-basic-offset: 8 + * End: + */ diff --git a/frontends/atari/findfile.h b/frontends/atari/findfile.h new file mode 100644 index 000000000..9cda2a0be --- /dev/null +++ b/frontends/atari/findfile.h @@ -0,0 +1,26 @@ +/* + * Copyright 2008 Daniel Silverstone <dsilvers@netsurf-browser.org> + * Copyright 2011 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef NS_ATARI_FINDFILE_H +#define NS_ATARI_FINDFILE_H + +extern char *atari_find_resource(char *buf, const char *filename, const char *def); +char *local_file_to_url(const char *filename); + +#endif /* NETSURF_ATARI_FINDFILE_H */ diff --git a/frontends/atari/font.c b/frontends/atari/font.c new file mode 100644 index 000000000..cb0c574ea --- /dev/null +++ b/frontends/atari/font.c @@ -0,0 +1,156 @@ +/* + * Copyright 2010 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <inttypes.h> +#include <assert.h> +#include <stdbool.h> +#include <stdlib.h> + +#include "utils/utf8.h" +#include "utils/log.h" +#include "utils/nsoption.h" +#include "desktop/gui_layout.h" +#include "desktop/mouse.h" +#include "desktop/plotters.h" + +#include "atari/gui.h" +#include "atari/plot/fontplot.h" +#include "atari/plot/plot.h" +#include "atari/findfile.h" +#include "atari/font.h" + +extern FONT_PLOTTER fplotter; + + +/** + * Find the position in a string where an x coordinate falls. + * + * \param[in] fstyle style for this text + * \param[in] string UTF-8 string to measure + * \param[in] length length of string, in bytes + * \param[in] x coordinate to search for + * \param[out] char_offset updated to offset in string of actual_x, [0..length] + * \param[out] actual_x updated to x coordinate of character closest to x + * \return NSERROR_OK and char_offset and actual_x updated or appropriate error code on faliure + */ +static nserror +atari_font_position(const plot_font_style_t *fstyle, + const char *string, + size_t length, + int x, + size_t *char_offset, + int *actual_x) +{ + float scale = plot_get_scale(); + + if (scale != 1.0) { + plot_font_style_t newstyle = *fstyle; + newstyle.size = (int)((float)fstyle->size*scale); + fplotter->pixel_pos(fplotter, &newstyle, string, length, x, + char_offset, actual_x); + } else { + fplotter->pixel_pos(fplotter, fstyle, string, length, x, + char_offset, actual_x); + } + + return NSERROR_OK; +} + + +/** + * Find where to split a string to make it fit a width. + * + * \param[in] fstyle style for this text + * \param[in] string UTF-8 string to measure + * \param[in] length length of string, in bytes + * \param[in] x width available + * \param[out] char_offset updated to offset in string of actual_x, [1..length] + * \param[out] actual_x updated to x coordinate of character closest to x + * \return NSERROR_OK or appropriate error code on faliure + * + * On exit, char_offset indicates first character after split point. + * + * \note char_offset of 0 must never be returned. + * + * Returns: + * char_offset giving split point closest to x, where actual_x <= x + * else + * char_offset giving split point closest to x, where actual_x > x + * + * Returning char_offset == length means no split possible + */ +static nserror +atari_font_split(const plot_font_style_t *fstyle, + const char *string, + size_t length, + int x, + size_t *char_offset, + int *actual_x) +{ + float scale = plot_get_scale(); + + if (scale != 1.0) { + plot_font_style_t newstyle = *fstyle; + newstyle.size = (int)((float)fstyle->size*scale); + fplotter->str_split(fplotter, &newstyle, string, length, x, + char_offset, actual_x); + } else { + fplotter->str_split(fplotter, fstyle, string, length, x, + char_offset, actual_x); + } + + return NSERROR_OK; +} + + +/** + * Measure the width of a string. + * + * \param[in] fstyle plot style for this text + * \param[in] string UTF-8 string to measure + * \param[in] length length of string, in bytes + * \param[out] width updated to width of string[0..length) + * \return NSERROR_OK and width updated or appropriate error code on faliure + */ +static nserror +atari_font_width(const plot_font_style_t *fstyle, + const char *str, + size_t length, + int * width) +{ + float scale = plot_get_scale(); + + if (scale != 1.0) { + plot_font_style_t newstyle = *fstyle; + newstyle.size = (int)((float)fstyle->size*scale); + fplotter->str_width(fplotter, &newstyle, str, length, width); + } else { + fplotter->str_width(fplotter, fstyle, str, length, width); + } + + return NSERROR_OK; +} + + +static struct gui_layout_table layout_table = { + .width = atari_font_width, + .position = atari_font_position, + .split = atari_font_split, +}; + +struct gui_layout_table *atari_layout_table = &layout_table; diff --git a/frontends/atari/font.h b/frontends/atari/font.h new file mode 100644 index 000000000..a01d000c0 --- /dev/null +++ b/frontends/atari/font.h @@ -0,0 +1,25 @@ +/* + * Copyright 2010 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef NS_ATARI_FONT_H +#define NS_ATARI_FONT_H + +struct gui_layout_table *atari_layout_table; + +#endif /* NETSURF_FB_FONT_H */ + diff --git a/frontends/atari/gemtk/aestabs.c b/frontends/atari/gemtk/aestabs.c new file mode 100644 index 000000000..519676514 --- /dev/null +++ b/frontends/atari/gemtk/aestabs.c @@ -0,0 +1,191 @@ +/*
+ * Copyright 2013 Ole Loots <ole@monochrom.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */ + +#include <stdlib.h> +#include <assert.h> +#include <gem.h> +#include <cflib.h> +#include "aestabs.h" + +#ifndef NDEBUG +# define DEBUG_PRINT(x) printf x +#else +# define DEBUG_PRINT(x) +#endif + + +AES_TABLIST * tablist_declare(OBJECT *tree, aes_tablist_user_func user_func) +{ + AES_TABLIST * newlist = malloc(sizeof(AES_TABLIST)); + + newlist->first = NULL; + newlist->tree = tree; + newlist->user_func = user_func; + DEBUG_PRINT(("aes_tablist_declare: %p\n", newlist)); + return(newlist); +} + + +AES_TAB * tablist_add(AES_TABLIST * tablist, short obj_tab, OBJECT * page_tree, + short obj_page) +{ + AES_TAB * newtab = malloc(sizeof(AES_TAB)); + + assert(newtab); + assert(tablist); + + newtab->next = NULL; + newtab->prev = NULL; + newtab->obj_tab = obj_tab; + newtab->obj_page = obj_page; + newtab->page_tree = page_tree; + + if(newtab->page_tree == NULL){ + newtab->page_tree = tablist->tree; + } + + if (tablist->first == NULL) { + tablist->first = newtab; + set_state(tablist->tree, newtab->obj_tab, OS_SELECTED, 0); + } else { + AES_TAB *tmp = tablist->first; + while( tmp->next != NULL ) { + tmp = tmp->next; + } + tmp->next = newtab; + newtab->prev = tmp; + newtab->next = NULL; + set_state(tablist->tree, newtab->obj_tab, OS_SELECTED, 0); + } + + // TODO: Set the visible flag on that register? + + DEBUG_PRINT(("tablist_add: Tab=%p\n", newtab)); + + return(newtab); +} + + +short tablist_activate(AES_TABLIST * tablist, short tab, short options) +{ + AES_TAB *tmp, *activated=NULL, *deactivated=NULL; + struct aes_tab_s *active; + short activated_pg = -1; + short is_tab = 0; + + assert(tablist); + assert(tablist->first); + + active = tablist_get_active(tablist); + + if (active != NULL) { + if ((options & AES_TABLIST_OPTION_FORCE_EVENTS) == 0) { + if(active->obj_tab == tab) + return(0); + } + } + + tmp = tablist->first; + while (tmp != NULL) { + if(tmp->obj_tab == tab) { + is_tab = 1; + } + tmp = tmp->next; + } + + if(is_tab == 0) { + return(0); + } + + tmp = tablist->first; + while ( tmp != NULL ) { + if(tab != tmp->obj_tab) { + if (get_state(tablist->tree, tmp->obj_tab, OS_SELECTED) != 0) { + deactivated = tmp; + set_state(tablist->tree, tmp->obj_tab, OS_SELECTED, 0); + } + // the tab registers can share the same page, consider that: + if (tablist->tree == tmp->page_tree + && activated_pg != tmp->obj_page) { + + set_flag(tablist->tree, tmp->obj_page, OF_HIDETREE, 1); + } + } else { + activated = tmp; + // this tab must the selected / visible + set_state(tablist->tree, tmp->obj_tab, OS_SELECTED, 1); + if(tablist->tree == tmp->page_tree) + set_flag(tablist->tree, tmp->obj_page, OF_HIDETREE, 0); + activated_pg = tmp->obj_page; + } + tmp = tmp->next; + } + + if(tablist->user_func != NULL) { + AES_TABLIST_FUNC_ARGS args; + if(deactivated){ + args.event = AES_TABLIST_TAB_DEACTIVATED; + args.tab = deactivated; + tablist->user_func(tablist, &args); + } + if(activated){ + args.event = AES_TABLIST_TAB_ACTIVATED; + args.tab = activated; + tablist->user_func(tablist, &args); + } + } + return(1); +} + +struct aes_tab_s *tablist_get_active(AES_TABLIST * tablist) +{ + AES_TAB *tmp = tablist->first; + while( tmp != NULL ) { + if(get_state(tablist->tree, tmp->obj_tab, OS_SELECTED) != 0) { + // that's the one + return(tmp); + } + tmp = tmp->next; + } + return(NULL); +} + +AES_TAB * tablist_find(AES_TABLIST * tablist, OBJECT * page, short tab) +{ + AES_TAB *tmp = tablist->first; + while( tmp != NULL ) { + if((tmp->page_tree == page) && (tab == tmp->obj_tab)) { + return(tmp); + } + tmp = tmp->next; + } + return(NULL); +} + +void tablist_delete(AES_TABLIST *tablist) +{ + AES_TAB *tmp = tablist->first, *cur; + while ( tmp != NULL ) { + cur = tmp; + tmp = tmp->next; + DEBUG_PRINT(("tablist_delete, Freeing tab: %p\n", cur)); + free(cur); + } + DEBUG_PRINT(("tablist_delete, Freeing list: %p\n", tablist)); + free(tablist); +} diff --git a/frontends/atari/gemtk/aestabs.h b/frontends/atari/gemtk/aestabs.h new file mode 100644 index 000000000..c72054acc --- /dev/null +++ b/frontends/atari/gemtk/aestabs.h @@ -0,0 +1,56 @@ +#ifndef AESTABS_H_INCLUDED
+#define AESTABS_H_INCLUDED
+ +struct aes_tab_s; +struct aes_tablist_s; +typedef struct aes_tab_s AES_TAB; +typedef struct aes_tablist_s AES_TABLIST; + +#define AES_TABLIST_TAB_ACTIVATED 0x01 +#define AES_TABLIST_TAB_DEACTIVATED 0x02 + +#define AES_TABLIST_OPTION_FORCE_EVENTS 0x01 // do not eat events which do + // not changed the internal state + // this is required for tabs which + // require "activate" events + // for tabs which are already + // selected. + + +struct aes_tablist_user_args_s +{ + short event; + AES_TAB *tab; +}; + +typedef struct aes_tablist_user_args_s AES_TABLIST_FUNC_ARGS; + +typedef void (*aes_tablist_user_func)(AES_TABLIST * list, + AES_TABLIST_FUNC_ARGS * args); + +struct aes_tab_s { + short obj_tab; + short obj_page; + OBJECT * page_tree; + AES_TAB * next, *prev; +}; + +struct aes_tablist_s { + OBJECT *tree; + AES_TAB * first; + aes_tablist_user_func user_func; +}; + + + +AES_TABLIST * tablist_declare(OBJECT *tree, aes_tablist_user_func user_func); +void tablist_delete(AES_TABLIST * tablist); +AES_TAB * tablist_add(AES_TABLIST * tablist, short tab, OBJECT *page_tree, + short page); +short tablist_activate(AES_TABLIST * tablist, short tab, short option); +struct aes_tab_s *tablist_get_active(AES_TABLIST * tablist); +AES_TAB * tablist_find(AES_TABLIST * tablist, OBJECT *page, short tab); + +#define AES_TAB_IS_ACTIVE(l, x) (tablist_get_active(l) == x) +
+#endif // AESTABS_H_INCLUDED
diff --git a/frontends/atari/gemtk/dragdrop.c b/frontends/atari/gemtk/dragdrop.c new file mode 100755 index 000000000..a4b7b82a3 --- /dev/null +++ b/frontends/atari/gemtk/dragdrop.c @@ -0,0 +1,515 @@ +/* +* Routine pour Drag and drop sous MultiTos +* source: D&D Atari, demo OEP (Alexander Lorenz) +* +* Struktur OEP (oep.apid): AES-ID der Applikation +* +* (Tab = 4) +*/ + +#ifdef __PUREC__ +#include <tos.h> +#else +#include <osbind.h> +#include <mintbind.h> +#include <signal.h> +#endif + +#include <string.h> +#include <stdio.h> + +#include "gemtk.h" +#include "cflib.h" + +#ifndef EACCDN +#define EACCDN (-36) +#endif + +#ifndef FA_HIDDEN +#define FA_HIDDEN 0x02 +#endif + +static char pipename[] = "U:\\PIPE\\DRAGDROP.AA"; +static long pipesig; + +/* +* Routinen fr den Sender +*/ + +/* +* Erzeugt Pipe fr D&D +* +* Eingabeparameter: +* pipe - Pointer auf 2 Byte Buffer fr Pipeextension +* +* Ausgabeparameters: +* keine +* +* Returnwert: +* >0: Filehandle der Pipe +* -1: Fehler beim Erzeugen der Pipe +*/ + +short gemtk_dd_create(short *pipe) +{ + long fd = -1; + + pipename[17] = 'A'; + pipename[18] = 'A' - 1; + + do /* ouvre un pipe inoccup */ + { + pipename[18]++; + if (pipename[18] > 'Z') + { + pipename[17]++; + if (pipename[17] > 'Z') + break; + else + pipename[18] = 'A'; + } + + /* FA_HIDDEN fr Pipe notwendig! */ + + fd = Fcreate(pipename, FA_HIDDEN); + + } while (fd == (long) EACCDN); + + if (fd < 0L) + return(-1); + + *pipe = (pipename[17] << 8) | pipename[18]; + + + /* Signalhandler konfigurieren */ + + gemtk_dd_getsig(&pipesig); + + + return((short) fd); +} + + + +/* +* Sendet AP_DRAGDROP an Empfngerapplikation +* +* Eingabeparameter: +* apid - AES-ID der Emfngerapp. +* 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: Empfngerapp. gibt DD_NAK zurck +* -2: Empfngerapp. 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 Empfngerapplikation +* +* 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 Empfnger 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 - Empfnger akzeptiert Datentyp +* DD_NAK - Empfnger brach Drag&Drop ab +* DD_EXT - Empfnger lehnt Datentyp ab +* DD_LEN - Empfnger 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 Empfnger */ + +/* +* Pipe schlieen (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 Empfnger */ + +/* +* 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); +} + + + +/* +* Nchsten 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 Datengre (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 donne (extension) +* 1 long: taille des donnes +* STRING: description des donnes +* STRING: nom du fichiers +* soit au minimun 11 octets (cas ou les string sont rduites \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 donnes */ + return(-1); + + hdrlen -= 8; /* on a lu 8 octets */ + + if (hdrlen > DD_NAMEMAX*2) + i = DD_NAMEMAX*2; + else + i = hdrlen; + + len = i; + + if (Fread(fd, (long) i, buf) != (long) i) + return(-1); + + hdrlen -= i; + + strncpy(name, buf, DD_NAMEMAX); + + i = (short) strlen(name) + 1; + + if (len - i > 0) + strncpy(file, buf + i, DD_NAMEMAX); + else + file[0] = '\0'; + + + /* weitere Bytes im Header in den Mll */ + + while (hdrlen > DD_NAMEMAX*2) + { + if (Fread(fd, DD_NAMEMAX*2, buf) != DD_NAMEMAX*2) + return(-1); + + hdrlen -= DD_NAMEMAX*2; + } + + if (hdrlen > 0) + { + if (Fread(fd, (long) hdrlen, buf) != (long) hdrlen) + return(-1); + } + + return(1); +} + + + +/* +* Sendet der Senderapplikation eine 1 Byte Antwort +* +* Eingabeparameter: +* fd - Filehandle der Pipe (von gemtk_dd_open()) +* ack - Byte das gesendet werden soll (zB. DD_OK) +* +* Ausgabeparameter: +* keine +* +* Returnwert: +* >0: kein Fehler +* -1: Fehler (die Pipe wird automatisch geschlossen!) +*/ + +short gemtk_dd_reply(short fd, char ack) +{ + if (Fwrite(fd, 1L, &ack) != 1L) + { + gemtk_dd_close(fd); + return(-1); + } + + return(1); +} + + diff --git a/frontends/atari/gemtk/dragdrop.h b/frontends/atari/gemtk/dragdrop.h new file mode 100755 index 000000000..38466137b --- /dev/null +++ b/frontends/atari/gemtk/dragdrop.h @@ -0,0 +1,4 @@ +#ifndef DD_H_INCLUDED +#define DD_H_INCLUDED + +#endif diff --git a/frontends/atari/gemtk/gemtk.h b/frontends/atari/gemtk/gemtk.h new file mode 100644 index 000000000..e5915e6eb --- /dev/null +++ b/frontends/atari/gemtk/gemtk.h @@ -0,0 +1,298 @@ +#ifndef GEMTK_H_INCLUDED +#define GEMTK_H_INCLUDED + +#include <stdint.h> +#include <stdbool.h> + +#include <mint/osbind.h> +#include <mint/cookie.h> + +#include <gem.h> +#include <cflib.h> + + +/* -------------------------------------------------------------------------- */ +/* SYSTEM UTILS */ +/* -------------------------------------------------------------------------- */ + +/* System type detection added by [GS] */ +/* detect the system type, AES + kernel */ +#define SYS_TOS 0x0001 +#define SYS_MAGIC 0x0002 +#define SYS_MINT 0x0004 +#define SYS_GENEVA 0x0010 +#define SYS_NAES 0x0020 +#define SYS_XAAES 0x0040 +#define sys_type() (_systype_v ? _systype_v : _systype()) +#define sys_MAGIC() ((sys_type() & SYS_MAGIC) != 0) +#define sys_NAES() ((sys_type() & SYS_NAES) != 0) +#define sys_XAAES() ((sys_type() & SYS_XAAES) != 0) + +#define TOS4VER 0x03300 /* this is assumed to be the last single tasking OS */ + +extern unsigned short _systype_v; +unsigned short _systype (void); + +/* GEMTK Utils API: */ + +#define GEMTK_DBG_GRECT(s,g) \ + printf("%s", s); \ + printf("\tx0: %d, \n", (g)->g_x); \ + printf("\ty0: %d, \n", (g)->g_y); \ + printf("\tx1: %d, \n", (g)->g_x+(g)->g_w); \ + printf("\ty1: %d, \n", (g)->g_y+(g)->g_h); \ + printf("\tw: %d, \n", (g)->g_w); \ + printf("\th: %d \n", (g)->g_h); \ + +/* +* Chech for GRECT intersection without modifiend the src rectangles +* return true when the GRECT's intersect, fals otherwise. +*/ +bool gemtk_rc_intersect_ro(GRECT *a, GRECT *b); + +/* +* Convert keycode returned by evnt_multi to ascii value +*/ +int gemtk_keybd2ascii( int keybd, int shift); + +/** set VDI clip area by passing an GRECT */ +void gemtk_clip_grect(VdiHdl vh, GRECT *rect); + +void gemtk_wind_get_str(short aes_handle, short mode, char *str, int len); + +/* send application message */ +void gemtk_send_msg(short msg_type, short data2, short data3, short data4, + short data5, short data6, short data7); + + +#ifndef POINT_WITHIN +# define POINT_WITHIN(_x,_y, r) ((_x >= r.g_x) && (_x <= r.g_x + r.g_w ) \ + && (_y >= r.g_y) && (_y <= r.g_y + r.g_h)) +#endif + +#ifndef RC_WITHIN +# define RC_WITHIN(a,b) \ + (((a)->g_x >= (b)->g_x) \ + && (((a)->g_x + (a)->g_w) <= ((b)->g_x + (b)->g_w))) \ + && (((a)->g_y >= (b)->g_y) \ + && (((a)->g_y + (a)->g_h) <= ((b)->g_y + (b)->g_h))) +#endif + +#ifndef MAX +# define MAX(_a,_b) ((_a>_b) ? _a : _b) +#endif + +#ifndef MIN +# define MIN(_a,_b) ((_a<_b) ? _a : _b) +#endif + +#ifndef SET_BIT +# define SET_BIT(field,bit,val) field = (val)?((field)|(bit)):((field) & ~(bit)) +#endif + +/* -------------------------------------------------------------------------- */ +/* MultiTOS Drag & Drop */ +/* -------------------------------------------------------------------------- */ +short gemtk_dd_create(short *pipe); +short gemtk_dd_message(short apid, short fd, short winid, short mx, short my, short kstate, short pipename); +short gemtk_dd_rexts(short fd, char *exts); +short gemtk_dd_stry(short fd, char *ext, char *text, char *name, long size); +void gemtk_dd_close(short fd); +void gemtk_dd_getsig(long *oldsig); +void gemtk_dd_setsig(long oldsig); +short gemtk_dd_open(short ddnam, char ddmsg); +short gemtk_dd_sexts(short fd, char *exts); +short gemtk_dd_rtry(short fd, char *name, char *file, char *whichext, long *size); +short gemtk_dd_reply(short fd, char ack); + +/* -------------------------------------------------------------------------- */ +/* AV/VA Protocol Module */ +/* -------------------------------------------------------------------------- */ +int gemtk_av_init(const char *appname); +void gemtk_av_exit(void); +bool gemtk_av_send (short message, const char * data1, const char * data2); +bool gemtk_av_dispatch (short msg[8]); + +/* -------------------------------------------------------------------------- */ +/* Message Box module */ +/* -------------------------------------------------------------------------- */ +#define GEMTK_MSG_BOX_ALERT 1 +#define GEMTK_MSG_BOX_CONFIRM 2 + +short gemtk_msg_box_show(short type, const char * msg); + +/* -------------------------------------------------------------------------- */ +/* GUIWIN Module */ +/* -------------------------------------------------------------------------- */ +#define GEMTK_WM_FLAG_PREPROC_WM 0x01 // let guiwin API handle some events +#define GEMTK_WM_FLAG_RECV_PREPROC_WM 0x02 // get notified even when pre-processed +#define GEMTK_WM_FLAG_HAS_VTOOLBAR 0x04 // the attached toolbar is vertical +#define GEMTK_WM_FLAG_CUSTOM_TOOLBAR 0x08 // no internal toolbar handling + // (Except considering it's size) +#define GEMTK_WM_FLAG_CUSTOM_SCROLLING 0x20 // no internal scroller handling + +#define GEMTK_WM_FLAG_DEFAULTS \ + (GEMTK_WM_FLAG_PREPROC_WM | GEMTK_WM_FLAG_RECV_PREPROC_WM) + +#define GEMTK_WM_STATUS_ICONIFIED 0x01 +#define GEMTK_WM_STATUS_SHADED 0x02 + +#define GEMTK_WM_VSLIDER 0x01 +#define GEMTK_WM_HSLIDER 0x02 +#define GEMTK_WM_VH_SLIDER 0x03 + +/* + Message sent to the client application when an AES object is + clicked in an window which contains an form. + + Message Parameters: + msg[4] = Clicked Object. + msg[5] = Number of clicks. + msg[6] = Modifier keys. +*/ +#define GEMTK_WM_WM_FORM_CLICK 1001 +#define GEMTK_WM_WM_FORM_KEY 1002 + +struct gemtk_window_s; + +/** list struct for managing AES windows */ +typedef struct gemtk_window_s GUIWIN; + +/** GUIWIN event handler */ +typedef short (*gemtk_wm_event_handler_f)(GUIWIN *gw, + EVMULT_OUT *ev_out, short msg[8]); + +typedef void (*gemtk_wm_redraw_f)(GUIWIN *win, uint16_t msg, GRECT *clip); + +struct gemtk_wm_scroll_info_s { + + /** Definition of a content unit (horizontal) measured in pixel */ + int x_unit_px; + + /** Definition of content unit (vertical) measured in pixel */ + int y_unit_px; + + /** Current scroll position (in content units) */ + int x_pos; + + /** Current scroll position (in content units) */ + int y_pos; + + /** Size of content (horizontal) measured in content units */ + int x_units; + + /** Size of content (vertical) measured in content units */ + int y_units; +}; + +/** Well known areas inside the window */ +enum guwin_area_e { + GEMTK_WM_AREA_WORK = 0, + GEMTK_WM_AREA_TOOLBAR, + GEMTK_WM_AREA_CONTENT +}; + +/* -------------------------------------------------------------------------- */ +/* GUIWIN functions (document in guiwin.c) */ +/* -------------------------------------------------------------------------- */ + +short +gemtk_wm_init(void); + +void gemtk_wm_exit(void); + +GUIWIN * gemtk_wm_add(short handle, uint32_t flags, + gemtk_wm_event_handler_f handler); + +GUIWIN * gemtk_wm_find(short handle); + +void gemtk_wm_dump_window_info(GUIWIN *win); + +short gemtk_wm_remove(GUIWIN *win); + +GUIWIN * gemtk_wm_validate_ptr(GUIWIN *win); + +GUIWIN *gemtk_wm_link(GUIWIN *win); + +GUIWIN *gemtk_wm_unlink(GUIWIN *win); + +short gemtk_wm_dispatch_event(EVMULT_IN *ev_in, EVMULT_OUT *ev_out, short msg[8]); + +void gemtk_wm_get_grect(GUIWIN *win, enum guwin_area_e mode, GRECT *dest); + +short gemtk_wm_get_toolbar_edit_obj(GUIWIN *win); + +short gemtk_wm_get_handle(GUIWIN *win); + +uint32_t gemtk_wm_get_state(GUIWIN *win); + +void gemtk_wm_set_toolbar(GUIWIN *win, OBJECT *toolbar, short idx, + uint32_t flags); + +void gemtk_wm_set_event_handler(GUIWIN *win,gemtk_wm_event_handler_f cb); + +void gemtk_wm_set_user_data(GUIWIN *win, void *data); + +void * gemtk_wm_get_user_data(GUIWIN *win); + +struct gemtk_wm_scroll_info_s * gemtk_wm_get_scroll_info(GUIWIN *win); + +void gemtk_wm_set_scroll_grid(GUIWIN * win, short x, short y); + +void gemtk_wm_set_content_units(GUIWIN * win, short x, short y); + +void gemtk_wm_set_form(GUIWIN *win, OBJECT *tree, short index); + +void gemtk_wm_set_toolbar_size(GUIWIN *win, uint16_t s); + +void gemtk_wm_set_toolbar_edit_obj(GUIWIN *win, uint16_t obj, short kreturn); + +void gemtk_wm_set_toolbar_redraw_func(GUIWIN *win, gemtk_wm_redraw_f func); + +bool gemtk_wm_update_slider(GUIWIN *win, short mode); + +void gemtk_wm_scroll(GUIWIN *gw, short orientation, int units, bool refresh); + +void gemtk_wm_send_msg(GUIWIN *win, short msgtype, short a, short b, short c, + short d); + +short gemtk_wm_exec_msg(GUIWIN *win, short msg_type, short a, short b, short c, + short d); + +void gemtk_wm_exec_redraw(GUIWIN *win, GRECT *area); + +VdiHdl gemtk_wm_get_vdi_handle(GUIWIN *win); + +short getm_wm_get_toolbar_edit_obj(GUIWIN *win); + +bool gemtk_wm_has_intersection(GUIWIN *win, GRECT *work); + +void gemtk_wm_toolbar_redraw(GUIWIN *win, uint16_t msg, GRECT *clip); + +void gemtk_wm_form_redraw(GUIWIN *gw, GRECT *clip); + +void gemtk_wm_clear(GUIWIN *win); + +/* -------------------------------------------------------------------------- */ +/* AES SCROLLER MODULE */ +/* -------------------------------------------------------------------------- */ + +/* -------------------------------------------------------------------------- */ +/* AES TABS MODULE */ +/* -------------------------------------------------------------------------- */ + +/* -------------------------------------------------------------------------- */ +/* AES OBJECT TREE TOOLS */ +/* -------------------------------------------------------------------------- */ +char gemtk_obj_set_str_safe(OBJECT * tree, short idx, const char *txt); +char *gemtk_obj_get_text(OBJECT * tree, short idx); +GRECT * gemtk_obj_screen_rect(OBJECT * tree, short obj); +bool gemtk_obj_is_inside(OBJECT * tree, short obj, GRECT *area); +OBJECT *gemtk_obj_get_tree(int idx); +void gemtk_obj_mouse_sprite(OBJECT *tree, int index); +OBJECT *gemtk_obj_tree_copy(OBJECT *tree); +OBJECT * gemtk_obj_create_popup_tree(const char **items, int nitems, + char * selected, bool horizontal, + int max_width, int max_height); +void gemtk_obj_destroy_popup_tree(OBJECT * popup); +#endif // GEMTK_H_INCLUDED diff --git a/frontends/atari/gemtk/guiwin.c b/frontends/atari/gemtk/guiwin.c new file mode 100644 index 000000000..ea0f8f917 --- /dev/null +++ b/frontends/atari/gemtk/guiwin.c @@ -0,0 +1,1430 @@ +/* + * Copyright 2012 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdint.h> +#include <stdbool.h> +#include <assert.h> + +#include <gem.h> +#include <gemx.h> +#include <cflib.h> + +#include "gemtk.h" +#include "vaproto.h" + +//#define DEBUG_PRINT(x) printf x +#define DEBUG_PRINT(x) + +struct gemtk_window_s { + + /** The AES handle of the window */ + short handle; + + /** the generic event handler function for events passed to the client */ + gemtk_wm_event_handler_f handler_func; + + /** The toolbar redraw function, if any */ + gemtk_wm_redraw_f toolbar_redraw_func; + + /** window configuration */ + uint32_t flags; + + /** window state */ + uint32_t state; + + /** AES Tree used as toolbar */ + OBJECT *toolbar; + + /** Current edit object selected in the toolbar, if any. */ + short toolbar_edit_obj; + + /** Current selected object in the toolbar, if any. */ + short toolbar_focus_obj; + + /** Describes the start of the toolbar tree (usually 0) */ + short toolbar_idx; + + /** depending on the flag GEMTK_WM_FLAG_HAS_VTOOLBAR this defines the toolbar + height or the toolbar width (GEMTK_WM_FLAG_HAS_VTOOLBAR means width). + */ + short toolbar_size; + + /** AES Object tree to be used for windowed dialogs. */ + OBJECT *form; + + /** Current form edit object, if any. */ + short form_edit_obj; + + /** Current form focus object, if any */ + short form_focus_obj; + + /** Describes the start of the form tree */ + short form_idx; + + /** Scroll state */ + struct gemtk_wm_scroll_info_s scroll_info; + + /** Arbitary data set by the user */ + void *user_data; + + /** linked list items */ + struct gemtk_window_s *next, *prev; +}; + +static GUIWIN * winlist; +static VdiHdl v_vdi_h = -1; +static short work_out[57]; + +static void move_rect(GUIWIN * win, GRECT *rect, int dx, int dy) +{ + INT16 xy[ 8]; + long dum = 0L; + GRECT g; + + VdiHdl vh = gemtk_wm_get_vdi_handle(win); + + while(!wind_update(BEG_UPDATE)); + graf_mouse(M_OFF, 0L); + + /* get intersection with screen area */ + wind_get_grect(0, WF_CURRXYWH, &g); + if(!rc_intersect(&g, rect)){ + goto error; + } + xy[0] = rect->g_x; + xy[1] = rect->g_y; + xy[2] = xy[0] + rect->g_w-1; + xy[3] = xy[1] + rect->g_h-1; + xy[4] = xy[0] + dx; + xy[5] = xy[1] + dy; + xy[6] = xy[2] + dx; + xy[7] = xy[3] + dy; + vro_cpyfm(vh, S_ONLY, xy, (MFDB *)&dum, (MFDB *)&dum); + +error: + graf_mouse(M_ON, 0L); + wind_update(END_UPDATE); +} + +/** +* Handles common events. +* returns 0 when the event was not handled, 1 otherwise. +*/ +static short preproc_wm(GUIWIN * gw, EVMULT_OUT *ev_out, short msg[8]) +{ + GRECT g, g_ro, g2; + short retval = 1; + int val = 1; + struct gemtk_wm_scroll_info_s *slid; + + switch(msg[0]) { + + case WM_HSLID: + gemtk_wm_get_grect(gw, GEMTK_WM_AREA_CONTENT, &g); + wind_set(gw->handle, WF_HSLIDE, msg[4], 0, 0, 0); + slid = gemtk_wm_get_scroll_info(gw); + val = (float)(slid->x_units-(g.g_w/slid->x_unit_px))/1000*(float)msg[4]; + if(val != slid->x_pos) { + if (val < slid->x_pos) { + val = -(MAX(0, slid->x_pos-val)); + } else { + val = val-slid->x_pos; + } + gemtk_wm_scroll(gw, GEMTK_WM_HSLIDER, val, false); + } + break; + + case WM_VSLID: + gemtk_wm_get_grect(gw, GEMTK_WM_AREA_CONTENT, &g); + wind_set(gw->handle, WF_VSLIDE, msg[4], 0, 0, 0); + slid = gemtk_wm_get_scroll_info(gw); + val = (float)(slid->y_units-(g.g_h/slid->y_unit_px))/1000*(float)msg[4]; + if(val != slid->y_pos) { + if (val < slid->y_pos) { + val = -(slid->y_pos - val); + } else { + val = val -slid->y_pos; + } + gemtk_wm_scroll(gw, GEMTK_WM_VSLIDER, val, false); + } + break; + + case WM_ARROWED: + if((gw->flags & GEMTK_WM_FLAG_CUSTOM_SCROLLING) == 0) { + + slid = gemtk_wm_get_scroll_info(gw); + gemtk_wm_get_grect(gw, GEMTK_WM_AREA_CONTENT, &g); + g_ro = g; + + switch(msg[4]) { + + case WA_UPPAGE: + /* scroll page up */ + gemtk_wm_scroll(gw, GEMTK_WM_VSLIDER, -(g.g_h/slid->y_unit_px), + true); + break; + + case WA_UPLINE: + /* scroll line up */ + gemtk_wm_scroll(gw, GEMTK_WM_VSLIDER, -1, true); + break; + + case WA_DNPAGE: + /* scroll page down */ + gemtk_wm_scroll(gw, GEMTK_WM_VSLIDER, g.g_h/slid->y_unit_px, + true); + break; + + case WA_DNLINE: + /* scroll line down */ + gemtk_wm_scroll(gw, GEMTK_WM_VSLIDER, +1, true); + break; + + case WA_LFPAGE: + /* scroll page left */ + gemtk_wm_scroll(gw, GEMTK_WM_HSLIDER, -(g.g_w/slid->x_unit_px), + true); + break; + + case WA_LFLINE: + /* scroll line left */ + gemtk_wm_scroll(gw, GEMTK_WM_HSLIDER, -1, + true); + break; + + case WA_RTPAGE: + /* scroll page right */ + gemtk_wm_scroll(gw, GEMTK_WM_HSLIDER, (g.g_w/slid->x_unit_px), + true); + break; + + case WA_RTLINE: + /* scroll line right */ + gemtk_wm_scroll(gw, GEMTK_WM_HSLIDER, 1, + true); + break; + + default: + break; + } + } + break; + + case WM_TOPPED: + wind_set(gw->handle, WF_TOP, 1, 0, 0, 0); + break; + + case WM_MOVED: + wind_get_grect(gw->handle, WF_CURRXYWH, &g); + wind_set(gw->handle, WF_CURRXYWH, msg[4], msg[5], g.g_w, g.g_h); + + if (gw->form) { + + gemtk_wm_get_grect(gw, GEMTK_WM_AREA_CONTENT, &g); + slid = gemtk_wm_get_scroll_info(gw); + + gw->form[gw->form_idx].ob_x = g.g_x - + (slid->x_pos * slid->x_unit_px); + + gw->form[gw->form_idx].ob_y = g.g_y - + (slid->y_pos * slid->y_unit_px); + } + + break; + + case WM_SIZED: + case WM_REPOSED: + wind_get_grect(gw->handle, WF_FULLXYWH, &g2); + wind_get_grect(gw->handle, WF_CURRXYWH, &g); + g.g_w = MIN(msg[6], g2.g_w); + g.g_h = MIN(msg[7], g2.g_h); + if(g2.g_w != g.g_w || g2.g_h != g.g_h) { + wind_set(gw->handle, WF_CURRXYWH, g.g_x, g.g_y, g.g_w, g.g_h); + if((gw->flags & GEMTK_WM_FLAG_CUSTOM_SCROLLING) == 0) { + if(gemtk_wm_update_slider(gw, GEMTK_WM_VH_SLIDER)) { + gemtk_wm_exec_redraw(gw, NULL); + } + } + } + + + break; + + case WM_FULLED: + wind_get_grect(DESKTOP_HANDLE, WF_WORKXYWH, &g); + wind_get_grect(gw->handle, WF_CURRXYWH, &g2); + if(g.g_w == g2.g_w && g.g_h == g2.g_h) { + wind_get_grect(gw->handle, WF_PREVXYWH, &g); + } + wind_set_grect(gw->handle, WF_CURRXYWH, &g); + if((gw->flags & GEMTK_WM_FLAG_CUSTOM_SCROLLING) == 0) { + if(gemtk_wm_update_slider(gw, GEMTK_WM_VH_SLIDER)) { + gemtk_wm_exec_redraw(gw, NULL); + } + } + break; + + case WM_ICONIFY: + wind_set(gw->handle, WF_ICONIFY, msg[4], msg[5], msg[6], msg[7]); + gw->state |= GEMTK_WM_STATUS_ICONIFIED; + break; + + case WM_UNICONIFY: + wind_set(gw->handle, WF_UNICONIFY, msg[4], msg[5], msg[6], msg[7]); + gw->state &= ~(GEMTK_WM_STATUS_ICONIFIED); + break; + + case WM_SHADED: + gw->state |= GEMTK_WM_STATUS_SHADED; + break; + + case WM_UNSHADED: + gw->state &= ~(GEMTK_WM_STATUS_SHADED); + break; + + case WM_REDRAW: + if ((gw->flags & GEMTK_WM_FLAG_CUSTOM_TOOLBAR) == 0 + && (gw->toolbar != NULL)) { + g.g_x = msg[4]; + g.g_y = msg[5]; + g.g_w = msg[6]; + g.g_h = msg[7]; + if((gw->state & GEMTK_WM_STATUS_ICONIFIED) == 0){ + gemtk_wm_toolbar_redraw(gw, WM_REDRAW, &g); + } + } + if (gw->form != NULL) { + g.g_x = msg[4]; + g.g_y = msg[5]; + g.g_w = msg[6]; + g.g_h = msg[7]; + gemtk_wm_form_redraw(gw, &g); + } + break; + + default: + retval = 0; + break; + + } + + return(retval); +} + +/** +* Preprocess mouse events +*/ +static short preproc_mu_button(GUIWIN * gw, EVMULT_OUT *ev_out, short msg[8]) +{ + short retval = 0, obj_idx = 0; + + DEBUG_PRINT(("preproc_mu_button\n")); + + // toolbar handling: + if ((gw->flags & GEMTK_WM_FLAG_CUSTOM_TOOLBAR) == 0 + && gw->toolbar != NULL) { + + GRECT tb_area; + + gemtk_wm_get_grect(gw, GEMTK_WM_AREA_TOOLBAR, &tb_area); + + if (POINT_WITHIN(ev_out->emo_mouse.p_x, + ev_out->emo_mouse.p_y, tb_area)) { + + gw->toolbar[gw->toolbar_idx].ob_x = tb_area.g_x; + gw->toolbar[gw->toolbar_idx].ob_y = tb_area.g_y; + obj_idx = objc_find(gw->toolbar, + gw->toolbar_idx, 8, + ev_out->emo_mouse.p_x, + ev_out->emo_mouse.p_y); + + gw->toolbar_focus_obj = obj_idx; + + DEBUG_PRINT(("Toolbar index: %d\n", obj_idx)); + if (obj_idx > -1 + && (gw->toolbar[obj_idx].ob_state & OS_DISABLED)== 0 + && ((gw->flags & GEMTK_WM_FLAG_CUSTOM_TOOLBAR) == 0)) { + + uint16_t type = (gw->toolbar[obj_idx].ob_type & 0xFF); + uint16_t nextobj; + + DEBUG_PRINT(("toolbar item type: %d, toolbar_edit_obj: %d\n", + type, gw->toolbar_edit_obj)); + // Report mouse click to the tree: + retval = form_wbutton(gw->toolbar, gw->toolbar_focus_obj, + ev_out->emo_mclicks, &nextobj, + gw->handle); + if (nextobj == obj_idx + && (type == G_FTEXT || type == G_FBOXTEXT)) { + gw->toolbar_edit_obj = obj_idx; + } + else { + gw->toolbar_edit_obj = -1; + } + } + + // send WM_TOOLBAR message + short oldevents = ev_out->emo_events; + short msg_out[8] = {WM_TOOLBAR, gl_apid, + 0, gw->handle, + obj_idx, ev_out->emo_mclicks, + ev_out->emo_kmeta, ev_out->emo_mbutton + }; + ev_out->emo_events = MU_MESAG; + // notify the window about toolbar click: + gw->handler_func(gw, ev_out, msg_out); + ev_out->emo_events = oldevents; + retval = 1; + } else { + if (gw->toolbar_edit_obj != -1) { + gw->toolbar_edit_obj = -1; + } + } + } + + if (gw->form != NULL) { + + GRECT content_area; + struct gemtk_wm_scroll_info_s *slid; + + DEBUG_PRINT(("preproc_mu_button: handling form click.\n")); + + gemtk_wm_get_grect(gw, GEMTK_WM_AREA_CONTENT, &content_area); + + if (POINT_WITHIN(ev_out->emo_mouse.p_x, + ev_out->emo_mouse.p_y, content_area)) { + + slid = gemtk_wm_get_scroll_info(gw); + + // adjust form position (considering window and scroll position): + gw->form[gw->form_idx].ob_x = content_area.g_x - + (slid->x_pos * slid->x_unit_px); + gw->form[gw->form_idx].ob_y = content_area.g_y - + (slid->y_pos * slid->y_unit_px); + + obj_idx = objc_find(gw->form, gw->form_idx, 8, + ev_out->emo_mouse.p_x, ev_out->emo_mouse.p_y); + gw->form_focus_obj = obj_idx; + DEBUG_PRINT(("Window Form click, obj: %d\n", gw->form_focus_obj)); + if (obj_idx > -1 + && (gw->form[obj_idx].ob_state & OS_DISABLED)== 0) { + + uint16_t type = (gw->form[obj_idx].ob_type & 0xFF); + uint16_t nextobj; + + DEBUG_PRINT(("type: %d\n", type)); + + retval = form_wbutton(gw->form, gw->form_focus_obj, + ev_out->emo_mclicks, &nextobj, + gw->handle); + + if (nextobj == obj_idx + && (type == G_FTEXT || type == G_FBOXTEXT)) { + gw->form_edit_obj = obj_idx; + } + else { + gw->form_edit_obj = -1; + } + + short oldevents = ev_out->emo_events; + short msg_out[8] = { GEMTK_WM_WM_FORM_CLICK, gl_apid, + 0, gw->handle, + gw->form_focus_obj, ev_out->emo_mclicks, + ev_out->emo_kmeta, 0 + }; + ev_out->emo_events = MU_MESAG; + // notify the window about form click: + gw->handler_func(gw, ev_out, msg_out); + ev_out->emo_events = oldevents; + retval = 1; + evnt_timer(150); + } + } + else { + gw->form_edit_obj = -1; + + } + } + + return(retval); +} + +/** +* Preprocess keyboard events (for forms/toolbars) +*/ +static short preproc_mu_keybd(GUIWIN * gw, EVMULT_OUT *ev_out, short msg[8]) +{ + short retval = 0; + + if ((gw->toolbar != NULL) && (gw->toolbar_edit_obj > -1)) { + + short next_edit_obj = gw->toolbar_edit_obj; + short next_char = -1; + short edit_idx; + short r; + + DEBUG_PRINT(("%s, gw: %p, toolbar_edit_obj: %d\n", __FUNCTION__, gw, + gw->toolbar_edit_obj)); + + r = form_wkeybd(gw->toolbar, gw->toolbar_edit_obj, next_edit_obj, + ev_out->emo_kreturn, + &next_edit_obj, &next_char, gw->handle); + + if (next_edit_obj != gw->toolbar_edit_obj) { + gemtk_wm_set_toolbar_edit_obj(gw, next_edit_obj, + ev_out->emo_kreturn); + } else { + if (next_char > 13) { + r = objc_wedit(gw->toolbar, gw->toolbar_edit_obj, + ev_out->emo_kreturn, &edit_idx, + EDCHAR, gw->handle); + } + } + //retval = 1; + /*gemtk_wm_send_msg(gw, GEMTK_WM_WM_FORM_KEY, gw->toolbar_edit_obj, + ev_out->emo_kreturn, 0, 0);*/ + } + + if((gw->form != NULL) && (gw->form_edit_obj > -1) ) { + + short next_edit_obj = gw->form_edit_obj; + short next_char = -1; + short edit_idx; + short r; + + r = form_wkeybd(gw->form, gw->form_edit_obj, next_edit_obj, + ev_out->emo_kreturn, + &next_edit_obj, &next_char, gw->handle); + + if (next_edit_obj != gw->form_edit_obj) { + + if(gw->form_edit_obj != -1) { + objc_wedit(gw->form, gw->form_edit_obj, + ev_out->emo_kreturn, &edit_idx, + EDEND, gw->handle); + } + + gw->form_edit_obj = next_edit_obj; + + objc_wedit(gw->form, gw->form_edit_obj, + ev_out->emo_kreturn, &edit_idx, + EDINIT, gw->handle); + } else { + if(next_char > 13) + r = objc_wedit(gw->form, gw->form_edit_obj, + ev_out->emo_kreturn, &edit_idx, + EDCHAR, gw->handle); + } + } + return(retval); +} + +/** +* Default toolbar redraw function +*/ +static void std_toolbar_redraw(GUIWIN *gw, uint16_t msg, GRECT *clip) +{ + GRECT g, tb_area; + + gemtk_wm_get_grect(gw, GEMTK_WM_AREA_TOOLBAR, &tb_area); + + assert(gw->toolbar); + assert(gw->toolbar_idx >= 0); + + // Update object position: + gw->toolbar[gw->toolbar_idx].ob_x = tb_area.g_x; + gw->toolbar[gw->toolbar_idx].ob_y = tb_area.g_y; + gw->toolbar[gw->toolbar_idx].ob_width = tb_area.g_w; + gw->toolbar[gw->toolbar_idx].ob_height = tb_area.g_h; + + wind_get_grect(gw->handle, WF_FIRSTXYWH, &g); + while (g.g_h > 0 || g.g_w > 0) { + if(rc_intersect(clip, &g)) { + objc_draw(gw->toolbar, gw->toolbar_idx, 8, g.g_x, g.g_y, + g.g_w, g.g_h); + + } + wind_get_grect(gw->handle, WF_NEXTXYWH, &g); + } +} + +/** +* Event Dispatcher function. The guiwin API doesn't own an event loop, +* so you have to inform it for every event that you want it to handle. +*/ +short gemtk_wm_dispatch_event(EVMULT_IN *ev_in, EVMULT_OUT *ev_out, short msg[8]) +{ + GUIWIN *dest; + short retval = 0; + bool handler_called = false; + + if( (ev_out->emo_events & MU_MESAG) != 0 ) { + DEBUG_PRINT(("gemtk_wm_handle_event_multi_fast: %d (%x)\n", msg[0], + msg[0])); + switch (msg[0]) { + case WM_REDRAW: + case WM_CLOSED: + case WM_TOPPED: + case WM_ARROWED: + case WM_HSLID: + case WM_VSLID: + case WM_FULLED: + case WM_SIZED: + case WM_REPOSED: + case WM_MOVED: + case WM_NEWTOP: + case WM_UNTOPPED: + case WM_ONTOP: + case WM_BOTTOM: + case WM_ICONIFY: + case WM_UNICONIFY: + case WM_ALLICONIFY: + case WM_TOOLBAR: + case AP_DRAGDROP: + case AP_TERM: + case AP_TFAIL: + dest = gemtk_wm_find(msg[3]); + if (dest) { + DEBUG_PRINT(("Found WM_ dest: %p (%d), flags: %d, cb: %p\n", + dest, dest->handle, dest->flags, + dest->handler_func)); + if (dest->flags&GEMTK_WM_FLAG_PREPROC_WM) { + retval = preproc_wm(dest, ev_out, msg); + if(((retval == 0)||(dest->flags&GEMTK_WM_FLAG_RECV_PREPROC_WM))) { + retval = dest->handler_func(dest, ev_out, msg); + handler_called = true; + } + } else { + if (dest->handler_func) { + retval = dest->handler_func(dest, ev_out, msg); + handler_called = true; + } + } + + } + break; +// TODO: check code with Thing! Desktop +/* + We receive VA_PROTOSTATUS but AV_START doesn't seem to cause + an TeraDesk response. Check if something happens with Thing! + Desktop. + + case VA_PROTOSTATUS: + case VA_VIEWED: + case AV_STARTED: + gemtk_av_dispatch(msg); + break; +*/ + } + } else { + + short h_aes; + h_aes = wind_find(ev_out->emo_mouse.p_x, ev_out->emo_mouse.p_y); + if(h_aes > 0 && (ev_out->emo_events != MU_TIMER)) { + + dest = gemtk_wm_find(h_aes); + + if (dest == NULL || dest->handler_func == NULL) + return(0); + + DEBUG_PRINT(("Found Event receiver GUIWIN: %p (%d), flags: %d, cb: %p\n", + dest, dest->handle, dest->flags, dest->handler_func)); + + if ((ev_out->emo_events & MU_BUTTON) != 0) { + DEBUG_PRINT(("gemtk_wm_handle_event_multi_fast: MU_BUTTON -> " + "%d / %d\n", ev_out->emo_mouse.p_x, + ev_out->emo_mouse.p_y)); + retval = preproc_mu_button(dest, ev_out, msg); + if(retval != 0) { + handler_called = true; + } + } + + if ((ev_out->emo_events & MU_KEYBD)) { + DEBUG_PRINT(("gemtk_wm_handle_event_multi_fast: MU_KEYBD -> %x\n", + ev_out->emo_kreturn)); + retval = preproc_mu_keybd(dest, ev_out, msg); + if(retval != 0) { + handler_called = true; + } + } + + if (handler_called==false) { + retval = dest->handler_func(dest, ev_out, msg); + } + } + } + + return(retval); +} + +/** +* Initialises the guiwin API +*/ +short gemtk_wm_init(void) +{ + if(v_vdi_h == -1) { + short dummy; + short work_in[12] = {Getrez()+2,1,1,1,1,1,1,1,1,1,2,1}; + v_vdi_h=graf_handle(&dummy, &dummy, &dummy, &dummy); + v_opnvwk(work_in, &v_vdi_h, work_out); + } + return(0); +} + +void gemtk_wm_exit(void) +{ + v_clsvwk(v_vdi_h); +} + +/** +* Adds and AES handle to the guiwin list and creates and GUIWIN management +* structure. +* +* \param handle The AES handle +* \param flags Creation flags, configures how the AES window is handled +* \param cb event handler function for that window +*/ +GUIWIN * gemtk_wm_add(short handle, uint32_t flags, gemtk_wm_event_handler_f cb) +{ + + GUIWIN *win = calloc(1, sizeof(GUIWIN)); + + assert(win!=NULL); + DEBUG_PRINT(("gemtk_wm_add: %d, %p, cb: %p\n", handle, win, cb)); + + win->handle = handle; + win->handler_func = cb; + win->flags = flags; + gemtk_wm_link(win); + + DEBUG_PRINT(("Added guiwin: %p, tb: %p\n", win, win->toolbar)); + return(win); +} + +/** +* Returns an GUIWIN* for AES handle, when that AES window is managed by gemtk_wm +*/ +GUIWIN *gemtk_wm_find(short handle) +{ + GUIWIN *g; + DEBUG_PRINT(("guiwin search handle: %d\n", handle)); + for (g = winlist; g != NULL; g=g->next) { + if(g->handle == handle) { + DEBUG_PRINT(("guiwin found handle: %p\n", g)); + return(g); + } + } + return(NULL); +} + +void gemtk_wm_dump_window_info(GUIWIN *win) +{ + + + + char title[255]; + GRECT work_area; + GRECT curr_area; + GRECT gemtk_work_area; + GRECT gemtk_toolbar_area; + GRECT gemtk_free_area; + short handle; + struct gemtk_wm_scroll_info_s *slid; + + handle = gemtk_wm_get_handle(win); + + assert(handle); + + gemtk_wind_get_str(handle, WF_NAME, title, 255); + wind_get_grect(handle, WF_WORKXYWH, &work_area); + wind_get_grect(handle, WF_CURRXYWH, &curr_area); + gemtk_wm_get_grect(win, GEMTK_WM_AREA_CONTENT, &gemtk_free_area); + gemtk_wm_get_grect(win, GEMTK_WM_AREA_WORK, &gemtk_work_area); + gemtk_wm_get_grect(win, GEMTK_WM_AREA_TOOLBAR, &gemtk_toolbar_area); + slid = gemtk_wm_get_scroll_info(win); + + printf ("GEMTK Window: %p (AES handle: %d)\n", win, win->handle); + printf ("Title: %s\n", title); + GEMTK_DBG_GRECT ("WF_WORKXYWH: \n", &work_area) + GEMTK_DBG_GRECT ("WF_CURRXYWH: \n", &curr_area) + GEMTK_DBG_GRECT ("GEMTK_WM_AREA_CONTENT:\n", &gemtk_free_area) + GEMTK_DBG_GRECT ("GEMTK_WM_AREA_WORK:\n", &gemtk_work_area) + GEMTK_DBG_GRECT ("GEMTK_WM_AREA_TOOLBAR:\n", &gemtk_toolbar_area) + printf ("Slider X pos: %d\n", slid->x_pos); + printf ("Slider Y pos: %d\n", slid->y_pos); + printf ("Slider X units: %d\n", slid->x_unit_px); + printf ("Slider Y units: %d\n", slid->y_unit_px); + + +#undef DBG_GRECT +}; + +/** +* Check's if the pointer is managed by the guiwin API. +*/ +GUIWIN *gemtk_wm_validate_ptr(GUIWIN *win) +{ + GUIWIN *g; + for( g = winlist; g != NULL; g=g->next ) { + DEBUG_PRINT(("guiwin gemtk_wm_validate_ptr check: %p\n", g)); + if(g == win) { + DEBUG_PRINT(("gemtk_wm_validate_ptr valid: %p\n", g)); + return(g); + } + } + return(NULL); +} + +/** +* Add the GUIWIN to the list of handled windows. +*/ +GUIWIN *gemtk_wm_link(GUIWIN *win) +{ + /* Make sure the window is not linked: */ + GUIWIN *win_val = gemtk_wm_validate_ptr(win); + if(win_val){ + DEBUG_PRINT(("GUIWIN %p is already linked!\n", win)); + return(NULL); + } + + if (winlist == NULL) { + winlist = win; + win->next = NULL; + win->prev = NULL; + } else { + GUIWIN *tmp = winlist; + while( tmp->next != NULL ) { + tmp = tmp->next; + } + tmp->next = win; + win->prev = tmp; + win->next = NULL; + } + return(win); +} + +/** +* Remove the GUIWIN from the list of handled windows. +*/ +GUIWIN *gemtk_wm_unlink(GUIWIN *win) +{ + GUIWIN * win_val; + + /* Make sure the window is linked: */ + win_val = gemtk_wm_validate_ptr(win); + if (win_val == NULL){ + DEBUG_PRINT(("GUIWIN %p is not linked!\n", win)); + return(NULL); + } + + + /* unlink the window: */ + if(win->prev != NULL ) { + win->prev->next = win->next; + } else { + winlist = win->next; + } + if (win->next != NULL) { + win->next->prev = win->prev; + } + return(win); +} + +/** +* Remove an GUIWIN from the list of managed windows and free the GUIWIN. +* Call this when the AES window is closed or deleted. +*/ +short gemtk_wm_remove(GUIWIN *win) +{ + gemtk_wm_unlink(win); + DEBUG_PRINT(("guiwin free: %p\n", win)); + free(win); + return(0); +} + +/** Calculate & get a well known area within the GUIWIN. +* \param win The GUIWIN ptr. +* \param mode Specifies the area to retrieve. +* \param dest The calculated rectangle. +*/ +void gemtk_wm_get_grect(GUIWIN *win, enum guwin_area_e mode, GRECT *dest) +{ + + assert(win != NULL); + + wind_get_grect(win->handle, WF_WORKXYWH, dest); + + if (mode == GEMTK_WM_AREA_CONTENT) { + GRECT tb_area; + gemtk_wm_get_grect(win, GEMTK_WM_AREA_TOOLBAR, &tb_area); + if (win->flags & GEMTK_WM_FLAG_HAS_VTOOLBAR) { + dest->g_x += tb_area.g_w; + dest->g_w -= tb_area.g_w; + } + else { + dest->g_y += tb_area.g_h; + dest->g_h -= tb_area.g_h; + } + } else if (mode == GEMTK_WM_AREA_TOOLBAR) { + if (win->toolbar) { + if (win->flags & GEMTK_WM_FLAG_HAS_VTOOLBAR) { + dest->g_w = win->toolbar_size; + } else { + dest->g_h = win->toolbar_size; + } + } + else { + dest->g_w = 0; + dest->g_h = 0; + } + } +} + + +/** +* Scroll the content area (GEMTK_WM_AREA_CONTENT) in the specified dimension +* (GEMTK_WM_VSLIDER, GEMTK_WM_HSLIDER) +* \param win The GUIWIN +* \param orientation GEMTK_WM_VSLIDER or GEMTK_WM_HSLIDER +* \param units the amout to scroll (pass negative values to scroll up) +* \param refresh Sliders will be updated when this flag is set +*/ +void gemtk_wm_scroll(GUIWIN *win, short orientation, int units, bool refresh) +{ + struct gemtk_wm_scroll_info_s *slid = gemtk_wm_get_scroll_info(win); + int oldpos = 0, newpos = 0, vis_units=0, pix = 0; + int abs_pix = 0; + GRECT *redraw=NULL, g, g_ro; + + gemtk_wm_get_grect(win, GEMTK_WM_AREA_CONTENT, &g); + g_ro = g; + + if (orientation == GEMTK_WM_VSLIDER) { + pix = units*slid->y_unit_px; + abs_pix = abs(pix); + oldpos = slid->y_pos; + vis_units = g.g_h/slid->y_unit_px; + newpos = slid->y_pos = MIN(slid->y_units-vis_units, + MAX(0, slid->y_pos+units)); + if(newpos < 0) { + newpos = slid->y_pos = 0; + } + if(oldpos == newpos) + return; + + if (units>=vis_units || gemtk_wm_has_intersection(win, &g_ro)) { + // send complete redraw + redraw = &g_ro; + } else { + // only adjust ypos when scrolling down: + if(pix < 0 ) { + // blit screen area: + g.g_h -= abs_pix; + move_rect(win, &g, 0, abs_pix); + g.g_y = g_ro.g_y; + g.g_h = abs_pix; + redraw = &g; + } else { + // blit screen area: + g.g_y += abs_pix; + g.g_h -= abs_pix; + move_rect(win, &g, 0, -abs_pix); + g.g_y = g_ro.g_y + g_ro.g_h - abs_pix; + g.g_h = abs_pix; + redraw = &g; + } + } + } else { + pix = units*slid->x_unit_px; + abs_pix = abs(pix); + oldpos = slid->x_pos; + vis_units = g.g_w/slid->x_unit_px; + newpos = slid->x_pos = MIN(slid->x_units-vis_units, + MAX(0, slid->x_pos+units)); + + if(newpos < 0) { + newpos = slid->x_pos = 0; + } + + if(oldpos == newpos) + return; + if (units>=vis_units || gemtk_wm_has_intersection(win, &g_ro)) { + // send complete redraw + redraw = &g_ro; + } else { + // only adjust ypos when scrolling down: + if(pix < 0 ) { + // blit screen area: + g.g_w -= abs_pix; + move_rect(win, &g, abs_pix, 0); + g.g_x = g_ro.g_x; + g.g_w = abs_pix; + redraw = &g; + } else { + // blit screen area: + g.g_x += abs_pix; + g.g_w -= abs_pix; + move_rect(win, &g, -abs_pix, 0); + g.g_x = g_ro.g_x + g_ro.g_w - abs_pix; + g.g_w = abs_pix; + redraw = &g; + } + } + } + + if (refresh) { + gemtk_wm_update_slider(win, orientation); + } + + if ((redraw != NULL) && (redraw->g_h > 0)) { + gemtk_wm_exec_redraw(win, redraw); + } +} + +/** +* Refresh the sliders of the window. +* \param win the GUIWIN +* \param mode bitmask, valid bits: GEMTK_WM_VSLIDER, GEMTK_WM_HSLIDER +*/ +bool gemtk_wm_update_slider(GUIWIN *win, short mode) +{ + GRECT viewport; + struct gemtk_wm_scroll_info_s * slid; + unsigned long size, pos; + int old_x, old_y; + + short handle = gemtk_wm_get_handle(win); + gemtk_wm_get_grect(win, GEMTK_WM_AREA_CONTENT, &viewport); + slid = gemtk_wm_get_scroll_info(win); + + old_x = slid->x_pos; + old_y = slid->y_pos; + + // TODO: check if the window has sliders of that direction...? + + if((mode & GEMTK_WM_VSLIDER) && (slid->y_unit_px > 0)) { + if ( slid->y_units < (long)viewport.g_h/slid->y_unit_px) { + size = 1000L; + } else + size = MAX( 50L, (unsigned long)viewport.g_h*1000L/ + (unsigned long)(slid->y_unit_px*slid->y_units)); + wind_set(handle, WF_VSLSIZE, (int)size, 0, 0, 0); + + if (slid->y_units > (long)viewport.g_h/slid->y_unit_px) { + pos = (unsigned long)slid->y_pos *1000L/ + (unsigned long)(slid->y_units-viewport.g_h/slid->y_unit_px); + wind_set(handle, WF_VSLIDE, (int)pos, 0, 0, 0); + } else if (slid->y_pos) { + slid->y_pos = 0; + wind_set(handle, WF_VSLIDE, 0, 0, 0, 0); + } + } + if((mode & GEMTK_WM_HSLIDER) && (slid->x_unit_px > 0)) { + if ( slid->x_units < (long)viewport.g_w/slid->x_unit_px) + size = 1000L; + else + size = MAX( 50L, (unsigned long)viewport.g_w*1000L/ + (unsigned long)(slid->x_unit_px*slid->x_units)); + wind_set(handle, WF_HSLSIZE, (int)size, 0, 0, 0); + + if( slid->x_units > (long)viewport.g_w/slid->x_unit_px) { + pos = (unsigned long)slid->x_pos*1000L/ + (unsigned long)(slid->x_units-viewport.g_w/slid->x_unit_px); + wind_set(handle, WF_HSLIDE, (int)pos, 0, 0, 0); + } else if (slid->x_pos) { + slid->x_pos = 0; + wind_set(handle, WF_HSLIDE, 0, 0, 0, 0); + } + } + + if(old_x != slid->x_pos || old_y != slid->y_pos) { + return(true); + } + return(false); +} + +/** +* Return the AES handle for the GUIWIN. +*/ +short gemtk_wm_get_handle(GUIWIN *win) +{ + return(win->handle); +} + +/** +* Return the VDI handle for an GUIWIN. +*/ +VdiHdl gemtk_wm_get_vdi_handle(GUIWIN *win) +{ + return(v_vdi_h); +} + +/** +* Returns the state bitmask of the window +*/ +uint32_t gemtk_wm_get_state(GUIWIN *win) +{ + return(win->state); +} + +/** +* Set and new event handler function. +*/ +void gemtk_wm_set_event_handler(GUIWIN *win,gemtk_wm_event_handler_f cb) +{ + win->handler_func = cb; +} + +/** +* Configure the window so that it shows an toolbar or at least reserves +* an area to draw an toolbar. +* \param win The GUIWIN +* \param toolbar the AES form +* \param idx index within the toolbar tree (0 in most cases...) +* \param flags optional configuration flags +*/ +//TODO: document flags +void gemtk_wm_set_toolbar(GUIWIN *win, OBJECT *toolbar, short idx, uint32_t flags) +{ + win->toolbar = toolbar; + win->toolbar_idx = idx; + win->toolbar_edit_obj = -1; + if (flags & GEMTK_WM_FLAG_HAS_VTOOLBAR) { + win->flags |= GEMTK_WM_FLAG_HAS_VTOOLBAR; + win->toolbar_size = win->toolbar[idx].ob_width; + } + else { + win->toolbar_size = win->toolbar[idx].ob_height; + } + gemtk_wm_set_toolbar_redraw_func(win, std_toolbar_redraw); +} + +/** Update width/height of the toolbar region +* \param win the GUIWIN +* \param s the width or height, depending on the flag GEMTK_WM_FLAG_HAS_VTOOLBAR +*/ +void gemtk_wm_set_toolbar_size(GUIWIN *win, uint16_t s) +{ + win->toolbar_size = s; +} + +short gemtk_wm_get_toolbar_edit_obj(GUIWIN *win) +{ + return(win->toolbar_edit_obj); +} + +/** Set the current active edit object */ +void gemtk_wm_set_toolbar_edit_obj(GUIWIN *win, uint16_t obj, short kreturn) +{ + short edit_idx; + + DEBUG_PRINT(("%s, win: %p, obj: %d, kret: %d\n", __FUNCTION__, + win, obj, kreturn)); + + if (obj != win->toolbar_edit_obj) { + + DEBUG_PRINT(("%s, current edit obj: %d\n", __FUNCTION__, + win->toolbar_edit_obj)); + + if(win->toolbar_edit_obj != -1) { + objc_wedit(win->toolbar, win->toolbar_edit_obj, kreturn, &edit_idx, + EDEND, win->handle); + } + + win->toolbar_edit_obj = obj; + + objc_wedit(win->toolbar, win->toolbar_edit_obj, kreturn, &edit_idx, + EDINIT, win->handle); + } else { + DEBUG_PRINT(("%s, nothing to do!\n", __FUNCTION__)); + } +} + +/** Set an custom toolbar redraw function which is called instead of +* default drawing routine. +* \param win the GUIWIN +* \param func the custom redraw function +*/ +void gemtk_wm_set_toolbar_redraw_func(GUIWIN *win, gemtk_wm_redraw_f func) +{ + win->toolbar_redraw_func = func; +} + +/** +* Attach an arbitary pointer to the GUIWIN +*/ +void gemtk_wm_set_user_data(GUIWIN *win, void *data) +{ + win->user_data = data; +} + +/** +* Retrieve the user_data pointer attached to the GUIWIN. +*/ +void *gemtk_wm_get_user_data(GUIWIN *win) +{ + return(win->user_data); +} + +/** Get the scroll management structure for a GUIWIN +*/ +struct gemtk_wm_scroll_info_s *gemtk_wm_get_scroll_info(GUIWIN *win) { + return(&win->scroll_info); +} + +/** +* Get the amount of content dimensions within the window +* which is calculated by using the scroll_info attached to the GUIWIN. +*/ +void gemtk_wm_set_scroll_grid(GUIWIN * win, short x, short y) +{ + struct gemtk_wm_scroll_info_s *slid = gemtk_wm_get_scroll_info(win); + + assert(slid != NULL); + + slid->y_unit_px = x; + slid->x_unit_px = y; +} + + +/** Set the size of the content measured in content units +* \param win the GUIWIN +* \param x horizontal size +* \param y vertical size +*/ +void gemtk_wm_set_content_units(GUIWIN * win, short x, short y) +{ + struct gemtk_wm_scroll_info_s *slid = gemtk_wm_get_scroll_info(win); + + assert(slid != NULL); + + slid->x_units = x; + slid->y_units = y; +} + +/** Send an Message to a GUIWIN using AES message pipe +* \param win the GUIWIN which shall receive the message +* \param msg_type the WM_ message definition +* \param a the 4th parameter to appl_write +* \param b the 5th parameter to appl_write +* \param c the 6th parameter to appl_write +* \param d the 7th parameter to appl_write +*/ +void gemtk_wm_send_msg(GUIWIN *win, short msg_type, short a, short b, short c, + short d) +{ + short msg[8]; + + msg[0] = msg_type; + msg[1] = gl_apid; + msg[2] = 0; + msg[3] = (win != NULL) ? win->handle : 0; + msg[4] = a; + msg[5] = b; + msg[6] = c; + msg[7] = d; + + appl_write(gl_apid, 16, &msg); +} + +/** Directly execute an Message to a GUIWIN using the internal dispatcher function. +* This only works for managed windows which have the, + GEMTK_WM_FLAG_PREPROC_WM flag set. + This call does not send any AES messages. +* \param win the GUIWIN which shall receive the message +* \param msg_type the WM_ message definition +* \param a the 4th parameter to appl_write +* \param b the 5th parameter to appl_write +* \param c the 6th parameter to appl_write +* \param d the 7th parameter to appl_write +*/ +short gemtk_wm_exec_msg(GUIWIN *win, short msg_type, short a, short b, short c, + short d) +{ + short msg[8], retval; + + EVMULT_OUT event_out; + + msg[0] = msg_type; + msg[1] = gl_apid; + msg[2] = 0; + msg[3] = win->handle; + msg[4] = a; + msg[5] = b; + msg[6] = c; + msg[7] = d; + + event_out.emo_events = MU_MESAG; + retval = preproc_wm(win, &event_out, msg); + if (retval == 0 || (win->flags & GEMTK_WM_FLAG_PREPROC_WM) != 0){ + retval = win->handler_func(win, &event_out, msg); + } + + return(retval); +} + +void gemtk_wm_exec_redraw(GUIWIN *win, GRECT *area) +{ + GRECT work; + + if (area == NULL) { + gemtk_wm_get_grect(win, GEMTK_WM_AREA_WORK, &work); + if (work.g_w < 1 || work.g_h < 1) { + if (win->toolbar != NULL) { + gemtk_wm_get_grect(win, GEMTK_WM_AREA_TOOLBAR, &work); + if (work.g_w < 1 || work.g_h < 1) { + return; + } + } + } + area = &work; + } + + gemtk_wm_exec_msg(win, WM_REDRAW, area->g_x, area->g_y, area->g_w, + area->g_h); +} + +/** Attach an AES FORM to the GUIWIN, similar feature like the toolbar +*/ +void gemtk_wm_set_form(GUIWIN *win, OBJECT *tree, short index) +{ + DEBUG_PRINT(("Setting form %p (%d) for window %p\n", tree, index, win)); + win->form = tree; + win->form_edit_obj = -1; + win->form_focus_obj = -1; + win->form_idx = index; +} + +/** Checks if a GUIWIN is overlapped by other windows. +*/ +bool gemtk_wm_has_intersection(GUIWIN *win, GRECT *work) +{ + GRECT area, mywork; + bool retval = true; + + if (work == NULL) { + gemtk_wm_get_grect(win, GEMTK_WM_AREA_CONTENT, &mywork); + work = &mywork; + } + + wind_get_grect(win->handle, WF_FIRSTXYWH, &area); + while (area.g_w) { + //GRECT * ptr = &area; + if (RC_WITHIN(work, &area)) { + retval = false; + } + wind_get_grect(win->handle, WF_NEXTXYWH, &area); + } + + return(retval); +} + +/** Execute an toolbar redraw +* \param msg specifies the AES message which initiated the redraw, or 0 when +* the function was called without AES message context. +*/ +void gemtk_wm_toolbar_redraw(GUIWIN *gw, uint16_t msg, GRECT *clip) +{ + GRECT tb_area, tb_area_ro; + + gemtk_wm_get_grect(gw, GEMTK_WM_AREA_TOOLBAR, &tb_area_ro); + + if(clip == NULL) { + clip = &tb_area_ro; + } + + tb_area = tb_area_ro; + + if (rc_intersect(clip, &tb_area)) { + gw->toolbar_redraw_func(gw, msg, &tb_area); + } +} + +/** Execute FORM redraw +*/ +void gemtk_wm_form_redraw(GUIWIN *gw, GRECT *clip) +{ + GRECT area, area_ro, g; + struct gemtk_wm_scroll_info_s *slid; + //int new_x, new_y, old_x, old_y; + + DEBUG_PRINT(("gemtk_wm_form_redraw\n")); + + // calculate form coordinates, include scrolling: + gemtk_wm_get_grect(gw, GEMTK_WM_AREA_CONTENT, &area_ro); + slid = gemtk_wm_get_scroll_info(gw); + + // Update form position: + gw->form[gw->form_idx].ob_x = area_ro.g_x - (slid->x_pos * slid->x_unit_px); + gw->form[gw->form_idx].ob_y = area_ro.g_y - (slid->y_pos * slid->y_unit_px); + + if(clip == NULL) { + clip = &area_ro; + } + + area = area_ro; + + /* Walk the AES rectangle list and redraw the visible areas of the window:*/ + if(rc_intersect(clip, &area)) { + + wind_get_grect(gw->handle, WF_FIRSTXYWH, &g); + while (g.g_h > 0 || g.g_w > 0) { + if(rc_intersect(&area, &g)) { + objc_draw(gw->form, gw->form_idx, 8, g.g_x, g.g_y, + g.g_w, g.g_h); + + } + wind_get_grect(gw->handle, WF_NEXTXYWH, &g); + } + } +} + + +/** Fill the content area with white color +*/ +void gemtk_wm_clear(GUIWIN *win) +{ + GRECT area, g; + short pxy[4]; + VdiHdl vh; + + vh = gemtk_wm_get_vdi_handle(win); + + if(win->state & GEMTK_WM_STATUS_ICONIFIED) { + // also clear the toolbar area when iconified: + gemtk_wm_get_grect(win, GEMTK_WM_AREA_WORK, &area); + } else { + gemtk_wm_get_grect(win, GEMTK_WM_AREA_CONTENT, &area); + } + + vsf_interior(vh, FIS_SOLID); + vsf_color(vh, 0); + vswr_mode(vh, MD_REPLACE); + wind_get_grect(win->handle, WF_FIRSTXYWH, &g); + while (g.g_h > 0 || g.g_w > 0) { + if(rc_intersect(&area, &g)) { + pxy[0] = g.g_x; + pxy[1] = g.g_y; + pxy[2] = g.g_x+g.g_w-1; + pxy[3] = g.g_y+g.g_h-1; + v_bar(vh, pxy); + } + wind_get_grect(win->handle, WF_NEXTXYWH, &g); + } +} diff --git a/frontends/atari/gemtk/guiwin.h b/frontends/atari/gemtk/guiwin.h new file mode 100644 index 000000000..6daf16ca9 --- /dev/null +++ b/frontends/atari/gemtk/guiwin.h @@ -0,0 +1,4 @@ +#ifndef OPKG_GUI_GUIWIN_H +#define OPKG_GUI_GUIWIN_ + +#endif /* OPKG_GUIWIN_H */ diff --git a/frontends/atari/gemtk/msgbox.c b/frontends/atari/gemtk/msgbox.c new file mode 100644 index 000000000..89ca75a46 --- /dev/null +++ b/frontends/atari/gemtk/msgbox.c @@ -0,0 +1,110 @@ +/*
+ * Copyright 2013 Ole Loots <ole@monochrom.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <gem.h> +#include "gemtk.h" + +#ifndef min +# define min(x,y) ((x<y) ? x : y ) +#endif + +/*** + * Display an message box + * + * \param type Valid values: GEMTK_MSG_BOX_CONFIRM, GEMTK_MSG_BOX_ALERT + * \param msg The message / query to display + * \return 0 on "No" + * + */ +short gemtk_msg_box_show(short type, const char * msg) +{ + #define GEMTK_MSG_BOX_STR_SIZE 256 + short retval=0, i=0, z=0, l=0; + char c; + int len_msg = strlen(msg); + + // TODO: localize strings + const char *str_yes = "Yes"; + const char *str_no = "No"; + const char *str_ok = "OK"; + char msg_box_str[GEMTK_MSG_BOX_STR_SIZE]; + char *dst = msg_box_str; + + memset(msg_box_str, 0, GEMTK_MSG_BOX_STR_SIZE); + + strncat(msg_box_str, "[1]", GEMTK_MSG_BOX_STR_SIZE); + strncat(msg_box_str, "[", GEMTK_MSG_BOX_STR_SIZE); + + dst = msg_box_str + strlen(msg_box_str); + + for (i=0; i<min(len_msg,40*5); i++) { + + c = msg[i]; + + if(c==0) + break; + + if (z==40) { + if(l==4){ + break; + } + z = 0; + l++; + *dst = (char)'|'; + dst++; + } + + if ((c=='\r' || c=='\n') && *dst != '|') { + if(l==4){ + break; + } + z = 0; + l++; + *dst = '|'; + dst++; + } + else { + z++; + *dst = c; + dst++; + } + } + strncat(msg_box_str, "][", GEMTK_MSG_BOX_STR_SIZE); + + if(type == GEMTK_MSG_BOX_CONFIRM){ + strncat(msg_box_str, str_yes, GEMTK_MSG_BOX_STR_SIZE); + strncat(msg_box_str, "|", GEMTK_MSG_BOX_STR_SIZE); + strncat(msg_box_str, str_no, GEMTK_MSG_BOX_STR_SIZE); + } else { + strncat(msg_box_str, str_ok, GEMTK_MSG_BOX_STR_SIZE); + } + strncat(msg_box_str, "]", GEMTK_MSG_BOX_STR_SIZE); + + retval = form_alert(type, msg_box_str); + if(type == GEMTK_MSG_BOX_CONFIRM){ + if(retval != 1){ + retval = 0; + } + } + return(retval); + + #undef GEMTK_MSG_BOX_STR_SIZE +} diff --git a/frontends/atari/gemtk/msgbox.h b/frontends/atari/gemtk/msgbox.h new file mode 100644 index 000000000..7a46900ef --- /dev/null +++ b/frontends/atari/gemtk/msgbox.h @@ -0,0 +1,5 @@ +#ifndef GUIMSG_H_INCLUDED
+#define GUIMSG_H_INCLUDED + +
+#endif // GUIMSG_H_INCLUDED
diff --git a/frontends/atari/gemtk/objc.c b/frontends/atari/gemtk/objc.c new file mode 100644 index 000000000..855413e0b --- /dev/null +++ b/frontends/atari/gemtk/objc.c @@ -0,0 +1,522 @@ +/* + * Copyright 2013 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Module Description: + * + * AES Object tree tools. + * + */ + +#include <assert.h> +#include "gemtk.h" + +char *gemtk_obj_get_text(OBJECT * tree, short idx) +{ + static char p[]=""; + + switch (tree[idx].ob_type & 0x00FF) { + case G_BUTTON: + case G_STRING: + case G_TITLE: + return( tree[idx].ob_spec.free_string); + case G_TEXT: + case G_BOXTEXT: + case G_FTEXT: + case G_FBOXTEXT: + return (tree[idx].ob_spec.tedinfo->te_ptext); + case G_ICON: + case G_CICON: + return (tree[idx].ob_spec.iconblk->ib_ptext); + break; + + default: + break; + } + return (p); +} + +static void set_text(OBJECT *obj, short idx, char * text, int len) +{ + char spare[255]; + + if( len > 254 ) + len = 254; + if( text != NULL ) { + strncpy(spare, text, 254); + } else { + strcpy(spare, ""); + } + + set_string(obj, idx, spare); +} + +char gemtk_obj_set_str_safe(OBJECT * tree, short idx, const char *txt) +{ + char spare[204]; + short type = 0; + short maxlen = 0; + + + type = (tree[idx].ob_type & 0xFF); + if (type == G_FTEXT || type == G_FBOXTEXT) { + TEDINFO *ted = ((TEDINFO *)get_obspec(tree, idx)); + maxlen = ted->te_tmplen+1; + if (maxlen > 200) { + maxlen = 200; + } else if (maxlen < 0) { + maxlen = 0; + } + } else { + assert((type == G_FTEXT) || (type == G_FBOXTEXT)); + } + + snprintf(spare, maxlen, "%s", txt); + set_string(tree, idx, spare); + + return(0); +} + +OBJECT *gemtk_obj_get_tree(int idx) +{ + + OBJECT *tree; + + rsrc_gaddr(R_TREE, idx, &tree); + + return tree; +} + +bool gemtk_obj_is_inside(OBJECT * tree, short obj, GRECT *area) +{ + GRECT obj_screen; + bool ret = false; + + objc_offset(tree, obj, &obj_screen.g_x, &obj_screen.g_y); + obj_screen.g_w = tree[obj].ob_width; + obj_screen.g_h = tree[obj].ob_height; + + ret = RC_WITHIN(&obj_screen, area); + + return(ret); +} + +GRECT * gemtk_obj_screen_rect(OBJECT * tree, short obj) +{ + static GRECT obj_screen; + + get_objframe(tree, obj, &obj_screen); + + return(&obj_screen); +} + + +void gemtk_obj_mouse_sprite(OBJECT *tree, int index) +{ + MFORM mform; + int dum; + + if ((tree[index].ob_type & 0xFF) != G_ICON) + return; + + dum = tree[index].ob_spec.iconblk->ib_char; + mform . mf_nplanes = 1; + mform . mf_fg = (dum>>8)&0x0F; + mform . mf_bg = dum>>12; + mform . mf_xhot = 0; /* to prevent the mform to "jump" on the */ + mform . mf_yhot = 0; /* screen (zebulon rules!) */ + + for( dum = 0; dum<16; dum ++) { + mform . mf_mask[dum] = tree[index].ob_spec.iconblk->ib_pmask[dum]; + mform . mf_data[dum] = tree[index].ob_spec.iconblk->ib_pdata[dum]; + } + graf_mouse(USER_DEF, &mform); +} + + +/* + * gemtk_obj_tree_copy + * + * Copy a complete object-tree including all substructures (optional). + * + * CAUTION: The object-tree *must* have the LASTOB-flag (0x20) set in + * it's physically last member. + * + * BUG: Up to now tree_copy won't copy the color-icon-structure, + * because I'm too lazy ;) Maybe I'll do that one day. If you need it + * urgently, contact me and force me to work... Btw, this doesn't mean + * that G_CICONs won't be copied at all, but the copied tree will + * share the CICONBLKs with the original. + * + * Input: + * tree: Pointer to tree which should be copied + * what: Specifies what substructures should be copied, too (see the + * C_xxx-definitions in tree-copy.h for details) + * + * Output: + * NULL: Tree couldn't be copied (due to lack of memory) + * otherwise: Pointer to copied tree, use free to dealloc it's memory + */ +OBJECT *gemtk_obj_tree_copy(OBJECT *tree) +{ + int16_t i, objects; + size_t to_malloc, size; + OBJECT *new_tree; + char *area; + + /* Calculate the number of bytes we need for the new tree */ + to_malloc = (size_t) 0; + for (i = 0;;) { + + /* Size of the OBJECT-structure itself */ + to_malloc += sizeof(OBJECT); + + switch (tree[i].ob_type & 0xff) { + case G_TEXT: + case G_BOXTEXT: + case G_FTEXT: + case G_FBOXTEXT: + /* Size of a TEDINFO-structure */ + to_malloc += sizeof(TEDINFO); + + /* Sizes of the strings in the TEDINFO-structure */ + to_malloc += (size_t)tree[i].ob_spec.tedinfo->te_txtlen; + to_malloc += (size_t)tree[i].ob_spec.tedinfo->te_txtlen; + to_malloc += (size_t)tree[i].ob_spec.tedinfo->te_tmplen; + break; + + case G_IMAGE: + + /* Size of the BITBLK-structure */ + to_malloc += sizeof(BITBLK); + + /* Size of the image-data in the BITBLK-structure */ + to_malloc += (size_t)((int32_t)tree[i].ob_spec.bitblk->bi_wb * + (int32_t)tree[i].ob_spec.bitblk->bi_hl); + + break; + + case G_USERDEF: + /* Size of the USERBLK-structure */ + to_malloc += sizeof(USERBLK); + break; + + case G_BUTTON: + case G_STRING: + case G_TITLE: + /* Size of the string (with one null character at the end) */ + to_malloc += strlen(tree[i].ob_spec.free_string) + 1L; + break; + + case G_ICON: + /* Size of the ICONBLK-structure */ + to_malloc += sizeof(BITBLK); + + /* Sizes of icon-data, icon-mask and icon-text */ + to_malloc += (size_t)((int32_t)tree[i].ob_spec.iconblk->ib_wicon * + (int32_t)tree[i].ob_spec.iconblk->ib_hicon / + 4L + 1L + + (int32_t)strlen(tree[i].ob_spec.iconblk->ib_ptext)); + + break; + } + + /* If the size is odd, make it even */ + if ((long)to_malloc & 1) + to_malloc++; + + /* Exit if we've reached the last object in the tree */ + if (tree[i].ob_flags & OF_LASTOB) + break; + + i++; + } + + objects = i + 1; + + /* If there's not enough memory left for the new tree, return NULL */ + if ((new_tree = (OBJECT *)calloc(1, to_malloc)) == NULL) { + return(NULL); + } + + /* + * area contains a pointer to the area where we copy the structures to + */ + area = (char *)((int32_t)new_tree+(int32_t)objects*(int32_t)sizeof(OBJECT)); + + for (i = 0; i < objects; i++) { + + /* Copy the contents of the OBJECT-structure */ + new_tree[i] = tree[i]; + + /* This was added to assure true copies of the object type */ + new_tree[i].ob_type = tree[i].ob_type; + + switch (tree[i].ob_type & 0xff) { + case G_TEXT: + case G_BOXTEXT: + case G_FTEXT: + case G_FBOXTEXT: + + /* Copy the contents of the TEDINFO-structure */ + *(TEDINFO *)area = *tree[i].ob_spec.tedinfo; + new_tree[i].ob_spec.tedinfo = (TEDINFO *)area; + area += sizeof(TEDINFO); + + /* Copy the strings in the TEDINFO-structure */ + strncpy(area, tree[i].ob_spec.tedinfo->te_ptext, + tree[i].ob_spec.tedinfo->te_txtlen); + new_tree[i].ob_spec.tedinfo->te_ptext = area; + area += tree[i].ob_spec.tedinfo->te_txtlen; + strncpy(area, tree[i].ob_spec.tedinfo->te_ptmplt, + tree[i].ob_spec.tedinfo->te_tmplen); + new_tree[i].ob_spec.tedinfo->te_ptmplt = area; + area += tree[i].ob_spec.tedinfo->te_tmplen; + strncpy(area, tree[i].ob_spec.tedinfo->te_pvalid, + tree[i].ob_spec.tedinfo->te_txtlen); + new_tree[i].ob_spec.tedinfo->te_pvalid = area; + area += tree[i].ob_spec.tedinfo->te_txtlen; + + break; + + case G_IMAGE: + + /* Copy the contents of the BITBLK-structure */ + *(BITBLK *)area = *tree[i].ob_spec.bitblk; + new_tree[i].ob_spec.bitblk = (BITBLK *)area; + area += sizeof(BITBLK); + + /* Copy the image-data */ + size = (size_t)((int32_t)tree[i].ob_spec.bitblk->bi_wb * + (int32_t)tree[i].ob_spec.bitblk->bi_hl); + memcpy(area, tree[i].ob_spec.bitblk->bi_pdata, size); + new_tree[i].ob_spec.bitblk->bi_pdata = (int16_t *)area; + area += size; + + break; + + case G_USERDEF: + + /* Copy the contents of the USERBLK-structure */ + *(USERBLK *)area = *tree[i].ob_spec.userblk; + new_tree[i].ob_spec.userblk = (USERBLK *)area; + area += sizeof(USERBLK); + + break; + + case G_BUTTON: + case G_STRING: + case G_TITLE: + + /* Copy the string */ + size = strlen(tree[i].ob_spec.free_string) + 1L; + strcpy(area, tree[i].ob_spec.free_string); + new_tree[i].ob_spec.free_string = area; + area += size; + + break; + + case G_ICON: + + /* Copy the contents of the ICONBLK-structure */ + *(ICONBLK *)area = *tree[i].ob_spec.iconblk; + new_tree[i].ob_spec.iconblk = (ICONBLK *)area; + area += sizeof(ICONBLK); + + size = (size_t)((int32_t)tree[i].ob_spec.iconblk->ib_wicon * + (int32_t)tree[i].ob_spec.iconblk->ib_hicon / + 8L); + /* Copy the mask-data */ + memcpy(area, tree[i].ob_spec.iconblk->ib_pmask, size); + new_tree[i].ob_spec.iconblk->ib_pmask = (int16_t *)area; + area += size; + + /* Copy the icon-data */ + memcpy(area, tree[i].ob_spec.iconblk->ib_pdata, size); + new_tree[i].ob_spec.iconblk->ib_pdata = (int16_t *)area; + area += size; + size = strlen(tree[i].ob_spec.iconblk->ib_ptext) + 1L; + + /* Copy the icon-string */ + strcpy(area, tree[i].ob_spec.iconblk->ib_ptext); + new_tree[i].ob_spec.iconblk->ib_ptext = area; + area += size; + + break; + } + + /* Assure that area contains an even address */ + if ((int32_t)area & 1) + area++; + } + + return(new_tree); +} + +/*** + * Create a simple OBJECT tree from a list of strings, to be used with menu_popup + * OBJECT ownership is passed to caller. + * Call gemtk_obj_destroy_popup_tree once the popup isn't needed anymore. + * + * \param items A list of string to be used as items + * \param nitems The number of items in the list + * \param selected The text of the selected item + * \param horizontal Set to true to render the tree horizontally + * \param max_width -1: autodetect width + * \param max_heigth -1: autodetect height (set to postive value when using a vertical scrolling popup) + * \return a pointer to the new OBJECT tree + */ +OBJECT * gemtk_obj_create_popup_tree(const char **items, int nitems, + char * selected, bool horizontal, + int max_width, int max_height) +{ + OBJECT * popup = NULL; + int box_width = 0; + int box_height = 0; + int char_width = 10; + int char_height = 16; + int item_height; // height of each item + + assert(items != NULL); + + item_height = char_height; + + /* Allocate room for n items and the root G_BOX: */ + popup = calloc(nitems+1, sizeof(OBJECT)); + assert(popup != null); + + for (int i=0; i<nitems; i++) { + + int len = strlen(items[i]); + + if (horizontal && (max_width<1)) { + box_width += (len * char_width)+4; + } + else if (!horizontal){ + /* Detect max width, used for vertical rendering: */ + if(len*char_width > box_width){ + box_width = (len+2) * char_width; + } + //if (max_height < 1) { + box_height += item_height; + //} + } + } + + if (max_width>0){ + box_width = max_width; + } + + if (horizontal) { + box_height = item_height; + } + else if(max_height > 0){ + // TODO: validate max_height, shrink values larger than screen height + //box_height = max_height; + } + +/* + printf("popup height: %d, popup width: %d\n", box_height, box_width); +*/ + + popup[0].ob_next = -1; /**< object's next sibling */ + popup[0].ob_head = 1; /**< head of object's children */ + popup[0].ob_tail = nitems; /**< tail of object's children */ + popup[0].ob_type = G_BOX; /**< type of object */ + popup[0].ob_flags = OF_FL3DBAK; /**< flags */ + popup[0].ob_state = OS_NORMAL; /**< state */ + popup[0].ob_spec.index = (long) 16650496L; /**< object-specific data */ + popup[0].ob_x = 0; /**< upper left corner of object */ + popup[0].ob_y = 0; /**< upper left corner of object */ + popup[0].ob_width = box_width; /**< width of obj */ + popup[0].ob_height = box_height; + + + + /* Add items to popup: */ + int xpos = 0, ypos = 0; + + for (int i=0; i<nitems; i++) { + + int state = OS_NORMAL; + int flags = OF_NONE; + int item_width; + char * string = calloc(1, strlen(items[i])+3); + + snprintf(string, strlen(items[i])+3, " %s", items[i]); + + if (selected != NULL) { + if (strcmp(selected, items[i]) == 0) { + state |= OS_CHECKED; + } + } + + if (i == nitems-1) { + flags |= OF_LASTOB; + } + + item_width = (horizontal) ? ((int)strlen(items[i])*char_width)+2 : box_width; +/* + printf("addin popup item \"%s\" (w: %d, h: %d, flags: %x) at %d/%d\n", items[i], + item_width, item_height, flags, + xpos, ypos); +*/ + + popup[i+1].ob_next = ((flags&OF_LASTOB) != 0) ? 0 : i+2; /**< object's next sibling */ + popup[i+1].ob_head = -1; /**< head of object's children */ + popup[i+1].ob_tail = -1; /**< tail of object's children */ + popup[i+1].ob_type = G_STRING; /**< type of object */ + popup[i+1].ob_flags = flags; /**< flags */ + popup[i+1].ob_state = state; /**< state */ + popup[i+1].ob_spec.free_string = string; /**< object-specific data */ + popup[i+1].ob_x = xpos; /**< upper left corner of object */ + popup[i+1].ob_y = ypos; /**< upper left corner of object */ + popup[i+1].ob_width = item_width; /**< width of obj */ + popup[i+1].ob_height = item_height; + + if (horizontal) { + xpos += item_width; + } + else { + ypos += item_height; + } + + } + + return(popup); +} + +/*** + * Free memory of an OBJECT tree created with gemtk_obj_create_popup_tree. + * + * \param popup The tree to destroy + */ +void gemtk_obj_destroy_popup_tree(OBJECT * popup) +{ + int i=0; + + while (1) { + if (popup[i].ob_type == G_STRING) { + free(popup[i+1].ob_spec.free_string); + } + if((popup[i].ob_flags & OF_LASTOB) != OF_LASTOB){ + break; + } + i++; + } + + free(popup); +} diff --git a/frontends/atari/gemtk/objc.h b/frontends/atari/gemtk/objc.h new file mode 100644 index 000000000..6fa1072b7 --- /dev/null +++ b/frontends/atari/gemtk/objc.h @@ -0,0 +1,7 @@ +#ifndef GEMTK_OBJC_H +#define GEMTK_OBJC_H + + + +#endif // GEMTK_OBJC_H + diff --git a/frontends/atari/gemtk/redrawslots.c b/frontends/atari/gemtk/redrawslots.c new file mode 100644 index 000000000..ee5627daf --- /dev/null +++ b/frontends/atari/gemtk/redrawslots.c @@ -0,0 +1,123 @@ +/*
+ * Copyright 2011 Ole Loots <ole@monochrom.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */ + +#include <stdbool.h> +#define WITH_RECT +#include "gemtk.h" +#undef WITH_RECT + +void redraw_slots_init(struct s_redrw_slots * slots, short size) +{ + // TODO: allocate slots dynamically! + slots->size = MIN( MAX_REDRW_SLOTS , size); + slots->areas_used = 0; +} + +void redraw_slots_free(struct s_redrw_slots * slots) +{ + // TOOD: free areas... +} + + +static inline bool rect_intersect( struct rect * box1, struct rect * box2 )
+{
+ if (box2->x1 < box1->x0)
+ return false;
+
+ if (box2->y1 < box1->y0)
+ return false;
+
+ if (box2->x0 > box1->x1)
+ return false;
+
+ if (box2->y0 > box1->y1)
+ return false;
+
+ return true;
+} + + +void redraw_slot_schedule_grect(struct s_redrw_slots * slots, GRECT *area, + bool force) +{ + redraw_slot_schedule(slots, area->g_x, area->g_y, + area->g_x + area->g_w, area->g_y + area->g_h, force); +} + +/*
+ schedule redraw coords.
+*/
+void redraw_slot_schedule(struct s_redrw_slots * slots, short x0, short y0, + short x1, short y1, bool force)
+{
+ int i = 0;
+ struct rect area;
+
+ area.x0 = x0;
+ area.y0 = y0;
+ area.x1 = x1;
+ area.y1 = y1;
+ + if (force == false) {
+ for (i=0; i<slots->areas_used; i++) {
+ if (slots->areas[i].x0 <= x0
+ && slots->areas[i].x1 >= x1
+ && slots->areas[i].y0 <= y0
+ && slots->areas[i].y1 >= y1) {
+ /* the area is already queued for redraw */
+ return;
+ } else {
+ if (rect_intersect(&slots->areas[i], &area )) {
+ slots->areas[i].x0 = MIN(slots->areas[i].x0, x0);
+ slots->areas[i].y0 = MIN(slots->areas[i].y0, y0);
+ slots->areas[i].x1 = MAX(slots->areas[i].x1, x1);
+ slots->areas[i].y1 = MAX(slots->areas[i].y1, y1);
+ return;
+ }
+ }
+ } + }
+
+ if (slots->areas_used < slots->size) {
+ slots->areas[slots->areas_used].x0 = x0;
+ slots->areas[slots->areas_used].x1 = x1;
+ slots->areas[slots->areas_used].y0 = y0;
+ slots->areas[slots->areas_used].y1 = y1;
+ slots->areas_used++;
+ } else {
+ /*
+ we are out of available slots, merge box with last slot
+ this is dumb... but also a very rare case.
+ */
+ slots->areas[slots->size-1].x0 = MIN(slots->areas[i].x0, x0);
+ slots->areas[slots->size-1].y0 = MIN(slots->areas[i].y0, y0);
+ slots->areas[slots->size-1].x1 = MAX(slots->areas[i].x1, x1);
+ slots->areas[slots->size-1].y1 = MAX(slots->areas[i].y1, y1);
+ }
+done: + return;
+} + +void redraw_slots_remove_area(struct s_redrw_slots * slots, int i) +{ + int x; + for(x = i+1; i<slots->areas_used; x++){ + slots->areas[x-1] = slots->areas[x]; + } + slots->areas_used--; +} diff --git a/frontends/atari/gemtk/redrawslots.h b/frontends/atari/gemtk/redrawslots.h new file mode 100644 index 000000000..9691fb4bc --- /dev/null +++ b/frontends/atari/gemtk/redrawslots.h @@ -0,0 +1,25 @@ +/*
+ * Copyright 2012 Ole Loots <ole@monochrom.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */ + + +#ifndef ATARI_REDRAW_SLOTS_H +#define ATARI_REDRAW_SLOTS_H + +#include <mt_gem.h> + +#endif diff --git a/frontends/atari/gemtk/utils.c b/frontends/atari/gemtk/utils.c new file mode 100644 index 000000000..63e6330ec --- /dev/null +++ b/frontends/atari/gemtk/utils.c @@ -0,0 +1,144 @@ +/* + * Copyright 2013 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <stdint.h> +#include <stdbool.h> +#include <mt_gem.h> +#include "gemtk.h" + +/* -------------------------------------------------------------------------- */ +/* GEM Utillity functions: */ +/* -------------------------------------------------------------------------- */ + +unsigned short _systype_v; +unsigned short _systype (void) +{ + int32_t * cptr = NULL; + _systype_v = SYS_TOS; + + cptr = (int32_t *)Setexc(0x0168, -1L); + if (cptr == NULL ) { + return _systype_v; /* stone old TOS without any cookie support */ + } + while (*cptr) { + if (*cptr == C_MgMc || *cptr == C_MgMx ) { + _systype_v = (_systype_v & ~0xF) | SYS_MAGIC; + } else if (*cptr == C_MiNT ) { + _systype_v = (_systype_v & ~0xF) | SYS_MINT; + } else if (*cptr == C_Gnva /* Gnva */ ) { + _systype_v |= SYS_GENEVA; + } else if (*cptr == C_nAES /* nAES */ ) { + _systype_v |= SYS_NAES; + } + cptr += 2; + } + if (_systype_v & SYS_MINT) { /* check for XaAES */ + short out = 0, u; + if (wind_get (0, (((short)'X') <<8)|'A', &out, &u,&u,&u) && out) { + _systype_v |= SYS_XAAES; + } + } + return _systype_v; +} + +bool gemtk_rc_intersect_ro(GRECT *a, GRECT *b) +{ + GRECT r1, r2; + + r1 = *a; + r2 = *b; + + return((bool)rc_intersect(&r1, &r2)); +} + + +typedef struct { + char *unshift; + char *shift; + char *capslock; +} KEYTAB; + +int gemtk_keybd2ascii( int keybd, int shift) +{ + + KEYTAB *key; + key = (KEYTAB *)Keytbl( (char*)-1, (char*)-1, (char*)-1); + return (shift)?key->shift[keybd>>8]:key->unshift[keybd>>8]; +} + + +void gemtk_clip_grect(VdiHdl vh, GRECT *rect) +{ + PXY pxy[2]; + + pxy[0].p_x = rect->g_x; + pxy[0].p_y = rect->g_y; + pxy[1].p_x = pxy[0].p_x + rect->g_w - 1; + pxy[1].p_y = pxy[0].p_y + rect->g_h - 1; + + vs_clip_pxy(vh, pxy); +} + +/** Send an Message to a GUIWIN using AES message pipe +* \param win the GUIWIN which shall receive the message +* \param msg_type the WM_ message definition +* \param a the 4th parameter to appl_write +* \param b the 5th parameter to appl_write +* \param c the 6th parameter to appl_write +* \param d the 7th parameter to appl_write +*/ +void gemtk_send_msg(short msg_type, short data2, short data3, short data4, + short data5, short data6, short data7) +{ + short msg[8]; + + msg[0] = msg_type; + msg[1] = gl_apid; + msg[2] = data2; + msg[3] = data3; + msg[4] = data4; + msg[5] = data5; + msg[6] = data6; + msg[7] = data7; + + appl_write(gl_apid, 16, &msg); +} + + +void gemtk_wind_get_str(short aes_handle, short mode, char *str, int len) +{ + + // TODO: remove or implement function + + if(len>255) { + len = 255; + } + + memset(str, 0, len); + return; + /* + + wind_get(aes_handle, mode, (short)(((unsigned long)tmp_str)>>16), + (short)(((unsigned long)tmp_str) & 0xffff), 0, 0); + + strncpy(str, tmp_str, len); + */ +} + + diff --git a/frontends/atari/gemtk/utils.h b/frontends/atari/gemtk/utils.h new file mode 100644 index 000000000..7ebbcf228 --- /dev/null +++ b/frontends/atari/gemtk/utils.h @@ -0,0 +1,5 @@ +#ifndef UTILS_H_INCLUDED
+#define UTILS_H_INCLUDED
+
+
+#endif // UTILS_H_INCLUDED
diff --git a/frontends/atari/gemtk/vaproto.c b/frontends/atari/gemtk/vaproto.c new file mode 100644 index 000000000..45e47225c --- /dev/null +++ b/frontends/atari/gemtk/vaproto.c @@ -0,0 +1,170 @@ +#include <limits.h> +#include <unistd.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <gem.h> + +#include "vaproto.h" +#include "gemtk.h" + +#ifndef NDEBUG +# define DEBUG_PRINT(x) printf x +#else +# define DEBUG_PRINT(x) +#endif + + +/* Global memory, at least 1024 bytes large: */ +static char *va_helpbuf; + +/* Desktop's AES ID: */ +static short av_shell_id = -1; + +/* What AV commands can desktop do? */ +static short av_shell_status = 0; + +/* The application name used for AV/VA messages: */ +static const char * av_clientname = "gemtk_av_app"; + + +static short get_avserver(void) +{ + short ret = -100; + const char * av_env = getenv("AVSERVER"); + if (av_env) { + char av_envname[9]; + strncpy(av_envname,av_env, 8); + av_envname[8] = '\0'; + while (strlen (av_envname) < 8) { + strcat(av_envname, " "); + } + ret = appl_find (av_envname); + } + return ret; +} + +/** + * initialitze the AV client API + * \param appname Name of the application passed to menu_register() + * \return returns 1 on success, otherwise an negative error code. + * + */ +int gemtk_av_init(const char *appname) +{ + short mode = 0x0003 /* prefer TT ram */ + | 0x0020; /* global accesible */ + + if(av_shell_id != -1) { + /* Already initialized */ + return(1); + } + + va_helpbuf = (char*)Mxalloc(1024, mode); + + if(va_helpbuf == NULL){ + gemtk_msg_box_show(GEMTK_MSG_BOX_ALERT, "Could not allocate AV memory!"); + return(-1); + } + + if(appname != NULL){ + av_clientname = appname; + } + + av_shell_id = get_avserver(); + DEBUG_PRINT(("AV Server ID: %d", av_shell_id)); + + gemtk_av_send(AV_PROTOKOLL, NULL, NULL); + + va_helpbuf[0] = '\0'; +} + +void gemtk_av_exit(void) +{ + if(av_shell_id == -1) { + /* Nothing to do */ + return; + } + + if (av_shell_status & AA_EXIT) { + /* AV server knows AV_EXIT */ + gemtk_av_send(AV_EXIT, NULL, NULL); + } + + if(va_helpbuf != NULL){ + free(va_helpbuf); + va_helpbuf = NULL; + } + + av_shell_id = -1; + +} + +bool gemtk_av_send (short message, const char * data1, const char * data2) +{ + short msg[8]; + short to_ap_id = av_shell_id; + + /* - 100 to ap id would be no AV server */ + if (to_ap_id == -100){ + return false; + } + + msg[0] = message; + msg[1] = gl_apid; + msg[7] = msg[6] = msg[5] = msg[4] = msg[3] = msg[2] = 0; + + switch (message) + { + case AV_EXIT: + msg[3] = gl_apid; + break; + case AV_PROTOKOLL: + msg[3] = VV_START | VV_ACC_QUOTING; + *(char **)(msg+6) = strcpy (va_helpbuf, av_clientname); + break; + case AV_STARTPROG: + DEBUG_PRINT(("AV_STARTPROG: %s (%s)\n", data1, data2)); + *(char **)(msg+3) = strcpy(va_helpbuf, data1); + *(char **)(msg+5) = strcpy(va_helpbuf, data2); + break; + case AV_VIEW: + DEBUG_PRINT(("AV_VIEW: %s (%d)\n", data1, (short)data2)); + *(char **)(msg+3) = strcpy(va_helpbuf, data1); + msg[5] = (short)data2; + break; + default: + return false; /* not supported */ + } + + return (appl_write (to_ap_id, 16, msg) > 0); +} + +bool gemtk_av_dispatch (short msg[8]) +{ + + if(av_shell_id == -1) + return(false); + + switch (msg[0]) { + case VA_PROTOSTATUS : + DEBUG_PRINT(("AV STATUS: %d for %d\n", msg[3], msg[1])); + if (msg[1] == av_shell_id) { + av_shell_status = msg[3]; + if(av_shell_status & AA_STARTPROG){ + printf(" AA_STARTPROG\n"); + } + } + break; + + default: + DEBUG_PRINT(("Unknown AV message: %d", msg[0])); + break; + } + + return(true); +} + + diff --git a/frontends/atari/gemtk/vaproto.h b/frontends/atari/gemtk/vaproto.h new file mode 100644 index 000000000..84e0ecf0b --- /dev/null +++ b/frontends/atari/gemtk/vaproto.h @@ -0,0 +1,121 @@ +#ifndef VAPROTO_H_INCLUDED
+#define VAPROTO_H_INCLUDED
+
+ +#define VAPRO 1 + +/* AES-Messages */ + +typedef enum +{ + AV_PROTOKOLL = 0x4700, + VA_PROTOSTATUS = 0x4701, + AV_GETSTATUS = 0x4703, + AV_STATUS = 0x4704, + VA_SETSTATUS = 0x4705, + AV_SENDKEY = 0x4710, + VA_START = 0x4711, + AV_ASKFILEFONT = 0x4712, + VA_FILEFONT = 0x4713, + AV_ASKCONFONT = 0x4714, + VA_CONFONT = 0x4715, + AV_ASKOBJECT = 0x4716, + VA_OBJECT = 0x4717, + AV_OPENCONSOLE = 0x4718, + VA_CONSOLEOPEN = 0x4719, + AV_OPENWIND = 0x4720, + VA_WINDOPEN = 0x4721, + AV_STARTPROG = 0x4722, + VA_PROGSTART = 0x4723, + AV_ACCWINDOPEN = 0x4724, + VA_DRAGACCWIND = 0x4725, + AV_ACCWINDCLOSED = 0x4726, + + AV_COPY_DRAGGED = 0x4728, + VA_COPY_COMPLETE = 0x4729, + AV_PATH_UPDATE = 0x4730, + AV_WHAT_IZIT = 0x4732, + VA_THAT_IZIT = 0x4733, + AV_DRAG_ON_WINDOW = 0x4734, + VA_DRAG_COMPLETE = 0x4735, + AV_EXIT = 0x4736, + AV_STARTED = 0x4738, + VA_FONTCHANGED = 0x4739, + AV_XWIND = 0x4740, + VA_XOPEN = 0x4741, + +/* Neue Messages seit dem 26.06.1995 */ + + AV_VIEW = 0x4751, + VA_VIEWED = 0x4752, + AV_FILEINFO = 0x4753, + VA_FILECHANGED = 0x4754, + AV_COPYFILE = 0x4755, + VA_FILECOPIED = 0x4756, + AV_DELFILE = 0x4757, + VA_FILEDELETED = 0x4758, + AV_SETWINDPOS = 0x4759, + VA_PATH_UPDATE = 0x4760, + VA_HIGH /* HR please always do this! */ +} AV_VA; + + +/* Objekttypen fr VA_THAT_IZIT */ + +enum +{ + VA_OB_UNKNOWN, + VA_OB_TRASHCAN, + VA_OB_SHREDDER, + VA_OB_CLIPBOARD, + VA_OB_FILE, + VA_OB_FOLDER, + VA_OB_DRIVE, + VA_OB_WINDOW, + VA_OB_NOTEPAD, + VA_OB_NOTE +}; + +typedef enum +{ + VV_SETSTATUS = 0x0001, + VV_START = 0x0002, + VV_STARTED = 0x0004, + VV_FONTCHANGED = 0x0008, + VV_ACC_QUOTING = 0x0010, + VV_PATH_UPDATE = 0x0020 +} av_va_give; + +typedef enum +{ /* mp[3]: */ + AA_SENDKEY = 0x0001, /* b0: MAGXDESK, THING */ + AA_ASKFILEFONT = 0x0002, /* b1: THING */ + AA_ASKCONFONT = 0x0004, /* b2: THING */ + AA_ASKOBJECT = 0x0008, + AA_OPENWIND = 0x0010, /* b4: MAGXDESK, THING */ + AA_STARTPROG = 0x0020, /* b5: MAGXDESK, THING */ + AA_ACCWIND = 0x0040, /* b6: THING */ + AA_STATUS = 0x0080, /* b7: THING */ + AA_COPY_DRAGGED= 0x0100, /* b8: THING */ + AA_DRAG_ON_WINDOW=0x0200, /* b9: MAGXDESK, THING */ + AA_EXIT = 0x0400, /* b10: MAGXDESK, THING */ + AA_XWIND = 0x0800, /* b11: MAGXDESK, THING */ + AA_FONTCHANGED = 0x1000, /* b2: THING */ + AA_STARTED = 0x2000, /* b13: MAGXDESK, THING */ + AA_SRV_QUOTING = 0x4000, /* b14: THING */ + AA_FILE = 0x8000, /* b15: THING */ + /* mp[4]: THING */ + AA_COPY = 0x0001, + AA_DELETE = 0x0002, + AA_VIEW = 0x0004, + AA_SETWINDPOS = 0x0008, + AA_COPYFILELINK= 0x0010, + AA_SENDCLICK = 0x0020 +} av_va_have; + +/* Makros zum Testen auf Quoting */ + +#define VA_ACC_QUOTING(a) ((a) & VV_ACC_QUOTING) +#define VA_SERVER_QUOTING(a) ((a) & AA_SRV_QUOTING)
+
+#endif // VAPROTO_H_INCLUDED
diff --git a/frontends/atari/gui.c b/frontends/atari/gui.c new file mode 100644 index 000000000..810c7646f --- /dev/null +++ b/frontends/atari/gui.c @@ -0,0 +1,1217 @@ +/* + * Copyright 2010 <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * \file + * + * Provides all the mandatory functions prefixed with gui_ for atari + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + +#include "utils/log.h" +#include "utils/messages.h" +#include "utils/corestrings.h" +#include "content/urldb.h" +#include "content/content.h" +#include "content/backing_store.h" +#include "content/hlcache.h" +#include "desktop/treeview.h" +#include "desktop/browser.h" +#include "desktop/gui_layout.h" +#include "desktop/gui_window.h" +#include "desktop/gui_clipboard.h" +#include "desktop/gui_fetch.h" +#include "desktop/gui_misc.h" +#include "desktop/netsurf.h" + +#include "atari/gemtk/gemtk.h" +#include "atari/gui.h" +#include "atari/misc.h" +#include "atari/findfile.h" +#include "atari/schedule.h" +#include "atari/rootwin.h" +#include "atari/statusbar.h" +#include "atari/toolbar.h" +#include "atari/hotlist.h" +#include "atari/cookies.h" +#include "atari/certview.h" +#include "atari/history.h" +#include "atari/login.h" +#include "atari/encoding.h" +#include "atari/res/netsurf.rsh" +#include "atari/plot/plot.h" +#include "atari/clipboard.h" +#include "atari/osspec.h" +#include "atari/search.h" +#include "atari/deskmenu.h" +#include "atari/download.h" +#include "atari/file.h" +#include "atari/filetype.h" +#include "atari/bitmap.h" +#include "atari/font.h" +#include "cflib.h" + +static bool atari_quit = false; + +struct gui_window *input_window = NULL; +struct gui_window *window_list = NULL; +void *h_gem_rsrc; +long next_poll; +bool rendering = false; +GRECT desk_area; + +/* Comandline / Options: */ +int option_window_width; +int option_window_height; +int option_window_x; +int option_window_y; + +/* Defaults to option_homepage_url, commandline options overwrites that value */ +const char *option_homepage_url; + +/* path to choices file: */ +char options[PATH_MAX]; + +EVMULT_IN aes_event_in = { + .emi_flags = MU_MESAG | MU_TIMER | MU_KEYBD | MU_BUTTON | MU_M1, + .emi_bclicks = 258, + .emi_bmask = 3, + .emi_bstate = 0, + .emi_m1leave = MO_ENTER, + .emi_m1 = {0,0,0,0}, + .emi_m2leave = 0, + .emi_m2 = {0,0,0,0}, + .emi_tlow = 0, + .emi_thigh = 0 +}; +EVMULT_OUT aes_event_out; +short aes_msg_out[8]; + +bool gui_window_get_scroll(struct gui_window *w, int *sx, int *sy); +static nserror gui_window_set_url(struct gui_window *w, nsurl *url); + +/** + * Core atari event processing. + */ +static void atari_poll(void) +{ + + struct gui_window *tmp; + short mx, my, dummy; + + aes_event_in.emi_tlow = schedule_run(); + + if(rendering){ + aes_event_in.emi_tlow = nsoption_int(atari_gui_poll_timeout); + } + + if(aes_event_in.emi_tlow < 0) { + aes_event_in.emi_tlow = 10000; + printf("long poll!\n"); + } + + if(input_window && input_window->root->redraw_slots.areas_used > 0) { + window_process_redraws(input_window->root); + } + + + graf_mkstate(&mx, &my, &dummy, &dummy); + aes_event_in.emi_m1.g_x = mx; + aes_event_in.emi_m1.g_y = my; + evnt_multi_fast(&aes_event_in, aes_msg_out, &aes_event_out); + if(gemtk_wm_dispatch_event(&aes_event_in, &aes_event_out, aes_msg_out) == 0) { + if( (aes_event_out.emo_events & MU_MESAG) != 0 ) { + LOG("WM: %d\n", aes_msg_out[0]); + switch(aes_msg_out[0]) { + + case MN_SELECTED: + LOG("Menu Item: %d\n", aes_msg_out[4]); + deskmenu_dispatch_item(aes_msg_out[3], aes_msg_out[4]); + break; + + case AP_TERM: + atari_quit = true; + break; + default: + break; + } + } + if((aes_event_out.emo_events & MU_KEYBD) != 0) { + uint16_t nkc = gem_to_norm( (short)aes_event_out.emo_kmeta, + (short)aes_event_out.emo_kreturn); + deskmenu_dispatch_keypress(aes_event_out.emo_kreturn, + aes_event_out.emo_kmeta, nkc); + } + } + + tmp = window_list; + while(tmp){ + if(tmp->root->redraw_slots.areas_used > 0){ + window_process_redraws(tmp->root); + } + tmp = tmp->next; + } + + /** @todo implement generic treeview redraw function. */ + /** @todo rename hl to atari_hotlist or create getter for it... */ + + atari_treeview_flush_redraws(); +} + +/** + * Create and open a gui window for a browsing context. + * + * \param bw bw to create gui_window for + * \param existing an existing gui_window, may be NULL + * \param flags flags for gui window creation + * \return gui window, or NULL on error + * + * If GW_CREATE_CLONE flag is set existing is non-NULL. + * + * The created gui_window must include a reference to the browser + * window passed in the bw param. + */ +static struct gui_window * +gui_window_create(struct browser_window *bw, + struct gui_window *existing, + gui_window_create_flags flags) +{ + struct gui_window *gw=NULL; + LOG("gw: %p, BW: %p, existing %p, flags: %d\n", gw, bw, existing, (int)flags); + + gw = calloc(1, sizeof(struct gui_window)); + if (gw == NULL) + return NULL; + + LOG("new window: %p, bw: %p\n", gw, bw); + window_create(gw, bw, existing, WIDGET_STATUSBAR|WIDGET_TOOLBAR|WIDGET_RESIZE\ + |WIDGET_SCROLL); + if (gw->root->win) { + GRECT pos = { + option_window_x, option_window_y, + option_window_width, option_window_height + }; + gui_window_set_url(gw, corestring_nsurl_about_blank); + gui_window_set_pointer(gw, BROWSER_POINTER_DEFAULT); + gui_set_input_gui_window(gw); + window_open(gw->root, gw, pos); + } + + /* add the window to the window list: */ + if( window_list == NULL ) { + window_list = gw; + gw->next = NULL; + gw->prev = NULL; + } else { + struct gui_window * tmp = window_list; + while( tmp->next != NULL ) { + tmp = tmp->next; + } + tmp->next = gw; + gw->prev = tmp; + gw->next = NULL; + } + + /* Loose focus: */ + window_set_focus(gw->root, WIDGET_NONE, NULL ); + + /* trigger on-focus event (select all text): */ + window_set_focus(gw->root, URL_WIDGET, NULL); + + /* delete selection: */ + toolbar_key_input(gw->root->toolbar, NK_DEL); + + return( gw ); + +} + +/** + * Destroy previously created gui window + * + * \param gw The gui window to destroy. + */ +void gui_window_destroy(struct gui_window *gw) +{ + if (gw == NULL) + return; + + LOG("%s\n", __FUNCTION__); + + if (input_window == gw) { + gui_set_input_gui_window(NULL); + } + + nsatari_search_session_destroy(gw->search); + free(gw->browser); + free(gw->status); + free(gw->title); + free(gw->url); + + /* unlink the window: */ + if(gw->prev != NULL ) { + gw->prev->next = gw->next; + } else { + window_list = gw->next; + } + if( gw->next != NULL ) { + gw->next->prev = gw->prev; + } + + window_unref_gui_window(gw->root, gw); + + free(gw); + gw = NULL; + + if(input_window == NULL) { + gw = window_list; + while( gw != NULL ) { + if(gw->root) { + gui_set_input_gui_window(gw); + break; + } + gw = gw->next; + } + } +} + +/** + * Find the current dimensions of a browser window's content area. + * + * \param w gui_window to measure + * \param width receives width of window + * \param height receives height of window + * \param scaled whether to return scaled values + */ +static void +gui_window_get_dimensions(struct gui_window *w, + int *width, + int *height, + bool scaled) +{ + if (w == NULL) + return; + GRECT rect; + window_get_grect(w->root, BROWSER_AREA_CONTENT, &rect); + *width = rect.g_w; + *height = rect.g_h; +} + +/** + * Set the title of a window. + * + * \param gw window to update + * \param title new window title + */ +static void gui_window_set_title(struct gui_window *gw, const char *title) +{ + if (gw == NULL) + return; + + if (gw->root) { + + int l; + char * conv; + l = strlen(title)+1; + if (utf8_to_local_encoding(title, l-1, &conv) == NSERROR_OK ) { + l = MIN((uint32_t)atari_sysinfo.aes_max_win_title_len, strlen(conv)); + if(gw->title == NULL) + gw->title = malloc(l); + else + gw->title = realloc(gw->title, l); + + strncpy(gw->title, conv, l); + free( conv ); + } else { + l = MIN((size_t)atari_sysinfo.aes_max_win_title_len, strlen(title)); + if(gw->title == NULL) + gw->title = malloc(l); + else + gw->title = realloc(gw->title, l); + strncpy(gw->title, title, l); + } + gw->title[l] = 0; + if(input_window == gw) + window_set_title(gw->root, gw->title); + } +} + +/* exported interface documented in atari/gui.h */ +void atari_window_set_status(struct gui_window *w, const char *text) +{ + int l; + if (w == NULL || text == NULL) + return; + + assert(w->root); + + l = strlen(text)+1; + if(w->status == NULL) + w->status = malloc(l); + else + w->status = realloc(w->status, l); + + strncpy(w->status, text, l); + w->status[l] = 0; + + if(input_window == w) + window_set_stauts(w->root, (char*)text); +} + +static void atari_window_reformat(struct gui_window *gw) +{ + int width = 0, height = 0; + + if (gw != NULL) { + gui_window_get_dimensions(gw, &width, &height, true); + browser_window_reformat(gw->browser->bw, false, width, height); + } +} + +static void gui_window_redraw_window(struct gui_window *gw) +{ + CMP_BROWSER b; + GRECT rect; + if (gw == NULL) + return; + b = gw->browser; + window_get_grect(gw->root, BROWSER_AREA_CONTENT, &rect); + window_schedule_redraw_grect(gw->root, &rect); +} + +static void gui_window_update_box(struct gui_window *gw, const struct rect *rect) +{ + GRECT area; + struct gemtk_wm_scroll_info_s *slid; + + if (gw == NULL) + return; + + slid = gemtk_wm_get_scroll_info(gw->root->win); + + window_get_grect(gw->root, BROWSER_AREA_CONTENT, &area); + area.g_x += rect->x0 - (slid->x_pos * slid->x_unit_px); + area.g_y += rect->y0 - (slid->y_pos * slid->y_unit_px); + area.g_w = rect->x1 - rect->x0; + area.g_h = rect->y1 - rect->y0; + //dbg_grect("update box", &area); + window_schedule_redraw_grect(gw->root, &area); +} + +bool gui_window_get_scroll(struct gui_window *w, int *sx, int *sy) +{ + if (w == NULL) + return false; + + window_get_scroll(w->root, sx, sy); + + return( true ); +} + +static void gui_window_set_scroll(struct gui_window *w, int sx, int sy) +{ + if ( (w == NULL) + || (w->browser->bw == NULL) + || (!browser_window_has_content(w->browser->bw))) + return; + + LOG("scroll (gui_window: %p) %d, %d\n", w, sx, sy); + window_scroll_by(w->root, sx, sy); + return; + +} + +/** + * Update the extent of the inside of a browser window to that of the + * current content. + * + * It seems this method is called when content size got adjusted, so + * that we can adjust scroll info. We also have to call it when tab + * change occurs. + * + * \param gw gui_window to update the extent of + */ +static void gui_window_update_extent(struct gui_window *gw) +{ + + if(browser_window_has_content(gw->browser->bw)) { + /** @todo store content size. */ + if(window_get_active_gui_window(gw->root) == gw) { + int width, height; + GRECT area; + browser_window_get_extents(gw->browser->bw, false, &width, &height); + window_set_content_size(gw->root, width, height); + window_update_back_forward(gw->root); + window_get_grect(gw->root, BROWSER_AREA_CONTENT, &area); + window_schedule_redraw_grect(gw->root, &area); + } + } +} + + +/** + * set the pointer shape + */ +void gui_window_set_pointer(struct gui_window *gw, gui_pointer_shape shape) +{ + if (gw == NULL) + return; + + switch (shape) { + case GUI_POINTER_POINT: /* link */ + gw->cursor = &gem_cursors.hand; + break; + + case GUI_POINTER_MENU: + gw->cursor = &gem_cursors.menu; + break; + + case GUI_POINTER_CARET: /* input */ + gw->cursor = &gem_cursors.ibeam; + break; + + case GUI_POINTER_CROSS: + gw->cursor = &gem_cursors.cross; + break; + + case GUI_POINTER_MOVE: + gw->cursor = &gem_cursors.sizeall; + break; + + case GUI_POINTER_RIGHT: + case GUI_POINTER_LEFT: + gw->cursor = &gem_cursors.sizewe; + break; + + case GUI_POINTER_UP: + case GUI_POINTER_DOWN: + gw->cursor = &gem_cursors.sizens; + break; + + case GUI_POINTER_RU: + case GUI_POINTER_LD: + gw->cursor = &gem_cursors.sizenesw; + break; + + case GUI_POINTER_RD: + case GUI_POINTER_LU: + gw->cursor = &gem_cursors.sizenwse; + break; + + case GUI_POINTER_WAIT: + gw->cursor = &gem_cursors.wait; + break; + + case GUI_POINTER_PROGRESS: + gw->cursor = &gem_cursors.appstarting; + break; + + case GUI_POINTER_NO_DROP: + gw->cursor = &gem_cursors.nodrop; + break; + + case GUI_POINTER_NOT_ALLOWED: + gw->cursor = &gem_cursors.deny; + break; + + case GUI_POINTER_HELP: + gw->cursor = &gem_cursors.help; + break; + + default: + gw->cursor = &gem_cursors.arrow; + break; + } + + if (input_window == gw) { + gem_set_cursor(gw->cursor); + } +} + + +static nserror gui_window_set_url(struct gui_window *w, nsurl *url) +{ + int l; + + if (w == NULL) + return NSERROR_OK; + + l = strlen(nsurl_access(url))+1; + + if (w->url == NULL) { + w->url = malloc(l); + } else { + w->url = realloc(w->url, l); + } + strncpy(w->url, nsurl_access(url), l); + w->url[l] = 0; + if(input_window == w->root->active_gui_window) { + toolbar_set_url(w->root->toolbar, nsurl_access(url)); + } + + return NSERROR_OK; +} + +char * gui_window_get_url(struct gui_window *gw) +{ + if (gw == NULL) { + return(NULL); + } + return(gw->url); +} + +char * gui_window_get_title(struct gui_window *gw) +{ + if (gw == NULL) { + return(NULL); + } + return(gw->title); +} + +static void throbber_advance( void * data ) +{ + + struct gui_window * gw = (struct gui_window *)data; + + if (gw->root == NULL) + return; + if (gw->root->toolbar == NULL) + return; + + if (gw->root->toolbar->throbber.running == false) + return; + + toolbar_throbber_progress(gw->root->toolbar); + atari_schedule(1000, throbber_advance, gw ); +} + +static void gui_window_start_throbber(struct gui_window *w) +{ + if (w == NULL) + return; + + toolbar_set_throbber_state(w->root->toolbar, true); + atari_schedule(1000, throbber_advance, w ); + rendering = true; +} + +static void gui_window_stop_throbber(struct gui_window *w) +{ + if (w == NULL) + return; + if (w->root->toolbar->throbber.running == false) + return; + + atari_schedule(-1, throbber_advance, w); + + toolbar_set_throbber_state(w->root->toolbar, false); + + rendering = false; +} + +/** + * Place caret in window + */ +static void +gui_window_place_caret(struct gui_window *w, int x, int y, int height, + const struct rect *clip) +{ + window_place_caret(w->root, 1, x, y, height, NULL); + w->root->caret.state |= CARET_STATE_ENABLED; + return; +} + + +/** + * clear window caret + */ +static void +gui_window_remove_caret(struct gui_window *w) +{ + if (w == NULL) + return; + + if ((w->root->caret.state & CARET_STATE_ENABLED) != 0) { + //printf("gw hide caret\n"); + window_place_caret(w->root, 0, -1, -1, -1, NULL); + w->root->caret.state &= ~CARET_STATE_ENABLED; + } + return; +} + +/** + * Set a favicon for a gui window. + * + * \param g window to update. + * \param icon handle to object to use as icon. + */ +static void +gui_window_set_icon(struct gui_window *g, hlcache_handle *icon) +{ + struct bitmap *bmp_icon; + + bmp_icon = (icon != NULL) ? content_get_bitmap(icon) : NULL; + g->icon = bmp_icon; + if(input_window == g) { + window_set_icon(g->root, bmp_icon); + } +} + +static void gui_window_new_content(struct gui_window *w) +{ + struct gemtk_wm_scroll_info_s *slid = gemtk_wm_get_scroll_info(w->root->win); + slid->x_pos = 0; + slid->y_pos = 0; + gemtk_wm_update_slider(w->root->win, GEMTK_WM_VH_SLIDER); + gui_window_redraw_window(w); +} + + +/** + * Core asks front end for clipboard contents. + * + * \param buffer UTF-8 text, allocated by front end, ownership yeilded to core + * \param length Byte length of UTF-8 text in buffer + */ +static void gui_get_clipboard(char **buffer, size_t *length) +{ + char *clip; + + *length = 0; + *buffer = 0; + + clip = scrap_txt_read(); + + if(clip == NULL) { + return; + } else { + + // clipboard is in atari encoding, convert it to utf8: + + size_t clip_len; + char *utf8 = NULL; + + clip_len = strlen(clip); + if (clip_len > 0) { + nserror ret; + ret = utf8_to_local_encoding(clip, clip_len, &utf8); + if (ret == NSERROR_OK && utf8 != NULL) { + *buffer = utf8; + *length = strlen(utf8); + } else { + assert(ret == NSERROR_OK && utf8 != NULL); + } + } + + free(clip); + } +} + +/** + * Core tells front end to put given text in clipboard + * + * \param buffer UTF-8 text, owned by core + * \param length Byte length of UTF-8 text in buffer + * \param styles Array of styles given to text runs, owned by core, or NULL + * \param n_styles Number of text run styles in array + */ +static void gui_set_clipboard(const char *buffer, size_t length, + nsclipboard_styles styles[], int n_styles) +{ + if (length > 0 && buffer != NULL) { + + // convert utf8 input to atari encoding: + + nserror ret; + char *clip = NULL; + + ret = utf8_to_local_encoding(buffer,length, &clip); + if (ret == NSERROR_OK) { + scrap_txt_write(clip); + } else { + assert(ret == NSERROR_OK); + } + free(clip); + } +} + +static void gui_401login_open(nsurl *url, const char *realm, + nserror (*cb)(bool proceed, void *pw), void *cbpw) +{ + bool bres; + char * out = NULL; + bres = login_form_do( url, (char*)realm, &out); + if (bres) { + LOG("url: %s, realm: %s, auth: %s\n", nsurl_access(url), realm, out); + urldb_set_auth_details(url, realm, out); + } + if (out != NULL) { + free( out ); + } + if (cb != NULL) { + cb(bres, cbpw); + } + +} + +static void +gui_cert_verify(nsurl *url, const struct ssl_cert_info *certs, + unsigned long num, nserror (*cb)(bool proceed, void *pw), + void *cbpw) +{ + struct sslcert_session_data *data; + LOG("url %s", nsurl_access(url)); + + // TODO: localize string + int b = form_alert(1, "[2][SSL Verify failed, continue?][Continue|Abort|Details...]"); + if(b == 1){ + // Accept + urldb_set_cert_permissions(url, true); + cb(true, cbpw); + } else if(b == 2) { + // Reject + urldb_set_cert_permissions(url, false); + cb(false, cbpw); + } else if(b == 3) { + // Inspect + sslcert_viewer_create_session_data(num, url, cb, cbpw, certs, + &data); + atari_sslcert_viewer_open(data); + } + +} + +void gui_set_input_gui_window(struct gui_window *gw) +{ + LOG("Setting input window from: %p to %p\n", input_window, gw); + input_window = gw; +} + +struct gui_window * gui_get_input_window(void) +{ + return(input_window); +} + +static void gui_quit(void) +{ + LOG("quitting"); + + struct gui_window *gw = window_list; + struct gui_window *tmp = window_list; + + /* Destroy all remaining browser windows: */ + while (gw) { + tmp = gw->next; + browser_window_destroy(gw->browser->bw); + gw = tmp; + } + + /* destroy the treeview windows: */ + atari_global_history_destroy(); + atari_hotlist_destroy(); + atari_cookie_manager_destroy(); + + /* shutdown netsurf treeview framework: */ + treeview_fini(); + + /* shutdown the toolbar framework: */ + toolbar_exit(); + + /* save persistent informations: */ + urldb_save_cookies(nsoption_charp(cookie_file)); + urldb_save(nsoption_charp(url_file)); + + deskmenu_destroy(); + gemtk_wm_exit(); + + rsrc_free(); + + LOG("Shutting down plotter"); + plot_finalise(); + LOG("done"); +} + +/** + * Process commandline parameters. + */ +static bool +process_cmdline(int argc, char** argv) +{ + int opt; + bool set_default_dimensions = true; + + LOG("argc %d, argv %p", argc, argv); + + if ((nsoption_int(window_width) != 0) && (nsoption_int(window_height) != 0)) { + + option_window_width = nsoption_int(window_width); + option_window_height = nsoption_int(window_height); + option_window_x = nsoption_int(window_x); + option_window_y = nsoption_int(window_y); + + if (option_window_width <= desk_area.g_w + && option_window_height < desk_area.g_h) { + set_default_dimensions = false; + } + } + + if (set_default_dimensions) { + if( sys_type() == SYS_TOS ) { + /* on single tasking OS, start as fulled window: */ + option_window_width = desk_area.g_w; + option_window_height = desk_area.g_h; + option_window_x = desk_area.g_w/2-(option_window_width/2); + option_window_y = (desk_area.g_h/2)-(option_window_height/2); + } else { + option_window_width = 600; + option_window_height = 360; + option_window_x = 10; + option_window_y = 30; + } + } + + if (nsoption_charp(homepage_url) != NULL) + option_homepage_url = nsoption_charp(homepage_url); + else + option_homepage_url = NETSURF_HOMEPAGE; + + while((opt = getopt(argc, argv, "w:h:")) != -1) { + switch (opt) { + case 'w': + option_window_width = atoi(optarg); + break; + + case 'h': + option_window_height = atoi(optarg); + break; + + default: + fprintf(stderr, + "Usage: %s [w,h,v] url\n", + argv[0]); + return false; + } + } + + if (optind < argc) { + option_homepage_url = argv[optind]; + } + return true; +} + +static inline void create_cursor(int flags, short mode, void * form, + MFORM_EX * m) +{ + m->flags = flags; + m->number = mode; + if( flags & MFORM_EX_FLAG_USERFORM ) { + m->number = mode; + m->tree = (OBJECT*)form; + } +} + +static nsurl *gui_get_resource_url(const char *path) +{ + char buf[PATH_MAX]; + nsurl *url = NULL; + + atari_find_resource((char*)&buf, path, path); + + netsurf_path_to_nsurl(buf, &url); + + return url; +} + +/** + * Set option defaults for atari frontend + * + * @param defaults The option table to update. + * @return error status. + */ +static nserror set_defaults(struct nsoption_s *defaults) +{ + /* Set defaults for absent option strings */ + nsoption_setnull_charp(cookie_file, strdup("cookies")); + if (nsoption_charp(cookie_file) == NULL) { + LOG("Failed initialising string options"); + return NSERROR_BAD_PARAMETER; + } + return NSERROR_OK; +} + +static char *theapp = (char*)"NetSurf"; + +/** + * Initialise atari gui. + */ +static void gui_init(int argc, char** argv) +{ + char buf[PATH_MAX]; + OBJECT * cursors; + + atari_find_resource(buf, "netsurf.rsc", "./res/netsurf.rsc"); + LOG("Using RSC file: %s ", (char *)&buf); + if (rsrc_load(buf)==0) { + + char msg[1024]; + + snprintf(msg, 1024, "Unable to open GEM Resource file (%s)!", buf); + die(msg); + } + + wind_get_grect(0, WF_WORKXYWH, &desk_area); + + create_cursor(0, POINT_HAND, NULL, &gem_cursors.hand ); + create_cursor(0, TEXT_CRSR, NULL, &gem_cursors.ibeam ); + create_cursor(0, THIN_CROSS, NULL, &gem_cursors.cross); + create_cursor(0, BUSY_BEE, NULL, &gem_cursors.wait); + create_cursor(0, ARROW, NULL, &gem_cursors.arrow); + create_cursor(0, OUTLN_CROSS, NULL, &gem_cursors.sizeall); + create_cursor(0, OUTLN_CROSS, NULL, &gem_cursors.sizenesw); + create_cursor(0, OUTLN_CROSS, NULL, &gem_cursors.sizenwse); + cursors = gemtk_obj_get_tree(CURSOR); + create_cursor(MFORM_EX_FLAG_USERFORM, CURSOR_APPSTART, + cursors, &gem_cursors.appstarting); + gem_set_cursor( &gem_cursors.appstarting ); + create_cursor(MFORM_EX_FLAG_USERFORM, CURSOR_SIZEWE, + cursors, &gem_cursors.sizewe); + create_cursor(MFORM_EX_FLAG_USERFORM, CURSOR_SIZENS, + cursors, &gem_cursors.sizens); + create_cursor(MFORM_EX_FLAG_USERFORM, CURSOR_NODROP, + cursors, &gem_cursors.nodrop); + create_cursor(MFORM_EX_FLAG_USERFORM, CURSOR_DENY, + cursors, &gem_cursors.deny); + create_cursor(MFORM_EX_FLAG_USERFORM, CURSOR_MENU, + cursors, &gem_cursors.menu); + create_cursor(MFORM_EX_FLAG_USERFORM, CURSOR_HELP, + cursors, &gem_cursors.help); + + LOG("Enabling core select menu"); + nsoption_set_bool(core_select_menu, true); + + LOG("Loading url.db from: %s", nsoption_charp(url_file)); + if( strlen(nsoption_charp(url_file)) ) { + urldb_load(nsoption_charp(url_file)); + } + + LOG("Loading cookies from: %s", nsoption_charp(cookie_file)); + if( strlen(nsoption_charp(cookie_file)) ) { + urldb_load_cookies(nsoption_charp(cookie_file)); + } + + if (process_cmdline(argc,argv) != true) + die("unable to process command line.\n"); + + LOG("Initializing NKC..."); + nkc_init(); + + LOG("Initializing plotters..."); + plot_init(nsoption_charp(atari_font_driver)); + + aes_event_in.emi_m1leave = MO_LEAVE; + aes_event_in.emi_m1.g_w = 1; + aes_event_in.emi_m1.g_h = 1; + //next_poll = clock() + (CLOCKS_PER_SEC>>3); + + deskmenu_init(); + menu_register( -1, theapp); + if (sys_type() & (SYS_MAGIC|SYS_NAES|SYS_XAAES)) { + menu_register( _AESapid, (char*)" NetSurf "); + } + gemtk_wm_init(); + + /* Initialize the netsurf treeview framework with default font size: */ + treeview_init(0); + + /* Initialize the specific treeview windows: */ + atari_global_history_init(); + atari_hotlist_init(); + atari_cookie_manager_init(); + + /* Initialize the toolbar framework: */ + toolbar_init(); +} + +static struct gui_window_table atari_window_table = { + .create = gui_window_create, + .destroy = gui_window_destroy, + .redraw = gui_window_redraw_window, + .update = gui_window_update_box, + .get_scroll = gui_window_get_scroll, + .set_scroll = gui_window_set_scroll, + .get_dimensions = gui_window_get_dimensions, + .update_extent = gui_window_update_extent, + .reformat = atari_window_reformat, + + .set_title = gui_window_set_title, + .set_url = gui_window_set_url, + .set_icon = gui_window_set_icon, + .set_status = atari_window_set_status, + .set_pointer = gui_window_set_pointer, + .place_caret = gui_window_place_caret, + .remove_caret = gui_window_remove_caret, + .new_content = gui_window_new_content, + .start_throbber = gui_window_start_throbber, + .stop_throbber = gui_window_stop_throbber, +}; + +static struct gui_clipboard_table atari_clipboard_table = { + .get = gui_get_clipboard, + .set = gui_set_clipboard, +}; + +static struct gui_fetch_table atari_fetch_table = { + .filetype = fetch_filetype, + + .get_resource_url = gui_get_resource_url, +}; + +static struct gui_misc_table atari_misc_table = { + .schedule = atari_schedule, + .warning = atari_warn_user, + + .quit = gui_quit, + .cert_verify = gui_cert_verify, + .login = gui_401login_open, +}; + +/* #define WITH_DBG_LOGFILE 1 */ +/** + * Entry point from OS. + * + * /param argc The number of arguments in the string vector. + * /param argv The argument string vector. + * /return The return code to the OS + */ +int main(int argc, char** argv) +{ + char messages[PATH_MAX]; + char store[PATH_MAX]; + const char *addr; + char * file_url = NULL; + struct stat stat_buf; + nsurl *url; + nserror ret; + + struct netsurf_table atari_table = { + .misc = &atari_misc_table, + .window = &atari_window_table, + .clipboard = &atari_clipboard_table, + .download = atari_download_table, + .fetch = &atari_fetch_table, + .file = atari_file_table, + .utf8 = atari_utf8_table, + .search = atari_search_table, + .llcache = filesystem_llcache_table, + .bitmap = atari_bitmap_table, + .layout = atari_layout_table + }; + + ret = netsurf_register(&atari_table); + if (ret != NSERROR_OK) { + die("NetSurf operation table failed registration"); + } + + /** @todo logging file descriptor update belongs in a nslog_init callback */ + setbuf(stderr, NULL); + setbuf(stdout, NULL); +#ifdef WITH_DBG_LOGFILE + freopen("stdout.log", "a+", stdout); + freopen("stderr.log", "a+", stderr); +#endif + + graf_mouse(BUSY_BEE, NULL); + + init_app(NULL); + + init_os_info(); + + atari_find_resource((char*)&messages, "messages", "res/messages"); + atari_find_resource((char*)&options, "Choices", "Choices"); + atari_find_resource((char*)&store, "cache", "res/cache"); + + /* initialise logging - not fatal if it fails but not much we can + * do about it + */ + nslog_init(NULL, &argc, argv); + + /* user options setup */ + ret = nsoption_init(set_defaults, &nsoptions, &nsoptions_default); + if (ret != NSERROR_OK) { + die("Options failed to initialise"); + } + nsoption_read(options, NULL); + nsoption_commandline(&argc, argv, NULL); + + ret = messages_add_from_file(messages); + + /* common initialisation */ + LOG("Initialising core..."); + ret = netsurf_init(store); + if (ret != NSERROR_OK) { + die("NetSurf failed to initialise"); + } + + LOG("Initializing GUI..."); + gui_init(argc, argv); + + graf_mouse( ARROW , NULL); + + LOG("Creating initial browser window..."); + addr = option_homepage_url; + if (strncmp(addr, "file://", 7) && strncmp(addr, "http://", 7)) { + if (stat(addr, &stat_buf) == 0) { + file_url = local_file_to_url(addr); + addr = file_url; + } + } + + /* create an initial browser window */ + ret = nsurl_create(addr, &url); + if (ret == NSERROR_OK) { + ret = browser_window_create(BW_CREATE_HISTORY, + url, + NULL, + NULL, + NULL); + nsurl_unref(url); + } + if (ret != NSERROR_OK) { + atari_warn_user(messages_get_errorcode(ret), 0); + } else { + LOG("Entering Atari event mainloop..."); + while (!atari_quit) { + atari_poll(); + } + } + + netsurf_exit(); + + free(file_url); + +#ifdef WITH_DBG_LOGFILE + fclose(stdout); + fclose(stderr); +#endif + LOG("exit_gem"); + exit_gem(); + + return 0; +} diff --git a/frontends/atari/gui.h b/frontends/atari/gui.h new file mode 100644 index 000000000..50184d029 --- /dev/null +++ b/frontends/atari/gui.h @@ -0,0 +1,183 @@ +/* + * Copyright 2010 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef NS_ATARI_GUI_H_ +#define NS_ATARI_GUI_H_ + +#include <stdbool.h> +#include <mt_gem.h> + +#include "desktop/mouse.h" + +#include "atari/redrawslots.h" +#include "atari/gemtk/gemtk.h" + +#ifndef PATH_MAX +#define PATH_MAX 1024 +#endif + +#define CARET_STATE_VISIBLE 0x01 +#define CARET_STATE_ENABLED 0x02 + +struct s_caret { + GRECT dimensions; + MFDB symbol; + int fd_size; + unsigned short state; +}; + +struct point_s { + int x; + int y; +}; + +typedef struct point_s POINT; + +#define MFORM_EX_FLAG_USERFORM 0x01 + +struct mform_ex_s +{ + unsigned char flags; + int number; + OBJECT * tree; +}; + +typedef struct mform_ex_s MFORM_EX; + +struct s_gem_cursors { + MFORM_EX hand; + MFORM_EX ibeam; + MFORM_EX cross; + MFORM_EX sizeall; + MFORM_EX sizewe; + MFORM_EX sizens; + MFORM_EX sizenesw; + MFORM_EX sizenwse; + MFORM_EX wait; + MFORM_EX appstarting; + MFORM_EX nodrop; + MFORM_EX deny; + MFORM_EX help; + MFORM_EX menu; + MFORM_EX arrow; +} gem_cursors; + +enum focus_element_type { + WIDGET_NONE=0, + URL_WIDGET, + SEARCH_INPUT, + BROWSER +}; + + +struct s_focus_info +{ + enum focus_element_type type; + void * element; +}; + +/* defines for data attached to components: */ +#define CDT_OBJECT 0x004f424aUL +#define CDT_OWNER 0x03UL +#define CDT_ICON 0x04UL +#define CDT_ICON_TYPE 0x05UL +# define CDT_ICON_TYPE_NONE 0x00UL +# define CDT_ICON_TYPE_OBJECT 0x01UL +# define CDT_ICON_TYPE_BITMAP 0x02UL + + +struct gui_window; +struct s_browser; +struct s_statusbar; +struct s_toolbar; + +typedef struct s_toolbar * CMP_TOOLBAR; +typedef struct s_statusbar * CMP_STATUSBAR; +typedef struct s_browser * CMP_BROWSER; + +/* + This is the "main" window. It can consist of several components + and also holds information shared by several frames within + the window. +*/ +struct s_gui_win_root +{ + short aes_handle; + GUIWIN *win; + CMP_TOOLBAR toolbar; + CMP_STATUSBAR statusbar; + struct s_focus_info focus; + float scale; + char * title; + struct bitmap * icon; + struct gui_window *active_gui_window; + struct s_redrw_slots redraw_slots; + struct s_caret caret; + /* current size of window on screen: */ + GRECT loc; +}; +typedef struct s_gui_win_root ROOTWIN; + +struct s_browser +{ + struct browser_window * bw; + bool attached; +}; + +/* + This is the part of the gui which is known by netsurf core. + You must implement it. Altough, you are free how to do it. + Each of the browser "viewports" managed by netsurf are bound + to this structure. +*/ +struct gui_window { + struct s_gui_win_root * root; + struct s_browser * browser; + MFORM_EX *cursor; + /* icon to be drawn when iconified, or NULL for default resource. */ + char * status; + char * title; + char * url; + float scale; + struct bitmap * icon; + struct s_caret caret; + struct s_search_form_session *search; + struct gui_window *next, *prev; +}; + +extern struct gui_window *window_list; + +/* -------------------------------------------------------------------------- */ +/* Public - non core gui window functions */ +/* -------------------------------------------------------------------------- */ +void gui_set_input_gui_window(struct gui_window *gw); +struct gui_window *gui_get_input_window(void); +char *gui_window_get_url(struct gui_window *gw); +char *gui_window_get_title(struct gui_window *gw); + +/** + * Set the status bar of a browser window. + * + * \param w The gui_window to update. + * \param text new status text + */ +void atari_window_set_status(struct gui_window *w, const char *text); +void gui_window_set_pointer(struct gui_window *gw, gui_pointer_shape shape); +void gui_window_destroy(struct gui_window *w); + +#endif diff --git a/frontends/atari/history.c b/frontends/atari/history.c new file mode 100644 index 000000000..ba72c7f00 --- /dev/null +++ b/frontends/atari/history.c @@ -0,0 +1,191 @@ +/* + * Copyright 2013 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <assert.h> +#include <inttypes.h> + +#include "utils/log.h" +#include "utils/messages.h" +#include "desktop/mouse.h" +#include "desktop/global_history.h" +#include "desktop/core_window.h" + +#include "atari/treeview.h" +#include "atari/history.h" +#include "atari/gemtk/gemtk.h" +#include "atari/res/netsurf.rsh" + +extern GRECT desk_area; + +struct atari_global_history_s atari_global_history; + +/* Setup Atari Treeview Callbacks: */ + +static nserror +atari_global_history_init_phase2(struct core_window *cw, + struct core_window_callback_table *cb_t) +{ + LOG("cw %p", cw); + return(global_history_init(cb_t, cw)); +} + +static void atari_global_history_finish(struct core_window *cw) +{ + LOG("cw %p", cw); + global_history_fini(); +} + +static void atari_global_history_draw(struct core_window *cw, int x, + int y, struct rect *clip, + const struct redraw_context *ctx) +{ + global_history_redraw(x, y, clip, ctx); +} + +static void atari_global_history_keypress(struct core_window *cw, uint32_t ucs4) +{ + LOG("ucs4: %"PRIu32, ucs4); + global_history_keypress(ucs4); +} + +static void +atari_global_history_mouse_action(struct core_window *cw, + browser_mouse_state mouse, + int x, int y) +{ + LOG("x: %d, y: %d\n", x, y); + + global_history_mouse_action(mouse, x, y); +} + +void atari_global_history_close(void) +{ + atari_treeview_close(atari_global_history.tv); +} + + +static short handle_event(GUIWIN *win, EVMULT_OUT *ev_out, short msg[8]) +{ + short retval = 0; + + LOG("win %p", win); + + if (ev_out->emo_events & MU_MESAG) { + switch (msg[0]) { + case WM_CLOSED: + atari_global_history_close(); + retval = 1; + break; + + default: break; + } + } + + return(retval); +} + +static struct atari_treeview_callbacks atari_global_history_treeview_callbacks = { + .init_phase2 = atari_global_history_init_phase2, + .finish = atari_global_history_finish, + .draw = atari_global_history_draw, + .keypress = atari_global_history_keypress, + .mouse_action = atari_global_history_mouse_action, + .gemtk_user_func = handle_event +}; + +void atari_global_history_init(void) +{ + if (atari_global_history.init == false) { + if( atari_global_history.window == NULL ) { + int flags = ATARI_TREEVIEW_WIDGETS; + short handle = -1; + OBJECT * tree = gemtk_obj_get_tree(TOOLBAR_HISTORY); + assert( tree ); + + handle = wind_create(flags, 0, 0, desk_area.g_w, desk_area.g_h); + atari_global_history.window = gemtk_wm_add(handle, GEMTK_WM_FLAG_DEFAULTS, NULL); + if( atari_global_history.window == NULL ) { + gemtk_msg_box_show(GEMTK_MSG_BOX_ALERT, + "Failed to allocate History"); + return; + } + wind_set_str(handle, WF_NAME, (char*)messages_get("History")); + gemtk_wm_set_toolbar(atari_global_history.window, tree, 0, 0); + gemtk_wm_unlink(atari_global_history.window); + + atari_global_history.tv = atari_treeview_create( + atari_global_history.window, + &atari_global_history_treeview_callbacks, + NULL, flags); + + if (atari_global_history.tv == NULL) { + /* handle it properly, clean up previous allocs */ + LOG("Failed to allocate treeview"); + return; + } + } + } + atari_global_history.init = true; +} + +void atari_global_history_open(void) +{ + assert(atari_global_history.init); + + if (atari_global_history.init == false) { + return; + } + + if (atari_treeview_is_open(atari_global_history.tv) == false) { + + GRECT pos; + pos.g_x = desk_area.g_w - desk_area.g_w / 4; + pos.g_y = desk_area.g_y; + pos.g_w = desk_area.g_w / 4; + pos.g_h = desk_area.g_h; + + atari_treeview_open(atari_global_history.tv, &pos); + } else { + wind_set(gemtk_wm_get_handle(atari_global_history.window), WF_TOP, 1, 0, 0, 0); + } +} + + +void atari_global_history_destroy(void) +{ + + if ( atari_global_history.init == false) { + return; + } + + if ( atari_global_history.window != NULL ) { + if (atari_treeview_is_open(atari_global_history.tv)) + atari_global_history_close(); + wind_delete(gemtk_wm_get_handle(atari_global_history.window)); + gemtk_wm_remove(atari_global_history.window); + atari_global_history.window = NULL; + atari_treeview_delete(atari_global_history.tv); + atari_global_history.init = false; + } + LOG("done"); +} + +void atari_global_history_redraw(void) +{ + atari_treeview_redraw(atari_global_history.tv); +} diff --git a/frontends/atari/history.h b/frontends/atari/history.h new file mode 100644 index 000000000..06a5d32f2 --- /dev/null +++ b/frontends/atari/history.h @@ -0,0 +1,39 @@ +/* + * Copyright 2013 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef NS_ATARI_HISTORY_H +#define NS_ATARI_HISTORY_H + +struct core_window; + +struct atari_global_history_s { + GUIWIN * window; + //struct atari_treeview_window * tv; /*< The hotlist treeview handle. */ + struct core_window *tv; + bool init; +}; + +extern struct atari_global_history_s atari_global_history; + +void atari_global_history_init(void); +void atari_global_history_open(void); +void atari_global_history_close(void); +void atari_global_history_destroy(void); +void atari_global_history_redraw(void); + +#endif diff --git a/frontends/atari/hotlist.c b/frontends/atari/hotlist.c new file mode 100644 index 000000000..1130e6251 --- /dev/null +++ b/frontends/atari/hotlist.c @@ -0,0 +1,315 @@ +/* + * Copyright 2013 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <ctype.h> +#include <string.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <time.h> + +#include "utils/log.h" +#include "utils/messages.h" +#include "utils/utils.h" +#include "content/content.h" +#include "content/hlcache.h" +#include "content/urldb.h" +#include "utils/nsoption.h" +#include "desktop/hotlist.h" +#include "desktop/tree.h" +#include "desktop/core_window.h" + +#include "atari/gui.h" +#include "atari/misc.h" +#include "atari/treeview.h" +#include "atari/hotlist.h" +#include "atari/findfile.h" +#include "atari/gemtk/gemtk.h" +#include "atari/res/netsurf.rsh" + +extern GRECT desk_area; + +struct atari_hotlist hl; + +/* Setup Atari Treeview Callbacks: */ +static nserror atari_hotlist_init_phase2(struct core_window *cw, + struct core_window_callback_table * default_callbacks); +static void atari_hotlist_finish(struct core_window *cw); +static void atari_hotlist_keypress(struct core_window *cw, + uint32_t ucs4); +static void atari_hotlist_mouse_action(struct core_window *cw, + browser_mouse_state mouse, + int x, int y); +static void atari_hotlist_draw(struct core_window *cw, int x, + int y, struct rect *clip, + const struct redraw_context *ctx); +static short handle_event(GUIWIN *win, EVMULT_OUT *ev_out, short msg[8]); + +static struct atari_treeview_callbacks atari_hotlist_treeview_callbacks = { + .init_phase2 = atari_hotlist_init_phase2, + .finish = atari_hotlist_finish, + .draw = atari_hotlist_draw, + .keypress = atari_hotlist_keypress, + .mouse_action = atari_hotlist_mouse_action, + .gemtk_user_func = handle_event +}; + +static nserror atari_hotlist_init_phase2(struct core_window *cw, + struct core_window_callback_table *cb_t) +{ + LOG("cw:%p", cw); + return(hotlist_init(cb_t, cw, hl.path)); +} + +static void atari_hotlist_finish(struct core_window *cw) +{ + LOG("cw:%p", cw); + hotlist_fini(hl.path); +} + +static void atari_hotlist_draw(struct core_window *cw, int x, + int y, struct rect *clip, + const struct redraw_context *ctx) +{ + hotlist_redraw(x, y, clip, ctx); +} + +static void atari_hotlist_keypress(struct core_window *cw, uint32_t ucs4) +{ + GUIWIN *gemtk_win; + GRECT area; + LOG("ucs4: %"PRIu32 , ucs4); + hotlist_keypress(ucs4); + gemtk_win = atari_treeview_get_gemtk_window(cw); + atari_treeview_get_grect(cw, TREEVIEW_AREA_CONTENT, &area); + //gemtk_wm_exec_redraw(gemtk_win, &area); +} + +static void atari_hotlist_mouse_action(struct core_window *cw, + browser_mouse_state mouse, + int x, int y) +{ + LOG("x: %d, y: %d\n", x, y); + + hotlist_mouse_action(mouse, x, y); +} + + + +static short handle_event(GUIWIN *win, EVMULT_OUT *ev_out, short msg[8]) +{ + char *cur_url = NULL; + char *cur_title = NULL; + short retval = 0; + struct atari_treeview_window *tv = NULL; + struct core_window *cw; + struct gui_window * gw; + OBJECT *toolbar; + GRECT tb_area; + GUIWIN * gemtk_win; + + LOG("gw:%p", win); + + tv = (struct atari_treeview_window*) gemtk_wm_get_user_data(win); + cw = (struct core_window *)tv; + + if (ev_out->emo_events & MU_MESAG) { + switch (msg[0]) { + + case WM_TOOLBAR: + LOG("WM_TOOLBAR"); + + toolbar = gemtk_obj_get_tree(TOOLBAR_HOTLIST); + + assert(toolbar); + assert(tv); + + switch (msg[4]) { + case TOOLBAR_HOTLIST_CREATE_FOLDER: + hotlist_add_folder(NULL, 0, 0); + break; + + case TOOLBAR_HOTLIST_ADD: + gw = gui_get_input_window(); + if(gw && gw->browser){ + cur_url = gui_window_get_url(gw); + cur_title = gui_window_get_title(gw); + // TODO: read language string. + cur_title = (cur_title ? cur_title : (char*)"New bookmark"); + } else { + cur_url = (char*)"http://www"; + } + atari_hotlist_add_page(cur_url, cur_title); + break; + + case TOOLBAR_HOTLIST_DELETE: + hotlist_keypress(NS_KEY_DELETE_LEFT); + break; + + case TOOLBAR_HOTLIST_EDIT: + hotlist_edit_selection(); + break; + } + + gemtk_win = atari_treeview_get_gemtk_window(cw); + assert(gemtk_win); + toolbar[msg[4]].ob_state &= ~OS_SELECTED; + atari_treeview_get_grect(cw, TREEVIEW_AREA_TOOLBAR, &tb_area); + evnt_timer(150); + gemtk_wm_exec_redraw(gemtk_win, &tb_area); + retval = 1; + break; + + case WM_CLOSED: + atari_hotlist_close(); + retval = 1; + break; + + default: break; + } + } + + return(retval); +} + + + +void atari_hotlist_init(void) +{ + if (hl.init == false) { + if( strcmp(nsoption_charp(hotlist_file), "") == 0 ){ + atari_find_resource( (char*)&hl.path, "hotlist", "hotlist" ); + } else { + strncpy( (char*)&hl.path, nsoption_charp(hotlist_file), PATH_MAX-1 ); + } + + LOG("Hotlist: %s", (char *)&hl.path); + + if( hl.window == NULL ){ + int flags = ATARI_TREEVIEW_WIDGETS; + short handle = -1; + OBJECT * tree = gemtk_obj_get_tree(TOOLBAR_HOTLIST); + assert( tree ); + + handle = wind_create(flags, 0, 0, desk_area.g_w, desk_area.g_h); + hl.window = gemtk_wm_add(handle, GEMTK_WM_FLAG_DEFAULTS, NULL); + if( hl.window == NULL ) { + gemtk_msg_box_show(GEMTK_MSG_BOX_ALERT, + "Failed to allocate Hotlist"); + return; + } + wind_set_str(handle, WF_NAME, (char*)messages_get("Hotlist")); + gemtk_wm_set_toolbar(hl.window, tree, 0, 0); + gemtk_wm_unlink(hl.window); + tree_hotlist_path = (const char*)&hl.path; + + hl.tv = atari_treeview_create(hl.window, &atari_hotlist_treeview_callbacks, + NULL, flags); + + if (hl.tv == NULL) { + /* handle it properly, clean up previous allocs */ + LOG("Failed to allocate treeview"); + return; + } + + } else { + + } + } + hl.init = true; +} + +void atari_hotlist_open(void) +{ + assert(hl.init); + if (hl.init == false) { + return; + } + + if (atari_treeview_is_open(hl.tv) == false) { + + GRECT pos; + pos.g_x = desk_area.g_w - desk_area.g_w / 4; + pos.g_y = desk_area.g_y; + pos.g_w = desk_area.g_w / 4; + pos.g_h = desk_area.g_h; + + atari_treeview_open(hl.tv, &pos); + } else { + wind_set(gemtk_wm_get_handle(hl.window), WF_TOP, 1, 0, 0, 0); + } +} + +void atari_hotlist_close(void) +{ + atari_treeview_close(hl.tv); +} + +void atari_hotlist_destroy(void) +{ + + if( hl.init == false) { + return; + } + if( hl.window != NULL ) { + if (atari_treeview_is_open(hl.tv)) + atari_hotlist_close(); + wind_delete(gemtk_wm_get_handle(hl.window)); + gemtk_wm_remove(hl.window); + hl.window = NULL; + atari_treeview_delete(hl.tv); + hl.init = false; + } + LOG("done"); +} + +void atari_hotlist_redraw(void) +{ + atari_treeview_redraw(hl.tv); +} + +struct node; + +void atari_hotlist_add_page( const char * url, const char * title ) +{ + nsurl *nsurl; + + if(hl.tv == NULL) + return; + + atari_hotlist_open(); + + if (nsurl_create(url, &nsurl) != NSERROR_OK) + return; + + if (hotlist_has_url(nsurl)) { + LOG("URL already added as Bookmark"); + nsurl_unref(nsurl); + return; + } + + /* doesn't look nice: + if( hl.tv->click.x >= 0 && hl.tv->click.y >= 0 ){ + hotlist_add_entry( nsurl, title, true, hl.tv->click.y ); + } else { + + }*/ + //hotlist_add_url(nsurl); + hotlist_add_entry(nsurl, title, 0, 0); + nsurl_unref(nsurl); +} diff --git a/frontends/atari/hotlist.h b/frontends/atari/hotlist.h new file mode 100644 index 000000000..159878233 --- /dev/null +++ b/frontends/atari/hotlist.h @@ -0,0 +1,52 @@ +/* + * Copyright 2013 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef NS_ATARI_HOTLIST_H +#define NS_ATARI_HOTLIST_H + +#include <stdbool.h> + +#include "desktop/tree.h" +#include "atari/gemtk/gemtk.h" +#include "atari/treeview.h" + +#ifndef PATH_MAX +#define PATH_MAX 1024 +#endif + +/* The hotlist window, toolbar and treeview data. */ + +struct atari_hotlist { + GUIWIN * window; + //ATARI_TREEVIEW_PTR tv;/*< The hotlist treeview handle. */ + struct core_window *tv; + bool init; + char path[PATH_MAX]; +}; + +extern struct atari_hotlist hl; + +void atari_hotlist_init( void ); +void atari_hotlist_open( void ); +void atari_hotlist_close( void ); +void atari_hotlist_destroy( void ); +void atari_hotlist_add_page( const char * url, const char * title ); +void atari_hotlist_redraw( void ); + + +#endif diff --git a/frontends/atari/login.c b/frontends/atari/login.c new file mode 100644 index 000000000..c44b07750 --- /dev/null +++ b/frontends/atari/login.c @@ -0,0 +1,71 @@ +/* + * Copyright 2010 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "utils/config.h" +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <stdbool.h> +#include <cflib.h> + +#include "utils/errors.h" +#include "utils/utils.h" +#include "utils/messages.h" +#include "utils/log.h" +#include "content/content.h" +#include "content/hlcache.h" +#include "content/urldb.h" +#include "content/fetch.h" + +#include "atari/gui.h" +#include "atari/misc.h" +#include "atari/login.h" +#include "atari/res/netsurf.rsh" + + +bool login_form_do(nsurl * url, char * realm, char ** out) +{ + char user[255]; + char pass[255]; + //const char * auth; + short exit_obj = 0; + OBJECT * tree; + + user[0] = 0; + pass[0] = 0; + + // TODO: use auth details for predefined login data + // auth = urldb_get_auth_details(url, realm); + tree = gemtk_obj_get_tree(LOGIN); + + assert(tree != NULL); + + exit_obj = simple_mdial(tree, 0); + + if(exit_obj == LOGIN_BT_LOGIN) { + get_string(tree, LOGIN_TB_USER, user); + get_string(tree, LOGIN_TB_PASSWORD, pass); + int size = strlen((char*)&user) + strlen((char*)&pass) + 2 ; + *out = malloc(size); + snprintf(*out, size, "%s:%s", user, pass); + } else { + *out = NULL; + } + return((exit_obj == LOGIN_BT_LOGIN)); +} + diff --git a/frontends/atari/login.h b/frontends/atari/login.h new file mode 100644 index 000000000..b61808c71 --- /dev/null +++ b/frontends/atari/login.h @@ -0,0 +1,26 @@ +/* + * Copyright 2010 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef NS_LOGIN_H_INCLUDED +#define NS_LOGIN_H_INCLUDED + +#include "utils/nsurl.h" + +bool login_form_do( nsurl * host, char * realm, char **cbpw ); + +#endif diff --git a/frontends/atari/misc.c b/frontends/atari/misc.c new file mode 100644 index 000000000..8688b93fd --- /dev/null +++ b/frontends/atari/misc.c @@ -0,0 +1,408 @@ +/* + * Copyright 2010 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <assert.h> +#include <stdlib.h> +#include <stdio.h> +#include <stdbool.h> +#include <string.h> + +#include <sys/types.h> +#include <mint/osbind.h> + +#include "utils/dirent.h" +#include "content/content.h" +#include "content/hlcache.h" +#include "desktop/cookie_manager.h" +#include "desktop/mouse.h" +#include "desktop/tree.h" +#include "utils/nsoption.h" +#include "utils/messages.h" +#include "utils/utils.h" +#include "utils/log.h" +#include "utils/file.h" +#include "content/fetch.h" + +#include "atari/gui.h" +#include "atari/toolbar.h" + +#include "atari/misc.h" +#include "atari/encoding.h" +#include "atari/gemtk/gemtk.h" +#include "cflib.h" + +extern void * h_gem_rsrc; + +struct is_process_running_callback_data { + const char * fname; + bool found; +}; + +/* exported function documented in atari/misc/h */ +nserror atari_warn_user(const char *warning, const char *detail) +{ + size_t len = 1 + ((warning != NULL) ? strlen(messages_get(warning)) : + 0) + ((detail != 0) ? strlen(detail) : 0); + char message[len]; + snprintf(message, len, messages_get(warning), detail); + + printf("%s\n", message); + gemtk_msg_box_show(GEMTK_MSG_BOX_ALERT, message); + + return NSERROR_OK; +} + +void die(const char *error) +{ + printf("%s\n", error); + gemtk_msg_box_show(GEMTK_MSG_BOX_ALERT, error); + exit(1); +} + + +struct gui_window * find_guiwin_by_aes_handle(short handle){ + + struct gui_window * gw; + gw = window_list; + + if( handle == 0 ){ + return( NULL ); + } + + while(gw != NULL) { + if(gw->root->win != NULL + && gemtk_wm_get_handle(gw->root->win) == handle) { + return(gw); + } + else + gw = gw->next; + } + + return( NULL ); +} + + +static int scan_process_list(scan_process_callback cb, void *data) +{ + int pid, count = 0; + DIR *dir; + char*dirname; + struct dirent *de; + + if (( dir = opendir("U:/kern")) == NULL) + return(0); + + while ((de = readdir( dir)) != NULL) { + dirname = de->d_name; + + if( dirname[0] != '1' && dirname[0] != '2' && dirname[0] != '3' && dirname[0] != '4' && dirname[0] != '5' + && dirname[0] != '6' && dirname[0] != '7' && dirname[0] != '8' && dirname[0] != '9') + continue; + + count++; + if (cb != NULL) { + /* when callback returns negative value, we stop scanning: */ + pid = atoi(dirname); + if (cb(pid, data)<0) { + break; + } + } + } + + closedir(dir); + + return(count); +} + +static int proc_running_callback(int pid, void * arg) +{ + char buf[PATH_MAX], fnamepath[256]; + FILE *fp; + int nread; + struct is_process_running_callback_data *data; + + data = (struct is_process_running_callback_data *)arg; + + sprintf(fnamepath, "U:\\kern\\%d\\fname", pid); + printf("checking: %s\n", fnamepath); + + fp = fopen(fnamepath, "r"); + if(!fp) + return(0); + + nread = fread(buf, 1, PATH_MAX-1, fp); + fclose(fp); + nread = MIN(PATH_MAX-1, nread); + + if (nread > 0) { + buf[nread] = 0; + + char *lastslash = strrchr(buf, '/'); + + if(lastslash == NULL) + lastslash = strrchr(buf, '\\'); + + if(lastslash==NULL) + lastslash = buf; + else + lastslash++; + + if(strcasecmp(lastslash, data->fname)==0){ + /* found process, check status: */ + sprintf(fnamepath, "U:\\kern\\%d\\status", pid); + fp = fopen(fnamepath, "r"); + if (fp) { + nread = fread(buf, 1, PATH_MAX-1, fp); + fclose(fp); + if (nread>0) { + nread = MIN(PATH_MAX-1,nread); + } + buf[nread] = 0; + if (strstr(buf, "zombie")==NULL) { + data->found = true; + return(-1); + } + } + + } + } + return(0); +} + +bool is_process_running(const char * name) +{ + struct is_process_running_callback_data data = {name, false}; + + scan_process_list(proc_running_callback, &data); + + return( (data.found==1) ? true : false ); +} + + +void gem_set_cursor( MFORM_EX * cursor ) +{ + static unsigned char flags = 255; + static int number = 255; + if( flags == cursor->flags && number == cursor->number ) + return; + if( cursor->flags & MFORM_EX_FLAG_USERFORM ) { + gemtk_obj_mouse_sprite(cursor->tree, cursor->number); + } else { + graf_mouse(cursor->number, NULL ); + } + number = cursor->number; + flags = cursor->flags; +} + + +/* exported interface documented in atari/misc.h */ +long nkc_to_input_key(short nkc, long * ucs4_out) +{ + unsigned char ascii = (nkc & 0xFF); + long ik = 0; + + // initialize result: + *ucs4_out = 0; + + // sanitize input key: + nkc = (nkc & (NKF_CTRL|NKF_SHIFT|0xFF)); + + /* shift + cntrl key: */ + if( ((nkc & NKF_CTRL) == NKF_CTRL) && ((nkc & (NKF_SHIFT))!=0) ) { + + } + /* cntrl key only: */ + else if( (nkc & NKF_CTRL) == NKF_CTRL ) { + switch ( ascii ) { + case 'A': + ik = NS_KEY_SELECT_ALL; + break; + + case 'C': + ik = NS_KEY_COPY_SELECTION; + break; + + case 'X': + ik = NS_KEY_CUT_SELECTION; + break; + + case 'V': + ik = NS_KEY_PASTE; + break; + + default: + break; + } + } + /* shift key only: */ + else if( (nkc & NKF_SHIFT) != 0 ) { + switch( ascii ) { + case NK_TAB: + ik = NS_KEY_SHIFT_TAB; + break; + + case NK_LEFT: + ik = NS_KEY_LINE_START; + break; + + case NK_RIGHT: + ik = NS_KEY_LINE_END; + break; + + case NK_UP: + ik = NS_KEY_PAGE_UP; + break; + + case NK_DOWN: + ik = NS_KEY_PAGE_DOWN; + break; + + default: + break; + } + } + /* No modifier keys: */ + else { + switch( ascii ) { + + case NK_INS: + ik = NS_KEY_PASTE; + break; + + case NK_BS: + ik = NS_KEY_DELETE_LEFT; + break; + + case NK_DEL: + ik = NS_KEY_DELETE_RIGHT; + break; + + case NK_TAB: + ik = NS_KEY_TAB; + break; + + + case NK_ENTER: + ik = NS_KEY_NL; + break; + + case NK_RET: + ik = NS_KEY_CR; + break; + + case NK_ESC: + ik = NS_KEY_ESCAPE; + break; + + case NK_CLRHOME: + ik = NS_KEY_TEXT_START; + break; + + case NK_RIGHT: + ik = NS_KEY_RIGHT; + break; + + case NK_LEFT: + ik = NS_KEY_LEFT; + break; + + case NK_UP: + ik = NS_KEY_UP; + break; + + case NK_UNDO: + ik = NS_KEY_UNDO; + break; + + case NK_DOWN: + ik = NS_KEY_DOWN; + break; + + case NK_M_PGUP: + ik = NS_KEY_PAGE_UP; + break; + + case NK_M_PGDOWN: + ik = NS_KEY_PAGE_DOWN; + break; + + default: + break; + } + } + + if( ik == 0 && ( (nkc & NKF_CTRL)==0) ) { + if (ascii >= 9 ) { + *ucs4_out = atari_to_ucs4(ascii); + } + } + return ( ik ); +} + +/** + * Show default file selector + * + * \param title The selector title. + * \param name Default file name + * \return a static char pointer or null if the user aborted the selection. + */ +const char * file_select(const char * title, const char * name) { + + static char path[PATH_MAX]=""; // First usage : current directory + static char fullname[PATH_MAX]=""; + char tmpname[255]; + char * use_title = (char*)title; + + if( strlen(name)>254) + return( NULL ); + + strcpy(tmpname, name); + + if( use_title == NULL ){ + use_title = (char*)""; + } + + if (select_file(path, tmpname, (char*)"*", use_title, NULL)) { + snprintf(fullname, PATH_MAX, "%s%s", path, tmpname); + return((const char*)&fullname); + } + + return( NULL ); +} + + +void dbg_grect(const char * str, GRECT * r) +{ + printf("%s: x: %d, y: %d, w: %d, h: %d (x2: %d, y2: %d)\n", str, + r->g_x, r->g_y, r->g_w, r->g_h, r->g_x + r->g_w, r->g_y + r->g_h); +} + +void dbg_pxy(const char * str, short * pxy ) +{ + printf("%s: x: %d, y: %d, w: %d, h: %d\n", str, + pxy[0], pxy[1], pxy[2], pxy[3] ); +} + +void dbg_rect(const char * str, int * pxy) +{ + printf("%s: x0: %d, y0: %d, x1: %d, y1: %d (w: %d, h: %d)\n", str, + pxy[0], pxy[1], pxy[2], pxy[3], + pxy[2] - pxy[0], + pxy[3] - pxy[1] ); +} + diff --git a/frontends/atari/misc.h b/frontends/atari/misc.h new file mode 100644 index 000000000..e581c23b2 --- /dev/null +++ b/frontends/atari/misc.h @@ -0,0 +1,106 @@ +/* + * Copyright 2010 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef NS_ATARI_MISC_H +#define NS_ATARI_MISC_H + + +#define SBUF8_TO_LBUF8(sbuf,lbuf)\ + lbuf[0] = (long)sbuf[0];\ + lbuf[1] = (long)sbuf[1];\ + lbuf[2] = (long)sbuf[2];\ + lbuf[3] = (long)sbuf[3];\ + lbuf[4] = (long)sbuf[4];\ + lbuf[5] = (long)sbuf[5];\ + lbuf[6] = (long)sbuf[6];\ + lbuf[7] = (long)sbuf[7]; + +#define RECT_TO_GRECT(r,g) \ + (g)->g_x = (r->x0 < r->x1) ? r->x0 : r->x1 ; \ + (g)->g_y = (r->y0 < r->y1) ? r->y0 : r->y1 ; \ + (g)->g_w = (r->x0 < r->x1) ? r->x1 - r->x0 : r->x0 - r->x1 ; \ + (g)->g_h = (r->y0 < r->y1) ? r->y1 - r->y0 : r->y0 - r->y1 ; + + + +/* Modes for find_gui_window: */ +#define BY_WINDOM_HANDLE 0x0 +#define BY_GEM_HANDLE 0x1 + +/** + */ +typedef int (*scan_process_callback)(int pid, void *data); + +/** + */ +struct gui_window * find_guiwin_by_aes_handle(short handle); + +/** + */ +bool is_process_running(const char * name); + +/** + */ +void gem_set_cursor( MFORM_EX * cursor ); + +/** + */ +void dbg_grect(const char * str, GRECT * r); + +/** + */ +void dbg_pxy(const char * str, short * pxy); + +/** + */ +void dbg_rect(const char * str, int * pxy); + +/** + */ +const char * file_select(const char * title, const char * name); + +/** + * Convert NKC to netsurf input key code and/or to ucs4 (depends on keycode). + * + * \param[in] nkc atari normalized key code + * \param[out] ucs4_out The ucs4 converted keycode + * \return The netsurf input keycode or 0 and ucs4_out updated with + * the NKC converted to UC4 encoding. + */ +long nkc_to_input_key(short nkc, long * ucs4_out); + +/** + * Cause an abnormal program termination. + * + * \note This never returns and is intended to terminate without any cleanup. + * + * \param error The message to display to the user. + */ +void die(const char * const error) __attribute__ ((noreturn)); + +/** + * Warn the user of an event. + * + * \param[in] warning A warning looked up in the message translation table + * \param[in] detail Additional text to be displayed or NULL. + * \return NSERROR_OK on success or error code if there was a + * faliure displaying the message to the user. + */ +nserror atari_warn_user(const char *warning, const char *detail); + +#endif diff --git a/frontends/atari/options.h b/frontends/atari/options.h new file mode 100644 index 000000000..4ae847d74 --- /dev/null +++ b/frontends/atari/options.h @@ -0,0 +1,48 @@ +/* + * Copyright 2012 Vincent Sanders <vince@netsurf-browser.org> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef NS_ATARI_OPTIONS_H_ +#define NS_ATARI_OPTIONS_H_ + +/* setup longer default reflow time */ +#define DEFAULT_REFLOW_PERIOD 350 /* time in cs */ + +#endif + +NSOPTION_STRING(atari_font_driver, "freetype") +NSOPTION_INTEGER(atari_font_monochrom, 0) +NSOPTION_INTEGER(atari_transparency, 1) +NSOPTION_INTEGER(atari_dither, 1) +NSOPTION_INTEGER(atari_gui_poll_timeout, 0) +NSOPTION_STRING(atari_editor, NULL) +NSOPTION_STRING(font_face_sans_serif, NULL) +NSOPTION_STRING(font_face_sans_serif_bold, NULL) +NSOPTION_STRING(font_face_sans_serif_italic, NULL) +NSOPTION_STRING(font_face_sans_serif_italic_bold, NULL) +NSOPTION_STRING(font_face_monospace, NULL) +NSOPTION_STRING(font_face_monospace_bold, NULL) +NSOPTION_STRING(font_face_serif, NULL) +NSOPTION_STRING(font_face_serif_bold, NULL) +NSOPTION_STRING(font_face_cursive, NULL) +NSOPTION_STRING(font_face_fantasy, NULL) +NSOPTION_STRING(downloads_path, "downloads") +NSOPTION_STRING(url_file, "url.db") +NSOPTION_STRING(hotlist_file, "hotlist") +NSOPTION_STRING(tree_icons_path, "./res/icons") + + diff --git a/frontends/atari/osspec.c b/frontends/atari/osspec.c new file mode 100644 index 000000000..f64402e8d --- /dev/null +++ b/frontends/atari/osspec.c @@ -0,0 +1,132 @@ +/* + * Copyright 2010 <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <sys/types.h> +#include <limits.h> +#include <stdlib.h> +#include <unistd.h> +#include <stdbool.h> +#include <stdio.h> +#include <string.h> +#include <support.h> +#include <mint/osbind.h> +#include <mint/cookie.h> + +#include "utils/log.h" +#include "atari/osspec.h" +#include "atari/gemtk/gemtk.h" + +#ifndef PATH_MAX +#define PATH_MAX 1024 +#endif + +NS_ATARI_SYSINFO atari_sysinfo; + +void init_os_info(void) +{ + int16_t out[4]; + long cookie_FSMC = 0; + + atari_sysinfo.gemdos_version = Sversion(); + + if( tos_getcookie (C_FSMC, &cookie_FSMC ) == C_FOUND ) { + atari_sysinfo.gdos_FSMC = 1; + } else { + atari_sysinfo.gdos_FSMC = 0; + } + atari_sysinfo.large_sfont_pxh = 13; + atari_sysinfo.medium_sfont_pxh = 6; + atari_sysinfo.small_sfont_pxh = 4; + /* todo: detect if system font is monospaced */ + atari_sysinfo.sfont_monospaced = true; + if( appl_xgetinfo(AES_LARGEFONT, &out[0], &out[1], &out[2], &out[3] ) > 0 ){ + atari_sysinfo.large_sfont_pxh = out[0]; + } + if( appl_xgetinfo(AES_SMALLFONT, &out[0], &out[1], &out[2], &out[3] ) > 0 ){ + atari_sysinfo.small_sfont_pxh = out[0]; + } + atari_sysinfo.aes_max_win_title_len = 79; + if (sys_type() & (SYS_MAGIC|SYS_NAES|SYS_XAAES)) { + if (sys_NAES()) { + atari_sysinfo.aes_max_win_title_len = 127; + } + if (sys_XAAES()) { + atari_sysinfo.aes_max_win_title_len = 200; + } + } +} + + +/* exported interface documented in atari/osspec.h */ +int tos_getcookie(long tag, long * value) +{ + COOKIE * cptr; + + if( atari_sysinfo.gemdos_version > TOS4VER ){ + return( Getcookie(tag, value) ); + } + + cptr = (COOKIE*)Setexc(0x0168, -1L); + if(cptr != NULL) { + do { + if( cptr->c == tag ){ + if(cptr->v != 0 ){ + if( value != NULL ){ + *value = cptr->v; + } + return( C_FOUND ); + } + } + } while( (cptr++)->c != 0L ); + } + return( C_NOTFOUND ); +} + +/* + + a fixed version of realpath() which returns valid + paths for TOS which have no U: drive + +*/ + +char *gemdos_realpath(const char * path, char * rpath) +{ + char work[PATH_MAX+1]; + char * r; + + if (rpath == NULL) { + return (NULL); + } + + // Check if the path is already absolute: + if(path[1] == ':'){ + strcpy(rpath, path); + return(rpath); + } + + LOG("realpath in: %s\n", path); + r = realpath(path, work); + if (r != NULL) { + unx2dos((const char *)r, rpath); + LOG("realpath out: %s\n", rpath); + return(rpath); + } else { + LOG("realpath out: NULL!\n"); + } + return (NULL); +} diff --git a/frontends/atari/osspec.h b/frontends/atari/osspec.h new file mode 100644 index 000000000..0c8d4cf66 --- /dev/null +++ b/frontends/atari/osspec.h @@ -0,0 +1,45 @@ +/* + * Copyright 2011 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef NS_ATARI_OSSPEC_H +#define NS_ATARI_OSSPEC_H + +typedef struct { + long c; + long v; +} COOKIE; + +typedef struct { + unsigned short gemdos_version; + unsigned short gdos_FSMC; + unsigned short systype; + unsigned short small_sfont_pxh; + unsigned short medium_sfont_pxh; + unsigned short large_sfont_pxh; + bool sfont_monospaced; + short aes_max_win_title_len; +} NS_ATARI_SYSINFO; + +extern NS_ATARI_SYSINFO atari_sysinfo; + +void init_os_info(void); +void fix_path(char * path); +char * gemdos_realpath(const char * path, char * rpath); +int tos_getcookie( long tag, long * value ); + +#endif diff --git a/frontends/atari/plot/eddi.h b/frontends/atari/plot/eddi.h new file mode 100644 index 000000000..7d6b90d4b --- /dev/null +++ b/frontends/atari/plot/eddi.h @@ -0,0 +1,54 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2009 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +#ifndef _atari_eddi_h +#define _atari_eddi_h + +/*--- Defines ---*/ + +/* EdDI versions */ + +#define EDDI_10 (0x0100) +#define EDDI_11 (0x0110) + +/* Screen format */ + +enum { + VDI_FORMAT_UNKNOWN=-1, + VDI_FORMAT_INTER=0, /* Interleaved bitplanes */ + VDI_FORMAT_VDI=1, /* VDI independent */ + VDI_FORMAT_PACK=2 /* Packed pixels */ +}; + +/* CLUT types */ +enum { + VDI_CLUT_NONE=0, /* Monochrome mode */ + VDI_CLUT_HARDWARE, /* <256 colours mode */ + VDI_CLUT_SOFTWARE /* True colour mode */ +}; + + +/*--- Functions ---*/ + +unsigned long EdDI_version(void *function_pointer); + +#endif /* atari_eddi_s_h */ diff --git a/frontends/atari/plot/eddi.s b/frontends/atari/plot/eddi.s new file mode 100644 index 000000000..f0ea18a1e --- /dev/null +++ b/frontends/atari/plot/eddi.s @@ -0,0 +1,42 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2009 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +/* + *Read EdDI version + * + *Patrice Mandin + */ + +.text + +.globl _EdDI_version + +/*--- Vector installer ---*/ + +_EdDI_version: +movel sp@(4),a0 /* Value of EdDI cookie */ + +/* Call EdDI function #0 */ +clrl d0 +jsr (a0) + +rts diff --git a/frontends/atari/plot/font_freetype.c b/frontends/atari/plot/font_freetype.c new file mode 100644 index 000000000..a77aff855 --- /dev/null +++ b/frontends/atari/plot/font_freetype.c @@ -0,0 +1,714 @@ +/* + * Copyright 2005 James Bursa <bursa@users.sourceforge.net> + * 2008 Vincent Sanders <vince@simtec.co.uk> + * 2011 Ole Loots <ole@monochrom.net> + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifdef WITH_FREETYPE_FONT_DRIVER +#include <assert.h> +#include <ft2build.h> +#include FT_CACHE_H + +#include "utils/log.h" +#include "utils/nsoption.h" +#include "desktop/mouse.h" +#include "desktop/plot_style.h" + +#include "atari/gui.h" +#include "atari/bitmap.h" +#include "atari/plot/plot.h" +#include "atari/plot/fontplot.h" +#include "atari/plot/font_freetype.h" +#include "atari/findfile.h" +#include "atari/gemtk/gemtk.h" + +/* -------------------------------------------------------------------------- */ +/* Font Loading & Mapping scheme */ +/* -------------------------------------------------------------------------- */ +/* + +Truetype fonts are loaded in the following priority order: + +1. Option values. +2. default resouce names (8.3 compatible). +3. default font package installation path. + + +Resource font names & their meanings: +-------------------------------------------- +s.ttf => Serif +sb.ttf => Serif Bold +ss.ttf => Sans Serif *Default Font +ssb.ttf => Sans Serif Bold +ssi.ttf => Sans Serif Italic +ssib.ttf => Sans Serif Italic Bold +mono.ttf => Monospaced +monob.ttf => Monospaced Bold +cursive.ttf => Cursive +fantasy.ttf => Fantasy +*/ + +#define FONT_RESOURCE_PATH "fonts/" +#define DEJAVU_PATH "/usr/share/fonts/truetype/ttf-dejavu/" +#define BITSTREAM_PATH "/usr/share/fonts/truetype/ttf-bitstream-vera/" + +#if !defined(USE_BITSTREAM_FONT_PACKAGE) && !defined(USE_DEJAVU_FONT_PACKAGE) +# define USE_BITSTREAM_FONT_PACKAGE +#endif + +#if defined(USE_DEJAVU_FONT_PACKAGE) +# define FONT_PKG_PATH DEJAVU_PATH +# define FONT_FILE_SANS "DejaVuSans.ttf" +# define FONT_FILE_SANS_BOLD "DejaVuSans-Bold.ttf" +# define FONT_FILE_SANS_OBLIQUE "DejaVuSans-Oblique.ttf" +# define FONT_FILE_SANS_BOLD_OBLIQUE "DejaVuSans-BoldOblique.ttf" +# define FONT_FILE_SERIF "DejaVuSerif.ttf" +# define FONT_FILE_SERIF_BOLD "DejaVuSerif-Bold.ttf" +# define FONT_FILE_MONO "DejaVuSansMono.ttf" +# define FONT_FILE_MONO_BOLD "DejaVuSerif-Bold.ttf" +# define FONT_FILE_OBLIQUE "DejaVuSansMono-Oblique.ttf" +# define FONT_FILE_FANTASY "DejaVuSerifCondensed-Bold.ttf" +#elif defined(USE_BITSTREAM_FONT_PACKAGE) +# define FONT_PKG_PATH BITSTREAM_PATH +# define FONT_FILE_SANS "Vera.ttf" +# define FONT_FILE_SANS_BOLD "VeraBd.ttf" +# define FONT_FILE_SANS_OBLIQUE "VeraIt.ttf" +# define FONT_FILE_SANS_BOLD_OBLIQUE "VeraBI.ttf" +# define FONT_FILE_SERIF "VeraSe.ttf" +# define FONT_FILE_SERIF_BOLD "VeraSeBd.ttf" +# define FONT_FILE_MONO "VeraMono.ttf" +# define FONT_FILE_MONO_BOLD "VeraMoBd.ttf" +# define FONT_FILE_OBLIQUE "VeraMoIt.ttf" +# define FONT_FILE_FANTASY "VeraMoBI.ttf" + +#endif + +#define CACHE_SIZE 2048 +#define CACHE_MIN_SIZE (100 * 1024) +#define BOLD_WEIGHT 700 + +extern unsigned long atari_plot_flags; +extern int atari_plot_vdi_handle; + +static FT_Library library; +static FTC_Manager ft_cmanager; +static FTC_CMapCache ft_cmap_cache ; +static FTC_ImageCache ft_image_cache; + +int ft_load_type; + +/* cache manager faceID data to create freetype faceid on demand */ +typedef struct ftc_faceid_s { + char *fontfile; /* path to font */ + int index; /* index of font */ + int cidx; /* character map index for unicode */ +} ftc_faceid_t; + +static int dtor( FONT_PLOTTER self ); +static int str_width( FONT_PLOTTER self,const plot_font_style_t *fstyle, + const char * str, size_t length, int * width ); +static int str_split( FONT_PLOTTER self, const plot_font_style_t *fstyle, + const char *string, size_t length,int x, + size_t *char_offset, int *actual_x ); +static int pixel_pos( FONT_PLOTTER self, const plot_font_style_t *fstyle, + const char *string, size_t length,int x, + size_t *char_offset, int *actual_x ); +static int text( FONT_PLOTTER self, int x, int y, const char *text, + size_t length, const plot_font_style_t *fstyle ); + +static void draw_glyph8(FONT_PLOTTER self, GRECT *clip, GRECT * loc, + uint8_t * pixdata, int pitch, uint32_t colour); +static void draw_glyph1(FONT_PLOTTER self, GRECT * clip, GRECT * loc, + uint8_t * pixdata, int pitch, uint32_t colour); + +static ftc_faceid_t *font_faces[FONT_FACE_COUNT]; +static MFDB tmp; +static int tmp_mfdb_size; +static bool init = false; +static struct bitmap * fontbmp; +static size_t fontbmp_stride; +static int fontbmp_allocated_height; +static int fontbmp_allocated_width; + + + +/* map cache manager handle to face id */ +static FT_Error ft_face_requester(FTC_FaceID face_id, FT_Library library, FT_Pointer request_data, FT_Face *face ) +{ + FT_Error error; + ftc_faceid_t *ft_face = (ftc_faceid_t *)face_id; + int cidx; + + error = FT_New_Face(library, ft_face->fontfile, ft_face->index, face); + if (error) { + LOG("Could not find font (code %d)\n", error); + } else { + error = FT_Select_Charmap(*face, FT_ENCODING_UNICODE); + if (error) { + LOG("Could not select charmap (code %d)\n", error); + } else { + for (cidx = 0; cidx < (*face)->num_charmaps; cidx++) { + if ((*face)->charmap == (*face)->charmaps[cidx]) { + ft_face->cidx = cidx; + break; + } + } + } + } + LOG("Loaded face from %s\n", ft_face->fontfile); + return error; +} + +/* create new framebuffer face and cause it to be loaded to check its ok */ +static ftc_faceid_t * +ft_new_face(const char *option, const char *resname, const char *fontfile) +{ + ftc_faceid_t *newf; + FT_Error error; + FT_Face aface; + char buf[PATH_MAX]; + + newf = calloc(1, sizeof(ftc_faceid_t)); + if (option != NULL) { + newf->fontfile = strdup(option); + } else { + atari_find_resource(buf, resname, fontfile); + newf->fontfile = strdup(buf); + } + error = FTC_Manager_LookupFace(ft_cmanager, (FTC_FaceID)newf, &aface); + if (error) { + LOG("Could not find font face %s (code %d)\n", fontfile, error); + free(newf); + newf = font_faces[FONT_FACE_DEFAULT]; /* use default */ + } + return newf; +} + +static void ft_fill_scalar(const plot_font_style_t *fstyle, FTC_Scaler srec) +{ + int selected_face = FONT_FACE_DEFAULT; + + switch (fstyle->family) { + + case PLOT_FONT_FAMILY_SERIF: + if (fstyle->weight >= BOLD_WEIGHT) { + selected_face = FONT_FACE_SERIF_BOLD; + } else { + selected_face = FONT_FACE_SERIF; + } + break; + + case PLOT_FONT_FAMILY_MONOSPACE: + if (fstyle->weight >= BOLD_WEIGHT) { + selected_face = FONT_FACE_MONOSPACE_BOLD; + } else { + selected_face = FONT_FACE_MONOSPACE; + } + break; + + case PLOT_FONT_FAMILY_CURSIVE: + selected_face = FONT_FACE_CURSIVE; + break; + + case PLOT_FONT_FAMILY_FANTASY: + selected_face = FONT_FACE_FANTASY; + break; + + case PLOT_FONT_FAMILY_SANS_SERIF: + default: + if ((fstyle->flags & FONTF_ITALIC) || + (fstyle->flags & FONTF_OBLIQUE)) { + if (fstyle->weight >= BOLD_WEIGHT) { + selected_face = FONT_FACE_SANS_SERIF_ITALIC_BOLD; + } else { + selected_face = FONT_FACE_SANS_SERIF_ITALIC; + } + } else { + if (fstyle->weight >= BOLD_WEIGHT) { + selected_face = FONT_FACE_SANS_SERIF_BOLD; + } else { + selected_face = FONT_FACE_SANS_SERIF; + } + } + } + + srec->face_id = (FTC_FaceID)font_faces[selected_face]; + + srec->width = srec->height = (fstyle->size * 64) / FONT_SIZE_SCALE; + srec->pixel = 0; + + /* calculate x/y resolution, when browser_get_dpi() isn't available */ + /* 72 is an good value. */ + /* TODO: because browser_get_dpi() is to large, calculate that value */ + /* by VDI values. */ + srec->x_res = srec->y_res = 72; // browser_get_dpi(); +} + +static FT_Glyph ft_getglyph(const plot_font_style_t *fstyle, uint32_t ucs4) +{ + FT_UInt glyph_index; + FTC_ScalerRec srec; + FT_Glyph glyph; + FT_Error error; + ftc_faceid_t *ft_face; + + ft_fill_scalar(fstyle, &srec); + ft_face = (ftc_faceid_t *)srec.face_id; + glyph_index = FTC_CMapCache_Lookup(ft_cmap_cache, srec.face_id, ft_face->cidx, ucs4); + error = FTC_ImageCache_LookupScaler(ft_image_cache, + &srec, + FT_LOAD_RENDER | + FT_LOAD_FORCE_AUTOHINT | + ft_load_type, + glyph_index, + &glyph, + NULL); + return glyph; +} + + +/* initialise font handling */ +static bool ft_font_init(void) +{ + FT_Error error; + FT_ULong max_cache_size; + FT_UInt max_faces = 6; + int i; + + /* freetype library initialise */ + error = FT_Init_FreeType( &library ); + if (error) { + LOG("Freetype could not initialised (code %d)\n", error); + return false; + } + + /* set the Glyph cache size up */ + max_cache_size = CACHE_SIZE * 1024; + if (max_cache_size < CACHE_MIN_SIZE) { + max_cache_size = CACHE_MIN_SIZE; + } + + /* cache manager initialise */ + error = FTC_Manager_New(library, + max_faces, + 0, + max_cache_size, + ft_face_requester, + NULL, + &ft_cmanager); + if (error) { + LOG("Freetype could not initialise cache manager (code %d)\n", error); + FT_Done_FreeType(library); + return false; + } + + error = FTC_CMapCache_New(ft_cmanager, &ft_cmap_cache); + error = FTC_ImageCache_New(ft_cmanager, &ft_image_cache); + + /* Optain font faces */ + + + /* Default font, Sans Serif */ + font_faces[FONT_FACE_SANS_SERIF] = NULL; + font_faces[FONT_FACE_SANS_SERIF] = ft_new_face( + nsoption_charp(font_face_sans_serif), + FONT_RESOURCE_PATH "ss.ttf", + FONT_PKG_PATH FONT_FILE_SANS + ); + if (font_faces[FONT_FACE_SANS_SERIF] == NULL) { + LOG("Could not find default font (code %d)\n", error); + FTC_Manager_Done(ft_cmanager); + FT_Done_FreeType(library); + return false; + } + + /* Sans Serif Bold*/ + font_faces[FONT_FACE_SANS_SERIF_BOLD] = + ft_new_face(nsoption_charp(font_face_sans_serif_bold), + FONT_RESOURCE_PATH "ssb.ttf", + FONT_PKG_PATH FONT_FILE_SANS_BOLD); + + /* Sans Serif Italic */ + font_faces[FONT_FACE_SANS_SERIF_ITALIC] = + ft_new_face(nsoption_charp(font_face_sans_serif_italic), + FONT_RESOURCE_PATH "ssi.ttf", + FONT_PKG_PATH FONT_FILE_SANS_OBLIQUE); + + /* Sans Serif Italic Bold */ + font_faces[FONT_FACE_SANS_SERIF_ITALIC_BOLD] = + ft_new_face(nsoption_charp(font_face_sans_serif_italic_bold), + FONT_RESOURCE_PATH "ssib.ttf", + FONT_PKG_PATH FONT_FILE_SANS_BOLD_OBLIQUE); + + /* Monospaced */ + font_faces[FONT_FACE_MONOSPACE] = + ft_new_face(nsoption_charp(font_face_monospace), + FONT_RESOURCE_PATH "mono.ttf", + FONT_PKG_PATH FONT_FILE_MONO); + + /* Mospaced Bold */ + font_faces[FONT_FACE_MONOSPACE_BOLD] = + ft_new_face(nsoption_charp(font_face_monospace_bold), + FONT_RESOURCE_PATH "monob.ttf", + FONT_PKG_PATH FONT_FILE_MONO_BOLD); + + /* Serif */ + font_faces[FONT_FACE_SERIF] = + ft_new_face(nsoption_charp(font_face_serif), + FONT_RESOURCE_PATH "s.ttf", + FONT_PKG_PATH FONT_FILE_SERIF); + + /* Serif Bold */ + font_faces[FONT_FACE_SERIF_BOLD] = + ft_new_face(nsoption_charp(font_face_serif_bold), + FONT_RESOURCE_PATH "sb.ttf", + FONT_PKG_PATH FONT_FILE_SERIF_BOLD); + + /* Cursive */ + font_faces[FONT_FACE_CURSIVE] = + ft_new_face(nsoption_charp(font_face_cursive), + FONT_RESOURCE_PATH "cursive.ttf", + FONT_PKG_PATH FONT_FILE_OBLIQUE); + + /* Fantasy */ + font_faces[FONT_FACE_FANTASY] = + ft_new_face(nsoption_charp(font_face_fantasy), + FONT_RESOURCE_PATH "fantasy.ttf", + FONT_PKG_PATH FONT_FILE_FANTASY); + + for (i=1; i<FONT_FACE_COUNT; i++) { + if (font_faces[i] == NULL){ + font_faces[i] = font_faces[FONT_FACE_SANS_SERIF]; + } + } + + return true; +} + + +static bool ft_font_finalise(void) +{ + FTC_Manager_Done(ft_cmanager ); + FT_Done_FreeType(library); + return true; +} + +static int str_width( FONT_PLOTTER self,const plot_font_style_t *fstyle, + const char *string, size_t length, + int *width) +{ + uint32_t ucs4; + size_t nxtchr = 0; + FT_Glyph glyph; + + *width = 0; + while (nxtchr < length) { + ucs4 = utf8_to_ucs4(string + nxtchr, length - nxtchr); + nxtchr = utf8_next(string, length, nxtchr); + + glyph = ft_getglyph(fstyle, ucs4); + if (glyph == NULL) + continue; + *width += glyph->advance.x >> 16; + } + return(1); +} + + +static int str_split( FONT_PLOTTER self, const plot_font_style_t *fstyle, + const char *string, size_t length, + int x, size_t *char_offset, int *actual_x) +{ + uint32_t ucs4; + size_t nxtchr = 0; + int last_space_x = 0; + int last_space_idx = 0; + FT_Glyph glyph; + + *actual_x = 0; + while (nxtchr < length) { + ucs4 = utf8_to_ucs4(string + nxtchr, length - nxtchr); + glyph = ft_getglyph(fstyle, ucs4); + if (glyph == NULL) + continue; + if (ucs4 == 0x20) { + last_space_x = *actual_x; + last_space_idx = nxtchr; + } + *actual_x += glyph->advance.x >> 16; + if (*actual_x > x && last_space_idx != 0) { + /* string has exceeded available width and we've + * found a space; return previous space */ + *actual_x = last_space_x; + *char_offset = last_space_idx; + return true; + } + nxtchr = utf8_next(string, length, nxtchr); + } + *char_offset = nxtchr; + return (1); +} + + +static int pixel_pos( FONT_PLOTTER self, const plot_font_style_t *fstyle, + const char *string, size_t length, + int x, size_t *char_offset, int *actual_x) +{ + uint32_t ucs4; + size_t nxtchr = 0; + FT_Glyph glyph; + int prev_x = 0; + + *actual_x = 0; + while (nxtchr < length) { + ucs4 = utf8_to_ucs4(string + nxtchr, length - nxtchr); + glyph = ft_getglyph(fstyle, ucs4); + if (glyph == NULL) + continue; + *actual_x += glyph->advance.x >> 16; + if (*actual_x > x) + break; + + prev_x = *actual_x; + nxtchr = utf8_next(string, length, nxtchr); + } + + /* choose nearest of previous and last x */ + if (abs(*actual_x - x) > abs(prev_x - x)) + *actual_x = prev_x; + *char_offset = nxtchr; + return ( 1 ); +} + + +static void draw_glyph8(FONT_PLOTTER self, GRECT * clip, GRECT * loc, uint8_t * pixdata, int pitch, uint32_t colour) +{ + uint32_t * linebuf; + uint32_t fontpix; + int xloop,yloop,xoff,yoff; + int x,y,w,h; + + x = loc->g_x; + y = loc->g_y; + w = loc->g_w; + h = loc->g_h; + + if( !rc_intersect( clip, loc ) ){ + return; + } + + xoff = loc->g_x - x; + yoff = loc->g_y - y; + + assert( loc->g_h <= h ); + assert( loc->g_w <= w ); + + h = loc->g_h; + w = loc->g_w; + + assert( h <= fontbmp_allocated_height ); + assert( w <= fontbmp_allocated_width ); + + fontbmp->height = h; + fontbmp->width = w; + for( yloop = 0; yloop < MIN(fontbmp_allocated_height, h); yloop++) { + linebuf = (uint32_t *)(fontbmp->pixdata + (fontbmp_stride * yloop)); + for(xloop = 0; xloop < MIN(fontbmp_allocated_width, w); xloop++){ + fontpix = (uint32_t)(pixdata[(( yoff + yloop ) * pitch) + xloop + xoff]); + linebuf[xloop] = (uint32_t)(colour | fontpix); + } + } + plot_blit_bitmap(fontbmp, loc->g_x, loc->g_y, 0, BITMAPF_MONOGLYPH); +} + +static void draw_glyph1(FONT_PLOTTER self, GRECT * clip, GRECT * loc, uint8_t * pixdata, int pitch, uint32_t colour) +{ + int xloop,yloop,xoff,yoff; + int x,y,w,h; + uint8_t bitm; + const uint8_t *fntd; + + x = loc->g_x; + y = loc->g_y; + w = loc->g_w; + h = loc->g_h; + + if( !rc_intersect( clip, loc ) ){ + return; + } + + xoff = loc->g_x - x; + yoff = loc->g_y - y; + + if (h > loc->g_h) + h = loc->g_h; + + if (w > loc->g_w) + w = loc->g_w; + + int stride = MFDB_STRIDE( w ); + if( tmp.fd_addr == NULL || tmp_mfdb_size < MFDB_SIZE( 1, stride, h) ){ + tmp_mfdb_size = init_mfdb( 1, w, h, MFDB_FLAG_STAND | MFDB_FLAG_ZEROMEM, &tmp ); + } else { + void * buf = tmp.fd_addr; + int size = init_mfdb( 1, w, h, MFDB_FLAG_STAND | MFDB_FLAG_NOALLOC, &tmp ); + tmp.fd_addr = buf; + memset( tmp.fd_addr, 0, size ); + } + short * buf; + for( yloop = 0; yloop < h; yloop++) { + fntd = pixdata + (pitch * (yloop+yoff))+(xoff>>3); + buf = tmp.fd_addr; + buf += (tmp.fd_wdwidth*yloop); + for ( xloop = 0, bitm = (1<<(7-(xoff%8))); xloop < w; xloop++, bitm=(bitm>>1) ) { + if( (*fntd & bitm) != 0 ){ + short whichbit = (1<<(15-(xloop%16))); + buf[xloop>>4] = ((buf[xloop>>4])|(whichbit)); + } + if( bitm == 1 ) { + fntd++; + bitm = 128; + } + } + } +#ifdef WITH_8BPP_SUPPORT + if( app.nplanes > 8 ){ +#endif + plot_blit_mfdb(loc, &tmp, OFFSET_CUSTOM_COLOR, PLOT_FLAG_TRANS ); +#ifdef WITH_8BPP_SUPPORT + } else { + plot_blit_mfdb(loc, &tmp, colour, PLOT_FLAG_TRANS ); + } +#endif + +} + +static int text( FONT_PLOTTER self, int x, int y, const char *text, size_t length, + const plot_font_style_t *fstyle ) +{ + uint32_t ucs4; + size_t nxtchr = 0; + FT_Glyph glyph; + FT_BitmapGlyph bglyph; + GRECT loc, clip; + uint32_t c = fstyle->foreground ; + struct rect clipping; + /* in -> BGR */ + /* out -> ARGB */ + if( !(self->flags & FONTPLOT_FLAG_MONOGLYPH) ){ + c = ABGR_TO_RGB(c); + } else { +#ifdef WITH_8BPP_SUPPORT + if( app.nplanes > 8 ){ +#endif + RGB1000 out; /* struct with RGB shorts */ + rgb_to_vdi1000( (unsigned char*)&c, &out); + vs_color(atari_plot_vdi_handle, OFFSET_CUSTOM_COLOR, + (short*)&out); +#ifdef WITH_8BPP_SUPPORT + } else { + c = RGB_TO_VDI(c); + } +#endif + } + + plot_get_clip(&clipping); + clip.g_x = clipping.x0; + clip.g_y = clipping.y0; + clip.g_w = (clipping.x1 - clipping.x0)+1; + clip.g_h = (clipping.y1 - clipping.y0)+1; + + fontbmp = atari_bitmap_realloc( clip.g_w, clip.g_h, + 4, clip.g_w << 2, + BITMAP_GROW, fontbmp ); + fontbmp_stride = atari_bitmap_get_rowstride(fontbmp); + fontbmp_allocated_height = clip.g_h; + fontbmp_allocated_width = clip.g_w; + + while (nxtchr < length) { + ucs4 = utf8_to_ucs4(text + nxtchr, length - nxtchr); + nxtchr = utf8_next(text, length, nxtchr); + + glyph = ft_getglyph(fstyle, ucs4); + if (glyph == NULL){ + continue; + } + + if (glyph->format == FT_GLYPH_FORMAT_BITMAP) { + bglyph = (FT_BitmapGlyph)glyph; + loc.g_x = x + bglyph->left; + loc.g_y = y - bglyph->top; + loc.g_w = bglyph->bitmap.width; + loc.g_h = bglyph->bitmap.rows; + + if( loc.g_w > 0) { + self->draw_glyph( self, + &clip, &loc, + bglyph->bitmap.buffer, + bglyph->bitmap.pitch, + c + ); + } + } + x += glyph->advance.x >> 16; + } + return( 0 ); +} + + +int ctor_font_plotter_freetype( FONT_PLOTTER self ) +{ + self->dtor = dtor; + self->str_width = str_width; + self->str_split = str_split; + self->pixel_pos = pixel_pos; + self->text = text; + + /* set the default render mode */ + if( (self->flags & FONTPLOT_FLAG_MONOGLYPH) != 0 ){ + ft_load_type = FT_LOAD_MONOCHROME; + self->draw_glyph = draw_glyph1; + } + else{ + ft_load_type = 0; + self->draw_glyph = draw_glyph8; + } + + LOG("%s: %s\n", (char *)__FILE__, __FUNCTION__); + if( !init ) { + ft_font_init(); + fontbmp = atari_bitmap_create(48, 48, 0); + fontbmp->opaque = false; + init = true; + } + + return( 1 ); +} + +static int dtor( FONT_PLOTTER self ) +{ + ft_font_finalise(); + if( fontbmp != NULL ) { + atari_bitmap_destroy( fontbmp ); + fontbmp = NULL; + } + if( tmp.fd_addr != NULL ){ + free( tmp.fd_addr ); + } + return( 1 ); +} + +#endif diff --git a/frontends/atari/plot/font_freetype.h b/frontends/atari/plot/font_freetype.h new file mode 100644 index 000000000..58a5372a4 --- /dev/null +++ b/frontends/atari/plot/font_freetype.h @@ -0,0 +1,52 @@ +/* + * Copyright 2011 Ole Loots <ole@monochrom.net> + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FONT_PLOTTER_FREETYPE +#define FONT_PLOTTER_FREETYPE + +#include <ft2build.h> +#include FT_FREETYPE_H +#include FT_GLYPH_H +#include "utils/utf8.h" + +/* defines for accesing the faces */ +#define FONT_FACE_DEFAULT 0 + +#define FONT_FACE_SANS_SERIF 0 +#define FONT_FACE_SANS_SERIF_BOLD 1 +#define FONT_FACE_SANS_SERIF_ITALIC 2 +#define FONT_FACE_SANS_SERIF_ITALIC_BOLD 3 +#define FONT_FACE_MONOSPACE 4 +#define FONT_FACE_MONOSPACE_BOLD 5 +#define FONT_FACE_SERIF 6 +#define FONT_FACE_SERIF_BOLD 7 +#define FONT_FACE_CURSIVE 8 +#define FONT_FACE_FANTASY 9 + +#define FONT_FACE_COUNT 10 + +struct font_desc { + const char *name; + int width, height; + const char *encoding; +}; + +/* extern int ft_load_type; */ + +int ctor_font_plotter_freetype( FONT_PLOTTER self ); + +#endif diff --git a/frontends/atari/plot/font_internal.c b/frontends/atari/plot/font_internal.c new file mode 100644 index 000000000..89a56d0e5 --- /dev/null +++ b/frontends/atari/plot/font_internal.c @@ -0,0 +1,2386 @@ +/* + * Copyright 2008 Vincent Sanders <vince@simtec.co.uk> + * Copyright 2011 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifdef WITH_INTERNAL_FONT_DRIVER + +#include <assert.h> +#include <unistd.h> + +#include "utils/utf8.h" +#include "utils/log.h" +#include "desktop/mouse.h" +#include "desktop/plot_style.h" + +#include "atari/gui.h" +#include "atari/bitmap.h" +#include "atari/plot/plot.h" +#include "atari/plot/fontplot.h" +#include "atari/plot/font_internal.h" + + +extern unsigned long atari_plot_flags; +extern int atari_plot_vdi_handle; + +static int dtor( FONT_PLOTTER self ); +static int str_width( FONT_PLOTTER self,const plot_font_style_t *fstyle, const char * str, size_t length, int * width ); +static int str_split( FONT_PLOTTER self, const plot_font_style_t *fstyle,const char *string, + size_t length,int x, size_t *char_offset, int *actual_x ); +static int pixel_pos( FONT_PLOTTER self, const plot_font_style_t *fstyle,const char *string, + size_t length,int x, size_t *char_offset, int *actual_x ); +static int text( FONT_PLOTTER self, int x, int y, const char *text, size_t length, const plot_font_style_t *fstyle ); + +static bool init = false; +static int vdih; +static struct bitmap * fontbmp; +extern struct s_vdi_sysinfo vdi_sysinfo; + +const struct fb_font_desc font_regular; +const struct fb_font_desc font_italic; +const struct fb_font_desc font_bold; +const struct fb_font_desc font_italic_bold; + +static MFDB tmp; +static int tmp_mfdb_size; + +#define FONTDATAMAX 4096 + +static const struct fb_font_desc* +fb_get_font(const plot_font_style_t *fstyle) +{ + if (fstyle->weight >= 700) { + if ((fstyle->flags & FONTF_ITALIC) || + (fstyle->flags & FONTF_OBLIQUE)) { + return &font_italic_bold; + } else { + return &font_bold; + } + } else { + if ((fstyle->flags & FONTF_ITALIC) || + (fstyle->flags & FONTF_OBLIQUE)) { + return &font_italic; + } else { + return &font_regular; + } + } +} + +static nserror utf8_to_font_encoding(const struct fb_font_desc* font, + const char *string, + size_t len, + char **result) +{ + return utf8_to_enc(string, font->encoding, len, result); + +} + +int ctor_font_plotter_internal( FONT_PLOTTER self ) +{ + self->dtor = dtor; + self->str_width = str_width; + self->str_split = str_split; + self->pixel_pos = pixel_pos; + self->text = text; + LOG("%s: %s\n", (char *)__FILE__, __FUNCTION__); + if( !init ) { + vdih = self->vdi_handle; + fontbmp = atari_bitmap_create(48, 48, 0); + fontbmp->opaque = false; + } + init = true; + return( 1 ); +} + +static int dtor( FONT_PLOTTER self ) +{ + if( tmp.fd_addr != NULL ){ + free( tmp.fd_addr ); + } + return( 1 ); +} + +static int str_width( FONT_PLOTTER self,const plot_font_style_t *fstyle, const char * str, + size_t length, int * width ) +{ + const struct fb_font_desc* fb_font = fb_get_font(fstyle); + *width = fb_font->width * utf8_bounded_length(str, length); + return( 1 ); +} + +static int str_split( FONT_PLOTTER self, const plot_font_style_t * fstyle, const char *string, + size_t length,int x, size_t *char_offset, int *actual_x ) +{ + const struct fb_font_desc* fb_font = fb_get_font(fstyle); + int c_off = *char_offset = x / fb_font->width; + if (*char_offset > length) { + *char_offset = length; + } else { + while (*char_offset > 0) { + if (string[*char_offset] == ' ') + break; + (*char_offset)--; + } + if (*char_offset == 0) { + *char_offset = c_off; + while (*char_offset < length && + string[*char_offset] != ' ') { + (*char_offset)++; + } + } + } + *actual_x = *char_offset * fb_font->width; + return( 1 ); +} + +static int pixel_pos( FONT_PLOTTER self, const plot_font_style_t * fstyle,const char *string, + size_t length,int x, size_t *char_offset, int *actual_x ) +{ + const struct fb_font_desc* fb_font = fb_get_font(fstyle); + *char_offset = x / fb_font->width; + if (*char_offset > length) + *char_offset = length; + *actual_x = *char_offset * fb_font->width; + return( 1 ); +} + +static void draw_glyph1(FONT_PLOTTER self, GRECT *inloc, uint8_t *chrp, int pitch, uint32_t colour ) +{ + size_t bmpstride; + GRECT clip; + uint32_t * fontdata; + int xloop,yloop; + int stride = pitch / 8; + uint32_t * linebuf; + GRECT loc = *inloc; + + fontbmp = atari_bitmap_realloc( loc.g_w, loc.g_h, fontbmp->bpp, loc.g_w * fontbmp->bpp, BITMAP_GROW, fontbmp ); + bmpstride = atari_bitmap_get_rowstride(fontbmp); + for( yloop = 0; yloop < loc.g_h; yloop++) { + uint32_t pixmask = 1 ; + linebuf = (uint32_t *)(fontbmp->pixdata + (bmpstride * yloop)); + fontdata = (uint32_t*)(chrp + (stride*yloop)); + for(xloop = loc.g_w-1; xloop>=0; xloop--){ + linebuf[xloop] = ((pixmask & *fontdata) == 0) ? 0 : colour; + pixmask = (pixmask << 1); + } + } + plot_blit_bitmap(fontbmp, loc.g_x, loc.g_y, 0, BITMAPF_MONOGLYPH ); +} + +static int text( FONT_PLOTTER self, int x, int y, const char *text, size_t length, + const plot_font_style_t *fstyle ) +{ + const struct fb_font_desc* fb_font = fb_get_font(fstyle); + const uint32_t *chrp; + char *buffer = NULL; + int chr; + int blen; + GRECT loc; + uint32_t c; + + utf8_to_font_encoding(fb_font, text, length, &buffer); + if (buffer == NULL) + return 1; + + /* y is given to the fonts baseline we need it to the fonts top */ + y-=((fb_font->height * 75)/100); + + /* needed? */ + y+=1; /* the coord is the bottom-left of the pixels offset by 1 to make + * it work since fb coords are the top-left of pixels + */ + blen = strlen(buffer); + if ( blen < 1 ) { + return( 1 ); + } + + if(atari_plot_flags & PLOT_FLAG_OFFSCREEN ){ + /* when the plotter is an offscreen plotter the call to + bitmap() isn't that expensive. Draw an 8 bit bitmap into the + offscreen buffer. + */ + c = fstyle->foreground; + /* in -> BGR */ + /* out -> ARGB */ + c = (ABGR_TO_RGB(c) | 0xFF); + loc.g_y = y; + loc.g_x = x; + loc.g_w = fb_font->width; + loc.g_h = fb_font->height; + for (chr = 0; chr < blen; chr++) { + loc.g_x = x; + chrp = fb_font->data + ((unsigned char)buffer[chr] * fb_font->height); + draw_glyph1(self, &loc, (uint8_t *)chrp, 32, c); + x+=fb_font->width; + } + } else { + /* render the whole string into an monochrom mfdb */ + /* and plot that to reduce overhead */ + loc.g_x = x; + loc.g_y = y; + loc.g_w = blen * fb_font->width; + assert( loc.g_w > 0 ); + loc.g_h = fb_font->height; + int stride = MFDB_STRIDE( loc.g_w ); + if( tmp.fd_addr == NULL || tmp_mfdb_size < MFDB_SIZE( 1, stride, loc.g_h) ){ + tmp_mfdb_size = init_mfdb( 1, loc.g_w, loc.g_h+1, MFDB_FLAG_STAND | MFDB_FLAG_ZEROMEM, &tmp ); + } else { + void * buf = tmp.fd_addr; + int size = init_mfdb( 1, loc.g_w, loc.g_h+1, MFDB_FLAG_STAND | MFDB_FLAG_NOALLOC, &tmp ); + tmp.fd_addr = buf; + memset( tmp.fd_addr, 0, size ); + } + short ypos; + int rowsize = tmp.fd_wdwidth << 1; + char * d; + uint32_t * pp; + for (chr = 0; chr < blen; chr++) { + pp = (uint32_t*)fb_font->data + ((unsigned char)buffer[chr] * fb_font->height); + d = ((uint8_t*)tmp.fd_addr) + chr; + for( ypos=0; ypos<loc.g_h; ypos++){ + *d = (unsigned char)*pp++; + d += rowsize; + } + } +#ifdef WITH_8BPP_SUPPORT + if( app.nplanes > 8 ){ +#endif + //unsigned short out[4]; + RGB1000 out; + //rgb_to_vdi1000( (unsigned char*)&fstyle->foreground, (unsigned short*)&out ); + out.blue = 0; + out.green = 1000; + out.red = 0; + vs_color(atari_plot_vdi_handle, OFFSET_CUSTOM_COLOR, (short *)&out); + vq_color(atari_plot_vdi_handle, OFFSET_CUSTOM_COLOR, 1, (short *)&out); + //printf("r:%d,g:%d,b:%d", out.red, out.green, out.blue); + //vsl_color(atari_plot_vdi_handle, OFFSET_CUSTOM_COLOR); + //vsf_color(atari_plot_vdi_handle, OFFSET_CUSTOM_COLOR); + plot_blit_mfdb(&loc, &tmp, OFFSET_CUSTOM_COLOR, PLOT_FLAG_TRANS); +#ifdef WITH_8BPP_SUPPORT + } else { + unsigned char c = RGB_TO_VDI(fstyle->foreground); + plot_blit_mfdb(&loc, &tmp, c, PLOT_FLAG_TRANS ); + } +#endif + } + + free(buffer); + return( 1 ); +} + +/* ------------------*/ +/* Fontdata */ +/* ------------------*/ + +static const uint32_t fontdata_bold[FONTDATAMAX] = { + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0xE4, 0xAC, 0xA4, 0xA4, 0xEE, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0xEC, 0xA2, 0xA4, 0xA8, 0xEE, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0xEC, 0xA2, 0xAC, 0xA2, 0xEC, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0xEA, 0xAA, 0xAE, 0xA2, 0xE2, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0xEE, 0xA8, 0xAE, 0xA2, 0xEE, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0xE6, 0xA8, 0xAE, 0xAA, 0xEE, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0xEE, 0xA2, 0xA4, 0xA4, 0xE4, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0xEE, 0xAA, 0xAE, 0xAA, 0xEE, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0xEE, 0xAA, 0xAE, 0xA2, 0xE2, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0xE4, 0xAA, 0xAE, 0xAA, 0xEA, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0xEC, 0xAA, 0xAC, 0xAA, 0xEC, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0xE4, 0xAA, 0xA8, 0xAA, 0xE4, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0xEC, 0xAA, 0xAA, 0xAA, 0xEC, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0xEE, 0xA8, 0xAC, 0xA8, 0xEE, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0xEE, 0xA8, 0xAC, 0xA8, 0xE8, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0x4E, 0xCA, 0x4A, 0x4A, 0xEE, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0x44, 0xCC, 0x44, 0x44, 0xEE, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0x4C, 0xC2, 0x44, 0x48, 0xEE, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0x4C, 0xC2, 0x4C, 0x42, 0xEC, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0x4A, 0xCA, 0x4E, 0x42, 0xE2, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0x4E, 0xC8, 0x4E, 0x42, 0xEE, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0x46, 0xC8, 0x4E, 0x4A, 0xEE, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0x4E, 0xC2, 0x44, 0x44, 0xE4, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0x4E, 0xCA, 0x4E, 0x4A, 0xEE, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0x4E, 0xCA, 0x4E, 0x42, 0xE2, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0x44, 0xCA, 0x4E, 0x4A, 0xEA, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0x4C, 0xCA, 0x4C, 0x4A, 0xEC, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0x44, 0xCA, 0x48, 0x4A, 0xE4, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0x4C, 0xCA, 0x4A, 0x4A, 0xEC, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0x4E, 0xC8, 0x4C, 0x48, 0xEE, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0x4E, 0xC8, 0x4C, 0x48, 0xE8, 0x00, 0xFE, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, + 0x1C, 0x00, 0x1C, 0x1C, 0x1C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x6C, 0x6C, 0xFE, 0xFE, 0xFE, 0x6C, 0x6C, + 0xFE, 0xFE, 0xFE, 0x6C, 0x6C, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x7C, 0xFE, 0xF6, 0xF0, 0xF8, 0x7C, + 0x3E, 0x1E, 0xDE, 0xFE, 0x7C, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xE0, 0xE6, 0xEE, 0x1C, + 0x38, 0x70, 0xEE, 0xCE, 0x0E, 0x00, 0x00, 0x00, + 0x00, 0x70, 0xF8, 0xF8, 0xF8, 0xF8, 0x76, 0xFE, + 0xFE, 0xEC, 0xEE, 0xFE, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x0C, 0x1C, 0x38, 0x38, 0x70, 0x70, 0x70, + 0x70, 0x70, 0x38, 0x38, 0x1C, 0x0C, 0x06, 0x00, + 0x60, 0x30, 0x38, 0x1C, 0x1C, 0x0E, 0x0E, 0x0E, + 0x0E, 0x0E, 0x1C, 0x1C, 0x38, 0x30, 0x60, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x54, 0xFE, 0x7C, 0x38, + 0x7C, 0xFE, 0x54, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x38, 0xFE, + 0xFE, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x38, 0x78, 0x70, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, + 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x1E, 0x3C, + 0x78, 0xF0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x7C, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0x7C, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x38, 0x78, 0x78, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0xFE, 0xEE, 0x0E, 0x0E, 0x7E, 0xFC, + 0xE0, 0xE0, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0xFE, 0xEE, 0x0E, 0x0E, 0x3C, 0x3C, + 0x0E, 0x0E, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x0C, 0x1C, 0x3C, 0x7C, 0x6C, 0xEC, + 0xFE, 0xFE, 0x1C, 0x1C, 0x1C, 0x00, 0x00, 0x00, + 0x00, 0xFE, 0xFE, 0xE0, 0xE0, 0xFC, 0xFE, 0x0E, + 0x0E, 0x0E, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0xFC, 0xE0, 0xE0, 0xFC, 0xFE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0xFE, 0xFE, 0x0E, 0x0E, 0x1C, 0x1C, 0x1C, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0xFE, 0xEE, 0xEE, 0xFE, 0x7C, 0xFE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0xFE, 0xEE, 0xEE, 0xEE, 0xFE, 0x7E, + 0x0E, 0x0E, 0x0E, 0x7C, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x38, 0x00, + 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x38, 0x00, + 0x00, 0x18, 0x38, 0x38, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x0E, 0x1C, 0x38, 0x70, + 0x70, 0x38, 0x1C, 0x0E, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x00, + 0x00, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x60, 0x70, 0x38, 0x1C, 0x0E, + 0x0E, 0x1C, 0x38, 0x70, 0x60, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0xFE, 0xEE, 0x0E, 0x0E, 0x3E, 0x7C, + 0x70, 0x00, 0x70, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0xFE, 0xEE, 0xEE, 0xEE, 0xFE, 0xFE, + 0xEC, 0xE0, 0xE0, 0xFC, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0xFE, 0xEE, 0xEE, 0xEE, 0xEE, 0xFE, + 0xFE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0xFC, 0xFE, 0xEE, 0xEE, 0xEE, 0xFC, 0xFC, + 0xEE, 0xEE, 0xEE, 0xFE, 0xFC, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0xFE, 0xEE, 0xEE, 0xE0, 0xE0, 0xE0, + 0xE0, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0xF8, 0xFC, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFC, 0xF8, 0x00, 0x00, 0x00, + 0x00, 0xFE, 0xFE, 0xE0, 0xE0, 0xE0, 0xF8, 0xF8, + 0xE0, 0xE0, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0xFE, 0xFE, 0xE0, 0xE0, 0xE0, 0xF8, 0xF8, + 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0xFE, 0xEE, 0xEE, 0xE0, 0xE0, 0xFE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xFE, 0xFE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0xFE, 0xFE, 0x38, 0x38, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x38, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, + 0x0E, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0xE0, 0xE6, 0xEE, 0xFE, 0xFC, 0xF8, 0xF0, + 0xF8, 0xFC, 0xFE, 0xEE, 0xE6, 0x00, 0x00, 0x00, + 0x00, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, + 0xE0, 0xE0, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0xC6, 0xEE, 0xFE, 0xFE, 0xFE, 0xFE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0xCE, 0xEE, 0xEE, 0xFE, 0xFE, 0xFE, 0xFE, + 0xFE, 0xFE, 0xEE, 0xEE, 0xE6, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0xFE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0xFC, 0xFE, 0xEE, 0xEE, 0xEE, 0xEE, 0xFE, + 0xFC, 0xE0, 0xE0, 0xE0, 0xE0, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0xFE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xFE, 0xFE, 0xFE, 0x7E, 0x06, 0x00, 0x00, + 0x00, 0xFC, 0xFE, 0xEE, 0xEE, 0xEE, 0xFE, 0xFC, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0xFE, 0xEE, 0xE0, 0xE0, 0xFC, 0x7E, + 0x0E, 0x0E, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0xFE, 0xFE, 0x38, 0x38, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, + 0x00, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0x6C, 0x7C, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, + 0x00, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xFE, 0xFE, 0xFE, 0xEE, 0x44, 0x00, 0x00, 0x00, + 0x00, 0xEE, 0xEE, 0xEE, 0xEE, 0x7C, 0x38, 0x38, + 0x7C, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x7C, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, + 0x00, 0xFE, 0xFE, 0x0E, 0x0E, 0x1C, 0x38, 0x38, + 0x70, 0xE0, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x3E, 0x3E, 0x38, 0x38, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x38, 0x3E, 0x3E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x40, 0xE0, 0xF0, 0x78, + 0x3C, 0x1E, 0x0E, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xFC, 0xFC, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, + 0x1C, 0x1C, 0x1C, 0xFC, 0xFC, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x7C, 0xEE, 0xC6, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, + 0x00, 0x00, 0x00, 0x30, 0x38, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x7E, 0x0E, + 0x7E, 0xFE, 0xEE, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0xE0, 0xE0, 0xE0, 0xE0, 0xFC, 0xFE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0xFC, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xFE, 0xEE, + 0xE0, 0xE0, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x0E, 0x0E, 0x0E, 0x0E, 0x7E, 0xFE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xFE, 0xEE, + 0xFE, 0xFE, 0xE0, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x3E, 0x7E, 0x70, 0x70, 0x70, 0xF8, 0xF8, + 0x70, 0x70, 0x70, 0x70, 0x70, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xFE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7E, 0x0E, 0x7E, 0x7C, + 0x00, 0x00, 0xE0, 0xE0, 0xE0, 0xFC, 0xFE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x38, 0x00, 0x78, 0x78, 0x38, + 0x38, 0x38, 0x38, 0x7C, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1C, 0x1C, 0x00, 0x3C, 0x3C, 0x1C, + 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x7C, 0x78, + 0x00, 0xE0, 0xE0, 0xE0, 0xE6, 0xEE, 0xFE, 0xFC, + 0xF8, 0xFC, 0xFE, 0xEE, 0xE6, 0x00, 0x00, 0x00, + 0x00, 0x78, 0x78, 0x38, 0x38, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0xFE, 0xFE, + 0xFE, 0xFE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xFE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0xFC, 0xE0, 0xE0, 0xE0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xFE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7E, 0x0E, 0x0F, 0x0F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xDE, 0xFE, 0xE0, + 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xFE, 0xE0, + 0xFC, 0x7E, 0x0E, 0xFE, 0xFC, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x30, 0x70, 0x70, 0xFC, 0xFC, 0x70, + 0x70, 0x70, 0x70, 0x7E, 0x3E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0x7C, 0x38, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xEE, 0xEE, 0xEE, + 0xFE, 0xFE, 0xFE, 0xEE, 0x44, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xEE, 0xEE, 0xEE, + 0x7C, 0x7C, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xFE, 0x7E, 0x0E, 0x0E, 0xFE, 0xFC, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x1E, + 0x3C, 0x78, 0xF0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x1E, 0x3E, 0x38, 0x38, 0x38, 0xF0, 0xF0, + 0x38, 0x38, 0x38, 0x3E, 0x1E, 0x00, 0x00, 0x00, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, + 0x00, 0xF0, 0xF8, 0x38, 0x38, 0x38, 0x1E, 0x1E, + 0x38, 0x38, 0x38, 0xF8, 0xF0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x66, 0xFE, 0xFE, 0xCC, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0xEE, 0x28, 0x4C, 0x48, 0x48, 0x00, 0xFE, + 0x00, 0x38, 0x7C, 0xEE, 0xE0, 0xFC, 0xE0, 0xF8, + 0xE0, 0xE0, 0xEE, 0x7C, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x38, 0x6C, 0x54, 0xF6, 0xEE, + 0x6C, 0x7C, 0x28, 0x38, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x38, 0x38, 0x18, 0x30, 0x00, + 0x00, 0x3E, 0x7E, 0x70, 0x70, 0x70, 0xF8, 0xF8, + 0x70, 0x70, 0x70, 0x70, 0x70, 0xF0, 0xE0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xEE, 0xEE, 0x66, 0xCC, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xDB, 0xDB, 0xDB, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x38, 0x38, 0x38, 0xFE, 0xFE, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, + 0x00, 0x38, 0x38, 0x38, 0xFE, 0xFE, 0x38, 0xFE, + 0xFE, 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, + 0x00, 0x7C, 0xEE, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xCE, 0x1C, + 0x38, 0x70, 0xE0, 0xDB, 0x1B, 0x00, 0x00, 0x00, + 0xEE, 0x7C, 0x00, 0x7C, 0xFE, 0xEE, 0xE0, 0xFC, + 0x7E, 0x0E, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0E, 0x1C, + 0x38, 0x70, 0x38, 0x1C, 0x0E, 0x06, 0x00, 0x00, + 0x00, 0x7F, 0xFF, 0xEE, 0xEE, 0xEE, 0xEF, 0xEF, + 0xEE, 0xEE, 0xEE, 0xFF, 0x7F, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x38, 0x6C, 0x54, 0xF6, 0xEE, + 0x6C, 0x7C, 0x28, 0x38, 0x10, 0x00, 0x00, 0x00, + 0xEE, 0x7C, 0x00, 0xFE, 0xFE, 0x0E, 0x1E, 0x3C, + 0x78, 0xF0, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x38, 0x6C, 0x54, 0xF6, 0xEE, + 0x6C, 0x7C, 0x28, 0x38, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x38, 0x6C, 0x54, 0xF6, 0xEE, + 0x6C, 0x7C, 0x28, 0x38, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x30, 0x30, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x36, 0x6C, 0x6C, 0x6C, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x36, 0x36, 0x36, 0x6C, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x7E, + 0x7E, 0x7E, 0x7E, 0x3C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7B, 0xDE, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xF1, 0xFB, 0x5F, 0x55, 0x51, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xEE, 0x7C, 0x38, 0x00, 0x7E, 0xFE, 0xE0, + 0xFC, 0x7E, 0x0E, 0xFE, 0xFC, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x70, 0x38, + 0x1C, 0x0E, 0x1C, 0x38, 0x70, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x6C, 0xFE, 0xFA, + 0xDE, 0xDE, 0xFC, 0xFE, 0x6E, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x38, 0x6C, 0x54, 0xF6, 0xEE, + 0x6C, 0x7C, 0x28, 0x38, 0x10, 0x00, 0x00, 0x00, + 0x00, 0xEE, 0x7C, 0x38, 0x00, 0xFE, 0xFE, 0x1E, + 0x3C, 0x78, 0xF0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0xEE, 0x00, 0xEE, 0xEE, 0xEE, 0xEE, 0x7C, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x38, 0x00, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x10, 0x7C, 0xFE, 0xD6, + 0xD0, 0xD0, 0xD6, 0xFE, 0x7C, 0x10, 0x10, 0x00, + 0x00, 0x3C, 0x7E, 0x76, 0x70, 0xFC, 0xFC, 0xFC, + 0x70, 0x76, 0xFE, 0xFE, 0xDC, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEE, 0xEE, 0x7C, 0xFE, + 0xFE, 0xFE, 0xFE, 0x7C, 0xEE, 0xEE, 0x00, 0x00, + 0x00, 0x00, 0xEE, 0xEE, 0xEE, 0x7C, 0x38, 0xFE, + 0x38, 0xFE, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x38, 0x38, 0x38, 0x38, 0x00, + 0x00, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x3C, 0x7C, 0x7C, 0x70, 0x3C, 0x7E, 0x66, + 0x7E, 0x3C, 0x0E, 0x3E, 0x3E, 0x3C, 0x00, 0x00, + 0x00, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3C, 0x7E, 0xC3, 0x99, 0xBD, 0xA5, 0xA1, + 0xA5, 0xBD, 0x99, 0xC3, 0x7E, 0x3C, 0x00, 0x00, + 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x7C, 0x00, 0xFC, + 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, + 0x7C, 0xF8, 0xF8, 0x7C, 0x3E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7E, 0x7E, 0x7E, 0x06, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7E, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3C, 0x7E, 0xC3, 0xB9, 0xBD, 0xA5, 0xB9, + 0xB9, 0xA5, 0xA5, 0xC3, 0x7E, 0x3C, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x78, 0xFC, 0xCC, 0xFC, 0x78, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x38, 0xFE, 0xFE, 0xFE, 0x38, + 0x38, 0x00, 0xFE, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xF0, 0xF8, 0x18, 0x78, 0xF0, 0xC0, + 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xF0, 0xF8, 0x18, 0x30, 0x18, 0xF8, + 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x38, 0x70, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0xFC, 0xE0, 0xE0, 0xC0, + 0x00, 0x00, 0x00, 0x7F, 0xDB, 0xDB, 0xDB, 0x7B, + 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x38, + 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x1C, 0x0C, 0x1C, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x60, 0xE0, 0x60, 0x60, 0x60, 0xF0, + 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x70, 0xF8, 0x88, 0xF8, 0x70, 0x00, 0xF8, + 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, + 0x6C, 0x36, 0x36, 0x6C, 0xD8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x60, 0xE0, 0x62, 0x66, 0xFE, 0x1C, + 0x38, 0x76, 0xEE, 0xD6, 0x3E, 0x3E, 0x06, 0x00, + 0x00, 0x00, 0x60, 0xE0, 0x62, 0x66, 0xFE, 0x1C, + 0x38, 0x70, 0xFC, 0xC6, 0x0C, 0x18, 0x1E, 0x00, + 0x00, 0x00, 0xE0, 0x30, 0x62, 0x36, 0xEE, 0x1C, + 0x3A, 0x76, 0xEE, 0xD6, 0x3E, 0x3E, 0x06, 0x00, + 0x00, 0x00, 0x1C, 0x1C, 0x1C, 0x00, 0x1C, 0x1C, + 0x7C, 0xF8, 0xE0, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, + 0x00, 0xE0, 0x70, 0x00, 0x10, 0x38, 0x7C, 0xEE, + 0xFE, 0xFE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0x0E, 0x1C, 0x00, 0x10, 0x38, 0x7C, 0xEE, + 0xFE, 0xFE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6C, 0xC6, 0x10, 0x38, 0x7C, 0xEE, + 0xFE, 0xFE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0x76, 0xDC, 0x00, 0x10, 0x38, 0x7C, 0xEE, + 0xFE, 0xFE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0xEE, 0xEE, 0x10, 0x38, 0x7C, 0xEE, 0xFE, + 0xFE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6C, 0x38, 0x38, 0x7C, 0xEE, 0xFE, + 0xFE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0x1F, 0x3F, 0x7F, 0xFE, 0xEE, 0xFF, 0xFF, + 0xFE, 0xEE, 0xEF, 0xEF, 0xEF, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0xFE, 0xEE, 0xE0, 0xE0, 0xE0, 0xE0, + 0xE0, 0xE0, 0xEE, 0xFE, 0x7C, 0x0E, 0x6E, 0x7C, + 0x00, 0x70, 0x38, 0x00, 0xFE, 0xFE, 0xE0, 0xE0, + 0xF8, 0xE0, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x1C, 0x38, 0x00, 0xFE, 0xFE, 0xE0, 0xE0, + 0xF8, 0xE0, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0xEE, 0x00, 0xFE, 0xFE, 0xE0, 0xE0, + 0xF8, 0xE0, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0xEE, 0xEE, 0x00, 0xFE, 0xFE, 0xE0, 0xE0, 0xF8, + 0xF8, 0xE0, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x70, 0x38, 0x00, 0x38, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x1C, 0x38, 0x00, 0x38, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6C, 0x38, 0x38, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, + 0x00, 0xEE, 0xEE, 0x00, 0x38, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xF8, 0xFC, 0xEE, 0xEE, 0xEE, 0xFE, + 0xEE, 0xEE, 0xEE, 0xFC, 0xF8, 0x00, 0x00, 0x00, + 0x00, 0x76, 0xDC, 0x00, 0xEE, 0xEE, 0xEE, 0xF6, + 0xFE, 0xDE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0x70, 0x38, 0x00, 0x7C, 0xFE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x1C, 0x38, 0x00, 0x7C, 0xFE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0xEE, 0x00, 0x7C, 0xFE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x76, 0xDC, 0x00, 0x7C, 0xFE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0xEE, 0xEE, 0x00, 0x7C, 0xFE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xEE, 0x7C, + 0x38, 0x38, 0x7C, 0xEE, 0xC6, 0x00, 0x00, 0x00, + 0x00, 0x7A, 0xFC, 0xEE, 0xEE, 0xEE, 0xFE, 0xFE, + 0xFE, 0xEE, 0xEE, 0xFE, 0x7C, 0x80, 0x00, 0x00, + 0x00, 0x70, 0x38, 0x00, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x1C, 0x38, 0x00, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0xEE, 0x00, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0xEE, 0xEE, 0x00, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x1C, 0x38, 0x00, 0xEE, 0xEE, 0xEE, 0xEE, + 0x7C, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xE0, 0xE0, 0xFC, 0xFE, 0xEE, 0xEE, + 0xEE, 0xFE, 0xFC, 0xE0, 0xE0, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0xFE, 0xEE, 0xEE, 0xEE, 0xFE, 0xFC, + 0xEE, 0xEE, 0xEE, 0xFE, 0xFC, 0xE0, 0xC0, 0x00, + 0x00, 0x00, 0x70, 0x38, 0x00, 0x7C, 0x7E, 0x0E, + 0x7E, 0xFE, 0xEE, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1C, 0x38, 0x00, 0x7C, 0x7E, 0x0E, + 0x7E, 0xFE, 0xEE, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x7C, 0xEE, 0x00, 0x7C, 0x7E, 0x0E, + 0x7E, 0xFE, 0xEE, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x76, 0xDC, 0x00, 0x7C, 0x7E, 0x0E, + 0x7E, 0xFE, 0xEE, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xEE, 0xEE, 0x00, 0x7C, 0x7E, 0x0E, + 0x7E, 0xFE, 0xEE, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6C, 0x38, 0x00, 0x7C, 0x7E, 0x0E, + 0x7E, 0xFE, 0xEE, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x74, 0x7E, 0x7E, 0x1A, + 0x7E, 0xFE, 0xD8, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xFE, + 0xEE, 0xE0, 0xEE, 0xFE, 0x7C, 0x1C, 0x7E, 0x7C, + 0x00, 0x00, 0x70, 0x38, 0x00, 0x7C, 0xFE, 0xEE, + 0xFE, 0xFE, 0xE0, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x70, 0x00, 0x7C, 0xFE, 0xEE, + 0xFE, 0xFE, 0xE0, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x7C, 0xEE, 0x00, 0x7C, 0xFE, 0xEE, + 0xFE, 0xFE, 0xE0, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xEE, 0xEE, 0x00, 0x7C, 0xFE, 0xEE, + 0xFE, 0xFE, 0xE0, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x70, 0x38, 0x00, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1C, 0x38, 0x00, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x7C, 0xEE, 0x00, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xEE, 0xEE, 0x00, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, + 0x00, 0xEC, 0x7C, 0xF8, 0xFC, 0x7E, 0xFE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x76, 0xFE, 0xDC, 0x00, 0xFC, 0xFE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xE0, 0x70, 0x00, 0x7C, 0xFE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x70, 0x00, 0x7C, 0xFE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x7C, 0xEE, 0x00, 0x7C, 0xFE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x76, 0xFE, 0xDC, 0x00, 0x7C, 0xFE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xEE, 0xEE, 0x00, 0x7C, 0xFE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0xFE, + 0xFE, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x7C, 0xFE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x80, 0x00, 0x00, + 0x00, 0x00, 0xE0, 0x70, 0x00, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x70, 0x00, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x7C, 0xEE, 0x00, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xEE, 0xEE, 0x00, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1C, 0x38, 0x00, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7E, 0x0E, 0xFE, 0xFC, + 0x00, 0x00, 0xE0, 0xE0, 0xFC, 0xFE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xFE, 0xFC, 0xE0, 0xE0, + 0x00, 0x00, 0xEE, 0xEE, 0x00, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7E, 0x0E, 0xFE, 0xFC, +}; + +const struct fb_font_desc font_bold = { + .name = "NetSurf Bold", + .width = 8, + .height = 16, + .encoding = "CP1252", + .data = fontdata_bold, +}; + + +static const uint32_t fontdata_italic[FONTDATAMAX] = { + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0xE4, 0xAC, 0xA4, 0xA4, 0xEE, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0xEC, 0xA2, 0xA4, 0xA8, 0xEE, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0xEC, 0xA2, 0xAC, 0xA2, 0xEC, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0xEA, 0xAA, 0xAE, 0xA2, 0xE2, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0xEE, 0xA8, 0xAE, 0xA2, 0xEE, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0xE6, 0xA8, 0xAE, 0xAA, 0xEE, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0xEE, 0xA2, 0xA4, 0xA4, 0xE4, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0xEE, 0xAA, 0xAE, 0xAA, 0xEE, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0xEE, 0xAA, 0xAE, 0xA2, 0xE2, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0xE4, 0xAA, 0xAE, 0xAA, 0xEA, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0xEC, 0xAA, 0xAC, 0xAA, 0xEC, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0xE4, 0xAA, 0xA8, 0xAA, 0xE4, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0xEC, 0xAA, 0xAA, 0xAA, 0xEC, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0xEE, 0xA8, 0xAC, 0xA8, 0xEE, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0xEE, 0xA8, 0xAC, 0xA8, 0xE8, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0x4E, 0xCA, 0x4A, 0x4A, 0xEE, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0x44, 0xCC, 0x44, 0x44, 0xEE, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0x4C, 0xC2, 0x44, 0x48, 0xEE, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0x4C, 0xC2, 0x4C, 0x42, 0xEC, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0x4A, 0xCA, 0x4E, 0x42, 0xE2, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0x4E, 0xC8, 0x4E, 0x42, 0xEE, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0x46, 0xC8, 0x4E, 0x4A, 0xEE, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0x4E, 0xC2, 0x44, 0x44, 0xE4, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0x4E, 0xCA, 0x4E, 0x4A, 0xEE, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0x4E, 0xCA, 0x4E, 0x42, 0xE2, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0x44, 0xCA, 0x4E, 0x4A, 0xEA, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0x4C, 0xCA, 0x4C, 0x4A, 0xEC, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0x44, 0xCA, 0x48, 0x4A, 0xE4, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0x4C, 0xCA, 0x4A, 0x4A, 0xEC, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0x4E, 0xC8, 0x4C, 0x48, 0xEE, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0x4E, 0xC8, 0x4C, 0x48, 0xE8, 0x00, 0xFE, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x06, 0x06, 0x06, 0x06, 0x0C, 0x0C, 0x0C, + 0x0C, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1B, 0x1B, 0x36, 0x36, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1B, 0x1B, 0x1B, 0x7F, 0x7F, 0x36, 0x36, + 0xFF, 0xFF, 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x3E, 0x7F, 0x6B, 0x68, 0x78, 0x3C, + 0x1E, 0x16, 0xD6, 0xFE, 0x7C, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xCE, 0x1C, + 0x38, 0x70, 0xE6, 0xC6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1C, 0x3E, 0x36, 0x36, 0x3C, 0x39, 0x7F, + 0x6E, 0xCC, 0xCC, 0xFE, 0x7A, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x06, 0x06, 0x0C, 0x0C, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x0E, 0x1C, 0x38, 0x30, 0x60, 0x60, 0xC0, + 0xC0, 0xC0, 0xC0, 0xC0, 0xE0, 0x70, 0x30, 0x00, + 0x18, 0x1C, 0x0E, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x0C, 0x0C, 0x18, 0x38, 0x70, 0xE0, 0xC0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x1C, 0x7F, + 0xFE, 0x38, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, + 0xFC, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x38, 0x70, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xFC, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0E, 0x1C, + 0x38, 0x70, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1E, 0x3F, 0x33, 0x33, 0x67, 0x6E, 0x76, + 0xE6, 0xCC, 0xCC, 0xFC, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x06, 0x0E, 0x1E, 0x3C, 0x0C, 0x0C, 0x18, + 0x18, 0x18, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x1E, 0x3F, 0x33, 0x03, 0x07, 0x1E, 0x7C, + 0x60, 0xC0, 0xC0, 0xFC, 0xFC, 0x00, 0x00, 0x00, + 0x00, 0x1E, 0x3F, 0x33, 0x03, 0x06, 0x1E, 0x1E, + 0x06, 0x06, 0xCC, 0xFC, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1E, 0x36, 0x7F, + 0x7F, 0x0C, 0x0C, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x1F, 0x1F, 0x30, 0x30, 0x7C, 0x7E, 0x06, + 0x06, 0x06, 0xCE, 0xFC, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x0F, 0x1F, 0x38, 0x30, 0x60, 0x7C, 0x7E, + 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x3F, 0x7F, 0x63, 0x03, 0x06, 0x06, 0x0C, + 0x0C, 0x18, 0x18, 0x30, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x1E, 0x3F, 0x33, 0x33, 0x33, 0x1E, 0x7C, + 0x66, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x1E, 0x3F, 0x33, 0x63, 0x63, 0x7E, 0x3E, + 0x06, 0x0C, 0x1C, 0xF8, 0xF0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00, + 0x00, 0x00, 0x18, 0x38, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x06, 0x0E, 0x1C, 0x38, 0x70, 0x70, + 0x70, 0x38, 0x1C, 0x0C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3E, 0x7C, 0x00, 0x00, + 0x7C, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x0C, 0x0C, 0x06, 0x0E, + 0x1C, 0x38, 0x70, 0x60, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1E, 0x3F, 0x33, 0x33, 0x03, 0x07, 0x0E, + 0x1C, 0x18, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x1E, 0x3F, 0x33, 0x63, 0x6F, 0x6B, 0x6B, + 0xCF, 0xCE, 0xC0, 0xFC, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x1E, 0x3F, 0x33, 0x33, 0x66, 0x7E, 0x7E, + 0x66, 0xCC, 0xCC, 0xCC, 0xCC, 0x00, 0x00, 0x00, + 0x00, 0x3E, 0x3F, 0x33, 0x63, 0x63, 0x7E, 0x7C, + 0x66, 0xC6, 0xC6, 0xFE, 0xFC, 0x00, 0x00, 0x00, + 0x00, 0x1E, 0x3F, 0x33, 0x30, 0x60, 0x60, 0x60, + 0x60, 0xC0, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x3E, 0x3F, 0x33, 0x63, 0x63, 0x63, 0x63, + 0xC3, 0xC6, 0xCE, 0xFC, 0xF8, 0x00, 0x00, 0x00, + 0x00, 0x3F, 0x3F, 0x30, 0x30, 0x60, 0x7C, 0x7C, + 0x60, 0xC0, 0xC0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x3F, 0x3F, 0x30, 0x30, 0x60, 0x7C, 0x7C, + 0x60, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, + 0x00, 0x1E, 0x3F, 0x33, 0x30, 0x60, 0x60, 0x6E, + 0x6E, 0xC6, 0xCE, 0xFC, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x33, 0x33, 0x33, 0x63, 0x66, 0x7E, 0x7E, + 0xC6, 0xC6, 0xCC, 0xCC, 0xCC, 0x00, 0x00, 0x00, + 0x00, 0x3F, 0x3F, 0x0C, 0x0C, 0x18, 0x18, 0x18, + 0x18, 0x30, 0x30, 0xFC, 0xFC, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x03, 0x03, 0x03, 0x06, 0x06, 0x06, + 0x06, 0x0C, 0xCC, 0xFC, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x30, 0x33, 0x36, 0x7C, 0x78, 0x70, + 0x78, 0xF8, 0xDC, 0xCE, 0xC6, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x30, 0x30, 0x30, 0x60, 0x60, 0x60, + 0x60, 0xC0, 0xC0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x33, 0x33, 0x3F, 0x3F, 0x7F, 0x6B, 0x66, + 0x66, 0xC6, 0xCC, 0xCC, 0xCC, 0x00, 0x00, 0x00, + 0x00, 0x33, 0x33, 0x3B, 0x3B, 0x7B, 0x7E, 0x6E, + 0x6E, 0xCE, 0xCC, 0xCC, 0xCC, 0x00, 0x00, 0x00, + 0x00, 0x1E, 0x3F, 0x33, 0x33, 0x63, 0x66, 0x66, + 0xC6, 0xCC, 0xCC, 0xFC, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x3E, 0x3F, 0x33, 0x33, 0x67, 0x7E, 0x7C, + 0x60, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, + 0x00, 0x1E, 0x3F, 0x33, 0x33, 0x63, 0x66, 0x66, + 0xC6, 0xF6, 0xDC, 0xF8, 0x7C, 0x0C, 0x00, 0x00, + 0x00, 0x3E, 0x3F, 0x33, 0x33, 0x63, 0x7E, 0x7C, + 0x6E, 0xC6, 0xC6, 0xCC, 0xCC, 0x00, 0x00, 0x00, + 0x00, 0x1E, 0x3F, 0x33, 0x60, 0x60, 0x7C, 0x3E, + 0x06, 0x06, 0xCE, 0xFC, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x7F, 0x7F, 0x18, 0x18, 0x30, 0x30, 0x30, + 0x30, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, + 0x00, 0x33, 0x33, 0x33, 0x33, 0x63, 0x66, 0x66, + 0x66, 0xC6, 0xCC, 0xFC, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x33, 0x33, 0x33, 0x33, 0x63, 0x63, 0x66, + 0x66, 0x6C, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x33, 0x33, 0x33, 0x33, 0x63, 0x63, 0x6B, + 0x6B, 0xFE, 0xFE, 0xEE, 0x44, 0x00, 0x00, 0x00, + 0x00, 0x63, 0x63, 0x63, 0x77, 0x3E, 0x1C, 0x38, + 0x7C, 0xEE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, + 0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x3C, 0x18, + 0x18, 0x30, 0x30, 0x60, 0x60, 0x00, 0x00, 0x00, + 0x00, 0x7F, 0x7F, 0x03, 0x07, 0x0E, 0x0C, 0x18, + 0x38, 0x70, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x0F, 0x0F, 0x0C, 0x0C, 0x18, 0x18, 0x18, + 0x18, 0x30, 0x30, 0x3E, 0x3E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE0, 0x70, + 0x38, 0x1C, 0x0E, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1F, 0x1F, 0x03, 0x03, 0x06, 0x06, 0x06, + 0x06, 0x0C, 0x0C, 0x7C, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x0E, 0x1F, 0x3B, 0x63, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x00, + 0x00, 0x00, 0x00, 0x0C, 0x0E, 0x0C, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x3E, 0x06, + 0x7E, 0xFC, 0xCC, 0xFC, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x18, 0x30, 0x30, 0x3E, 0x7F, 0x63, + 0x63, 0xC6, 0xC6, 0xFE, 0xFC, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x7E, 0x66, + 0xC0, 0xC0, 0xCC, 0xFC, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x03, 0x03, 0x06, 0x3E, 0x7E, 0x66, + 0xC6, 0xCC, 0xCC, 0xFC, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x7E, 0x66, + 0xFE, 0xFC, 0xC0, 0xFC, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x07, 0x0F, 0x0C, 0x18, 0x7E, 0x7E, 0x30, + 0x30, 0x30, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x7F, 0x63, + 0x63, 0xC6, 0xC6, 0xFE, 0x7E, 0x0C, 0xFC, 0xF8, + 0x00, 0x00, 0x30, 0x30, 0x30, 0x6E, 0x7F, 0x73, + 0x63, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x06, 0x06, 0x00, 0x1C, 0x3C, 0x0C, + 0x0C, 0x18, 0x18, 0x7C, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0x03, 0x00, 0x0E, 0x1E, 0x06, + 0x06, 0x0C, 0x0C, 0x0C, 0x0C, 0x18, 0xF8, 0xF0, + 0x00, 0x30, 0x30, 0x30, 0x33, 0x67, 0x6E, 0x7C, + 0x7C, 0xDC, 0xCE, 0xC6, 0xC6, 0x00, 0x00, 0x00, + 0x00, 0x0E, 0x0E, 0x06, 0x06, 0x0C, 0x0C, 0x0C, + 0x0C, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x7F, 0x7F, + 0x6B, 0xD6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x7E, 0x76, + 0x66, 0xCC, 0xCC, 0xCC, 0xCC, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x7E, 0x66, + 0x66, 0xCC, 0xCC, 0xFC, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x3F, 0x33, + 0x63, 0x66, 0x66, 0xFE, 0xFC, 0xC0, 0xC0, 0xC0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x7F, 0x63, + 0x63, 0xC6, 0xC6, 0xFE, 0x7C, 0x0C, 0x0E, 0x0E, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x6F, 0x7F, 0x70, + 0x60, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x7F, 0x60, + 0x7C, 0x3E, 0x06, 0xFE, 0xFC, 0x00, 0x00, 0x00, + 0x00, 0x06, 0x06, 0x0C, 0x0C, 0x3F, 0x3F, 0x18, + 0x18, 0x30, 0x30, 0x3E, 0x1C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0x66, + 0x66, 0x66, 0xCC, 0xFE, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, + 0xCC, 0xCC, 0xF8, 0x70, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x63, 0x63, + 0x6B, 0xDE, 0xFE, 0xFE, 0x6C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x63, 0x77, + 0x3E, 0x7C, 0xEE, 0xC6, 0xC6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x63, 0x63, + 0x63, 0xC6, 0xC6, 0xFE, 0x7E, 0x0C, 0xFC, 0xF8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x7F, 0x07, + 0x1E, 0x78, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x07, 0x0E, 0x0C, 0x0C, 0x18, 0x70, 0x70, + 0x18, 0x18, 0x30, 0x38, 0x1C, 0x00, 0x00, 0x00, + 0x06, 0x06, 0x06, 0x06, 0x0C, 0x0C, 0x0C, 0x0C, + 0x18, 0x18, 0x18, 0x18, 0x30, 0x30, 0x30, 0x00, + 0x00, 0x38, 0x1C, 0x0C, 0x18, 0x18, 0x0E, 0x0E, + 0x18, 0x30, 0x30, 0x70, 0xE0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1D, 0x3F, 0x37, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0xEE, 0x28, 0x4C, 0x48, 0x48, 0x00, 0xFE, + 0x00, 0x06, 0x0F, 0x1B, 0x18, 0x7E, 0x30, 0x7C, + 0x60, 0x60, 0x6C, 0x3C, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x38, 0x6C, 0x54, 0xF6, 0xEE, + 0x6C, 0x7C, 0x28, 0x38, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0x10, 0x20, 0x00, + 0x00, 0x07, 0x0F, 0x0C, 0x18, 0x7E, 0x7E, 0x30, + 0x30, 0x30, 0x60, 0x60, 0x60, 0xC0, 0x80, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x66, 0x66, 0x44, 0x88, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xDB, 0xDB, 0x00, 0x00, 0x00, + 0x00, 0x06, 0x06, 0x06, 0x1F, 0x3F, 0x0C, 0x0C, + 0x0C, 0x18, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, + 0x00, 0x06, 0x06, 0x06, 0x1F, 0x3F, 0x0C, 0x3F, + 0x3F, 0x18, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, + 0x00, 0x3E, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x63, 0x06, + 0x0C, 0x30, 0x60, 0xDB, 0x9B, 0x00, 0x00, 0x00, + 0x63, 0x3E, 0x00, 0x1E, 0x3F, 0x33, 0x60, 0x7C, + 0x3E, 0x06, 0xCE, 0xFC, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0E, + 0x1C, 0x30, 0x38, 0x1C, 0x0C, 0x00, 0x00, 0x00, + 0x00, 0x1F, 0x3F, 0x33, 0x33, 0x66, 0x67, 0x67, + 0x66, 0xCC, 0xCC, 0xFF, 0x7F, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x38, 0x6C, 0x54, 0xF6, 0xEE, + 0x6C, 0x7C, 0x28, 0x38, 0x10, 0x00, 0x00, 0x00, + 0x63, 0x3E, 0x00, 0x7F, 0x7F, 0x03, 0x07, 0x0E, + 0x18, 0x70, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x38, 0x6C, 0x54, 0xF6, 0xEE, + 0x6C, 0x7C, 0x28, 0x38, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x38, 0x6C, 0x54, 0xF6, 0xEE, + 0x6C, 0x7C, 0x28, 0x38, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x08, 0x10, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0C, 0x04, 0x08, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x09, 0x12, 0x1B, 0x36, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1B, 0x1B, 0x09, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x3F, + 0x3F, 0x7E, 0x7E, 0x3C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x19, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFB, 0xFF, 0x55, 0xA2, 0xA2, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x63, 0x36, 0x1C, 0x00, 0x3F, 0x7F, 0x60, + 0x7C, 0x3E, 0x06, 0xFE, 0xFC, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1C, + 0x0E, 0x0C, 0x1C, 0x38, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x7F, 0x6D, + 0x6F, 0xDE, 0xD8, 0xFE, 0x6E, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x38, 0x6C, 0x54, 0xF6, 0xEE, + 0x6C, 0x7C, 0x28, 0x38, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x63, 0x36, 0x1C, 0x00, 0x7F, 0x7F, 0x07, + 0x1E, 0x78, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x33, 0x00, 0x66, 0x66, 0x66, 0x3C, 0x3C, + 0x18, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00, + 0x0C, 0x18, 0x18, 0x18, 0x18, 0x30, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x04, 0x3E, 0x7F, 0x6B, + 0x68, 0xD0, 0xD6, 0xFE, 0x7C, 0x20, 0x20, 0x00, + 0x00, 0x0F, 0x1F, 0x19, 0x18, 0x30, 0x7C, 0x7C, + 0x30, 0x60, 0xE6, 0xFE, 0xDC, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x19, 0x33, 0x1E, 0x3F, + 0x33, 0x66, 0x7E, 0x3C, 0x66, 0xCC, 0x00, 0x00, + 0x00, 0x00, 0x19, 0x19, 0x19, 0x1E, 0x0C, 0x3F, + 0x0C, 0x7E, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x06, 0x0C, 0x0C, 0x00, + 0x00, 0x18, 0x18, 0x30, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x07, 0x0E, 0x18, 0x18, 0x3C, 0x7E, 0x66, + 0x7E, 0x3C, 0x18, 0x18, 0x70, 0xE0, 0x00, 0x00, + 0x00, 0x00, 0x33, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0E, 0x1F, 0x21, 0x21, 0x4D, 0x51, 0x51, + 0x91, 0xA1, 0x9A, 0x82, 0x7C, 0x38, 0x00, 0x00, + 0x00, 0x1C, 0x02, 0x1E, 0x22, 0x3C, 0x00, 0x7C, + 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, + 0x36, 0xD8, 0xD8, 0x6C, 0x36, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1E, 0x3E, 0x06, 0x0C, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0E, 0x1F, 0x21, 0x49, 0x55, 0x55, 0x59, + 0x99, 0xA5, 0xA5, 0x82, 0x7E, 0x78, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1E, 0x3F, 0x33, 0x3F, 0x3C, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x06, 0x3F, 0x3F, 0x0C, + 0x0C, 0x00, 0x7E, 0x7E, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3C, 0x3E, 0x06, 0x3C, 0x78, 0x60, + 0x7C, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3C, 0x3E, 0x06, 0x18, 0x0C, 0x7C, + 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x0C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33, + 0x33, 0x66, 0x66, 0x7E, 0x7C, 0xC0, 0xC0, 0x80, + 0x00, 0x00, 0x00, 0x3F, 0x6F, 0xDB, 0xDB, 0x7B, + 0x1B, 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, + 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x1C, 0x0C, 0x1C, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x38, 0x18, 0x30, 0x30, 0x78, + 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0C, 0x1E, 0x22, 0x3C, 0x18, 0x00, 0x3C, + 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6C, + 0x36, 0x36, 0x36, 0x6C, 0xD8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x30, 0x10, 0x23, 0x76, 0x0C, + 0x18, 0x64, 0xCC, 0x94, 0x3E, 0x08, 0x08, 0x00, + 0x00, 0x00, 0x10, 0x30, 0x10, 0x23, 0x76, 0x0C, + 0x18, 0x60, 0xDC, 0x82, 0x1C, 0x20, 0x3C, 0x00, + 0x00, 0x00, 0x38, 0x04, 0x18, 0x0B, 0x76, 0x0C, + 0x18, 0x64, 0xCC, 0x96, 0x3E, 0x08, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x0C, 0x0C, + 0x3C, 0x70, 0xC0, 0xC6, 0xC6, 0xFC, 0x78, 0x00, + 0x00, 0x18, 0x0C, 0x00, 0x04, 0x1C, 0x36, 0x63, + 0x7F, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x06, 0x00, 0x04, 0x1C, 0x36, 0x63, + 0x7F, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, + 0x00, 0x0E, 0x1B, 0x11, 0x04, 0x1C, 0x36, 0x63, + 0x7F, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, + 0x00, 0x1D, 0x37, 0x00, 0x04, 0x1C, 0x36, 0x63, + 0x7F, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, + 0x00, 0x1B, 0x1B, 0x04, 0x0E, 0x36, 0x63, 0x7F, + 0x7F, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, + 0x00, 0x0E, 0x11, 0x0E, 0x0E, 0x36, 0x63, 0x7F, + 0x7F, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, + 0x00, 0x07, 0x0F, 0x1F, 0x3B, 0x66, 0x7F, 0x7F, + 0x66, 0xCC, 0xCC, 0xCF, 0xCF, 0x00, 0x00, 0x00, + 0x00, 0x1E, 0x3F, 0x33, 0x30, 0x60, 0x60, 0x60, + 0x60, 0xC0, 0xC6, 0xFE, 0x7C, 0x1C, 0xCC, 0x78, + 0x00, 0x0C, 0x06, 0x00, 0x3F, 0x7F, 0x60, 0x78, + 0x78, 0xC0, 0xC0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x06, 0x00, 0x3F, 0x7F, 0x60, 0x78, + 0x78, 0xC0, 0xC0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x0E, 0x1B, 0x00, 0x3F, 0x7F, 0x60, 0x78, + 0x78, 0xC0, 0xC0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x1B, 0x1B, 0x00, 0x3F, 0x3F, 0x60, 0x60, 0x78, + 0x78, 0xC0, 0xC0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x0C, 0x06, 0x00, 0x1F, 0x1F, 0x0C, 0x0C, + 0x0C, 0x18, 0x18, 0x7C, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x06, 0x00, 0x1F, 0x1F, 0x0C, 0x0C, + 0x0C, 0x18, 0x18, 0x7C, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x06, 0x09, 0x1F, 0x1F, 0x0C, 0x0C, 0x0C, + 0x0C, 0x18, 0x18, 0x7C, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x1B, 0x1B, 0x00, 0x1F, 0x1F, 0x0C, 0x0C, + 0x0C, 0x18, 0x18, 0x7C, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1E, 0x1F, 0x1B, 0x33, 0x33, 0x7B, + 0x33, 0x66, 0x6E, 0x7C, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x1D, 0x37, 0x00, 0x31, 0x63, 0x73, 0x7B, + 0x7F, 0xDE, 0xCE, 0xC6, 0xC6, 0x00, 0x00, 0x00, + 0x00, 0x0C, 0x06, 0x00, 0x3E, 0x7F, 0x63, 0x63, + 0x63, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x06, 0x00, 0x3E, 0x7F, 0x63, 0x63, + 0x63, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x0E, 0x1B, 0x00, 0x3E, 0x7F, 0x63, 0x63, + 0x63, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x1D, 0x37, 0x00, 0x3E, 0x7F, 0x63, 0x63, + 0x63, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x1B, 0x1B, 0x00, 0x3E, 0x7F, 0x63, 0x63, + 0x63, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x77, 0x3E, + 0x1C, 0x38, 0x7C, 0xEE, 0xC6, 0x00, 0x00, 0x00, + 0x00, 0x1D, 0x3E, 0x37, 0x6B, 0x6B, 0x6B, 0xD6, + 0xD6, 0xD6, 0xEE, 0x7C, 0xB8, 0x00, 0x00, 0x00, + 0x00, 0x0C, 0x06, 0x00, 0x33, 0x33, 0x63, 0x66, + 0x66, 0xC6, 0xCE, 0xFC, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x06, 0x00, 0x33, 0x33, 0x63, 0x66, + 0x66, 0xC6, 0xCE, 0xFC, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x0E, 0x1B, 0x00, 0x33, 0x33, 0x63, 0x66, + 0x66, 0xC6, 0xCE, 0xFC, 0x78, 0x00, 0x00, 0x00, + 0x1B, 0x1B, 0x00, 0x33, 0x33, 0x63, 0x63, 0x63, + 0x66, 0xC6, 0xCE, 0xFC, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x06, 0x0C, 0x00, 0x33, 0x33, 0x66, 0x6E, + 0x7C, 0x38, 0x30, 0x60, 0x60, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x1F, 0x3F, 0x33, 0x33, + 0x3F, 0x7C, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, + 0x00, 0x0E, 0x1F, 0x1B, 0x1B, 0x33, 0x3F, 0x3E, + 0x33, 0x66, 0x66, 0x7E, 0x7C, 0xC0, 0x80, 0x00, + 0x00, 0x00, 0x0C, 0x06, 0x00, 0x3F, 0x7F, 0x63, + 0x63, 0xCE, 0xCE, 0xFE, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x06, 0x0C, 0x00, 0x3F, 0x7F, 0x63, + 0x63, 0xC6, 0xCE, 0xFE, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x0E, 0x1B, 0x00, 0x3F, 0x7F, 0x63, + 0x63, 0xC6, 0xCE, 0xFE, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1D, 0x37, 0x00, 0x3F, 0x7F, 0x63, + 0x63, 0xC6, 0xCE, 0xFE, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1B, 0x1B, 0x00, 0x3F, 0x7F, 0x63, + 0x63, 0xC6, 0xCE, 0xFE, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x0E, 0x1B, 0x0E, 0x00, 0x3E, 0x7F, 0x63, + 0x63, 0xC6, 0xCE, 0xFE, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x3F, 0x0D, + 0x1F, 0x7E, 0xD8, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x7F, + 0x63, 0xC0, 0xC6, 0xFE, 0x7C, 0x30, 0xF8, 0xF0, + 0x00, 0x00, 0x0C, 0x06, 0x00, 0x3E, 0x7F, 0x63, + 0x7F, 0xFE, 0xC0, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x06, 0x0C, 0x00, 0x3E, 0x7F, 0x63, + 0x7F, 0xFE, 0xC0, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x0E, 0x1B, 0x00, 0x3E, 0x7F, 0x63, + 0x7F, 0xFE, 0xC0, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1B, 0x1B, 0x00, 0x3E, 0x7F, 0x63, + 0x7F, 0xFE, 0xC0, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0C, 0x06, 0x00, 0x0C, 0x0C, 0x0C, + 0x0C, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0x06, 0x00, 0x0C, 0x0C, 0x0C, + 0x0C, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x06, 0x0F, 0x19, 0x00, 0x0C, 0x0C, 0x0C, + 0x0C, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1B, 0x1B, 0x00, 0x0C, 0x0C, 0x0C, + 0x0C, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x1B, 0x1F, 0x3E, 0x37, 0x3E, 0x7F, 0x63, + 0x63, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x1D, 0x3F, 0x37, 0x00, 0x7E, 0x7F, 0x63, + 0x63, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x0C, 0x00, 0x3E, 0x7F, 0x63, + 0x63, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x06, 0x0C, 0x00, 0x3E, 0x7F, 0x63, + 0x63, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x0E, 0x1B, 0x00, 0x3E, 0x7F, 0x63, + 0x63, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x1D, 0x3F, 0x37, 0x00, 0x3E, 0x7F, 0x63, + 0x63, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1B, 0x1B, 0x00, 0x3E, 0x7F, 0x63, + 0x63, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00, 0x3F, + 0x7E, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x7F, 0x67, + 0x6B, 0xD6, 0xE6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x0C, 0x00, 0x63, 0x63, 0x63, + 0x63, 0xC6, 0xC6, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x06, 0x0C, 0x00, 0x63, 0x63, 0x63, + 0x63, 0xC6, 0xC6, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x0E, 0x1B, 0x00, 0x63, 0x63, 0x63, + 0x63, 0xC6, 0xC6, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1B, 0x1B, 0x00, 0x63, 0x63, 0x63, + 0x63, 0xC6, 0xC6, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0x06, 0x00, 0x63, 0x63, 0x63, + 0x63, 0xC6, 0xC6, 0xFE, 0x7E, 0x0C, 0xF8, 0xF0, + 0x00, 0x00, 0x18, 0x18, 0x18, 0x3E, 0x3F, 0x33, + 0x33, 0x66, 0x66, 0x7E, 0x7C, 0xC0, 0xC0, 0xC0, + 0x00, 0x00, 0x00, 0x1B, 0x00, 0x63, 0x63, 0x63, + 0x63, 0xC6, 0xC6, 0xFE, 0x7E, 0x0C, 0xF8, 0xF0, +}; + +const struct fb_font_desc font_italic = { + .name = "NetSurf Italic", + .width = 8, + .height = 16, + .encoding = "CP1252", + .data = fontdata_italic, +}; + + +static const uint32_t fontdata_italic_bold[FONTDATAMAX] = { + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0xE4, 0xAC, 0xA4, 0xA4, 0xEE, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0xEC, 0xA2, 0xA4, 0xA8, 0xEE, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0xEC, 0xA2, 0xAC, 0xA2, 0xEC, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0xEA, 0xAA, 0xAE, 0xA2, 0xE2, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0xEE, 0xA8, 0xAE, 0xA2, 0xEE, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0xE6, 0xA8, 0xAE, 0xAA, 0xEE, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0xEE, 0xA2, 0xA4, 0xA4, 0xE4, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0xEE, 0xAA, 0xAE, 0xAA, 0xEE, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0xEE, 0xAA, 0xAE, 0xA2, 0xE2, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0xE4, 0xAA, 0xAE, 0xAA, 0xEA, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0xEC, 0xAA, 0xAC, 0xAA, 0xEC, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0xE4, 0xAA, 0xA8, 0xAA, 0xE4, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0xEC, 0xAA, 0xAA, 0xAA, 0xEC, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0xEE, 0xA8, 0xAC, 0xA8, 0xEE, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0xEE, 0xA8, 0xAC, 0xA8, 0xE8, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0x4E, 0xCA, 0x4A, 0x4A, 0xEE, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0x44, 0xCC, 0x44, 0x44, 0xEE, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0x4C, 0xC2, 0x44, 0x48, 0xEE, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0x4C, 0xC2, 0x4C, 0x42, 0xEC, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0x4A, 0xCA, 0x4E, 0x42, 0xE2, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0x4E, 0xC8, 0x4E, 0x42, 0xEE, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0x46, 0xC8, 0x4E, 0x4A, 0xEE, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0x4E, 0xC2, 0x44, 0x44, 0xE4, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0x4E, 0xCA, 0x4E, 0x4A, 0xEE, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0x4E, 0xCA, 0x4E, 0x42, 0xE2, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0x44, 0xCA, 0x4E, 0x4A, 0xEA, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0x4C, 0xCA, 0x4C, 0x4A, 0xEC, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0x44, 0xCA, 0x48, 0x4A, 0xE4, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0x4C, 0xCA, 0x4A, 0x4A, 0xEC, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0x4E, 0xC8, 0x4C, 0x48, 0xEE, 0x00, 0xFE, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0x4E, 0xC8, 0x4C, 0x48, 0xE8, 0x00, 0xFE, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0E, 0x0E, 0x0E, 0x0E, 0x1C, 0x1C, 0x1C, + 0x1C, 0x00, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x36, 0x36, 0x7F, 0x7F, 0x7F, 0x36, 0x6C, + 0xFE, 0xFE, 0xFE, 0x6C, 0x6C, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x3E, 0x7F, 0x7B, 0x78, 0x7C, 0x7C, + 0x3E, 0x1E, 0xDE, 0xFE, 0x7C, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x70, 0x73, 0x77, 0x0E, + 0x3C, 0x70, 0xEE, 0xCE, 0x0E, 0x00, 0x00, 0x00, + 0x00, 0x1C, 0x3E, 0x7E, 0x7C, 0x7C, 0x3B, 0xFE, + 0xFE, 0xEC, 0xEE, 0xFE, 0x74, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1C, 0x1C, 0x1C, 0x1C, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x06, 0x0E, 0x1C, 0x1C, 0x38, 0x38, 0x70, + 0x70, 0x70, 0x38, 0x38, 0x1C, 0x0C, 0x06, 0x00, + 0x60, 0x30, 0x38, 0x1C, 0x1C, 0x0E, 0x0E, 0x0E, + 0x1C, 0x1C, 0x38, 0x38, 0x70, 0x60, 0xC0, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x2A, 0x7F, 0x3E, 0x18, + 0x7C, 0xFE, 0x54, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x1C, 0x7E, + 0x7E, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x38, 0x78, 0x70, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, + 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0F, 0x3C, + 0x78, 0xF0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1C, 0x3E, 0x77, 0x77, 0x77, 0x77, 0xEE, + 0xEE, 0xEE, 0xEE, 0x7C, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x0C, 0x1C, 0x3C, 0x3C, 0x1C, 0x1C, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x3E, 0x7F, 0x77, 0x07, 0x07, 0x3E, 0x7C, + 0xE0, 0xE0, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x3E, 0x7F, 0x77, 0x07, 0x07, 0x1E, 0x3C, + 0x0E, 0x0E, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x06, 0x0E, 0x1E, 0x3E, 0x76, 0xEC, + 0xFE, 0xFE, 0x1C, 0x1C, 0x1C, 0x00, 0x00, 0x00, + 0x00, 0x7F, 0x7F, 0x70, 0x70, 0x7C, 0x7E, 0x0E, + 0x0E, 0x0E, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x3E, 0x7E, 0x70, 0x70, 0x7C, 0x7E, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x7F, 0x7F, 0x07, 0x07, 0x0E, 0x0E, 0x1C, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x3E, 0x7F, 0x77, 0x77, 0x7F, 0x3E, 0x7E, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x3E, 0x7F, 0x77, 0x77, 0x77, 0x7F, 0x3E, + 0x0E, 0x0E, 0x0E, 0x7C, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x1C, 0x00, + 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x1C, 0x00, + 0x00, 0x18, 0x38, 0x38, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x07, 0x0E, 0x1C, 0x70, + 0x70, 0x38, 0x1C, 0x0E, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x7F, 0x00, + 0x00, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x30, 0x38, 0x1C, 0x0E, 0x0E, + 0x0E, 0x1C, 0x38, 0x70, 0x60, 0x00, 0x00, 0x00, + 0x00, 0x3E, 0x7F, 0x77, 0x07, 0x07, 0x1E, 0x7C, + 0x70, 0x00, 0x70, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3E, 0x7F, 0x77, 0x77, 0x77, 0x7F, 0xFE, + 0xEC, 0xE0, 0xE0, 0xFC, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x3E, 0x7F, 0x77, 0x77, 0x77, 0x76, 0xFE, + 0xFE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0x7E, 0x7F, 0x77, 0x77, 0x77, 0x7E, 0xFC, + 0xEE, 0xEE, 0xEE, 0xFE, 0xFC, 0x00, 0x00, 0x00, + 0x00, 0x3E, 0x7F, 0x77, 0x77, 0x70, 0x70, 0xE0, + 0xE0, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0x7E, 0x77, 0x77, 0x77, 0x76, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFC, 0xF8, 0x00, 0x00, 0x00, + 0x00, 0x7F, 0x7F, 0x70, 0x70, 0x70, 0x7C, 0xF8, + 0xE0, 0xE0, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x7F, 0x7F, 0x70, 0x70, 0x70, 0x7C, 0xF8, + 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0x00, 0x00, 0x00, + 0x00, 0x3E, 0x7F, 0x77, 0x77, 0x70, 0x70, 0xFE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x7E, 0xFE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0x7F, 0x7F, 0x1C, 0x1C, 0x1C, 0x1C, 0x38, + 0x38, 0x38, 0x38, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x0E, + 0x0E, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x70, 0x70, 0x72, 0x77, 0x7F, 0x7E, 0xF8, + 0xF8, 0xFC, 0xFE, 0xEE, 0xE6, 0x00, 0x00, 0x00, + 0x00, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0xE0, + 0xE0, 0xE0, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x63, 0x77, 0x7F, 0x7F, 0x7F, 0x7E, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0x67, 0x77, 0x77, 0x7F, 0x7F, 0x7E, 0xFE, + 0xFE, 0xFE, 0xEE, 0xEE, 0xE6, 0x00, 0x00, 0x00, + 0x00, 0x3E, 0x7F, 0x77, 0x77, 0x77, 0x76, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x7E, 0x7F, 0x77, 0x77, 0x77, 0x77, 0xFE, + 0xFC, 0xE0, 0xE0, 0xE0, 0xE0, 0x00, 0x00, 0x00, + 0x00, 0x3E, 0x7F, 0x77, 0x77, 0x77, 0x76, 0xEE, + 0xEE, 0xFE, 0xFE, 0xFE, 0x7E, 0x06, 0x00, 0x00, + 0x00, 0x7E, 0x7F, 0x77, 0x77, 0x77, 0x7E, 0xFC, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0x3E, 0x7F, 0x77, 0x70, 0x70, 0x7C, 0x3E, + 0x0E, 0x0E, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x7F, 0x7F, 0x1C, 0x1C, 0x1C, 0x1C, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x76, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x76, 0xEE, + 0x6C, 0x7C, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x76, 0xEE, + 0xFE, 0xFE, 0xFE, 0xEE, 0x44, 0x00, 0x00, 0x00, + 0x00, 0x77, 0x77, 0x77, 0x77, 0x3E, 0x1C, 0x38, + 0x7C, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x3E, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x7F, 0x7F, 0x07, 0x07, 0x0E, 0x1C, 0x38, + 0x70, 0xE0, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x1F, 0x1F, 0x1C, 0x1C, 0x1C, 0x1C, 0x38, + 0x38, 0x38, 0x38, 0x3E, 0x3E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x70, 0x78, 0x38, + 0x1C, 0x1E, 0x0E, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7E, 0x7E, 0x0E, 0x0E, 0x0E, 0x0E, 0x1C, + 0x1C, 0x1C, 0x1C, 0xFC, 0xFC, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x1C, 0x3E, 0x77, 0x63, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x1C, 0x0C, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x3E, 0x0E, + 0x3E, 0x7E, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x38, 0x38, 0x70, 0x7C, 0x7E, 0x6E, + 0xEE, 0xEE, 0xEE, 0xFC, 0xF8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x7E, 0xEE, + 0xE0, 0xE0, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x07, 0x07, 0x07, 0x07, 0x3F, 0x7E, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x7E, 0xEE, + 0xFE, 0xFC, 0xE0, 0xFC, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x1F, 0x3F, 0x38, 0x38, 0x70, 0x7C, 0x7C, + 0x70, 0xE0, 0xE0, 0xE0, 0xE0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x7E, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x1C, 0xFC, 0xF8, + 0x00, 0x00, 0x70, 0x70, 0x70, 0x7C, 0x7E, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0E, 0x0E, 0x00, 0x1E, 0x3E, 0x1C, + 0x1C, 0x38, 0x38, 0x7C, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0E, 0x0E, 0x00, 0x1E, 0x3E, 0x0E, + 0x1C, 0x1C, 0x1C, 0x1C, 0x38, 0x38, 0xF8, 0xF0, + 0x00, 0x38, 0x38, 0x38, 0x3A, 0x7F, 0x7E, 0x7C, + 0x70, 0xF8, 0xFC, 0xEE, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0x3C, 0x3C, 0x1C, 0x1C, 0x38, 0x38, 0x38, + 0x38, 0x70, 0x70, 0x70, 0x70, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x7E, 0xFE, + 0xFE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x7E, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x7E, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFC, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x7E, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFC, 0xF8, 0xE0, 0xE0, 0xE0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x7E, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFC, 0x7C, 0x1C, 0x1E, 0x1E, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x7E, 0x70, + 0x70, 0xE0, 0xE0, 0xE0, 0xE0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x3E, 0x70, + 0x7C, 0x3E, 0x0E, 0x7C, 0xF8, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x38, 0x38, 0x70, 0x7C, 0x7C, 0x70, + 0xE0, 0xE0, 0xE0, 0xFC, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x76, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x76, 0xEE, + 0xEE, 0xEE, 0x7C, 0x38, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x76, 0xEE, + 0xFE, 0xFE, 0xFE, 0xEE, 0x44, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x76, 0x7E, + 0x38, 0x7C, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x76, 0xEE, + 0xEE, 0xEE, 0xFE, 0x7E, 0x1C, 0x1C, 0xFC, 0xF8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x7E, 0x1E, + 0x3C, 0x78, 0xF0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x0F, 0x1F, 0x1C, 0x1C, 0x1C, 0x78, 0xF0, + 0x38, 0x38, 0x38, 0x3E, 0x1E, 0x00, 0x00, 0x00, + 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, + 0x00, 0x78, 0x7C, 0x1C, 0x1C, 0x1C, 0x0F, 0x1E, + 0x38, 0x38, 0x38, 0xF8, 0xF0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x33, 0x7F, 0x7F, 0x66, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7F, 0x00, 0x77, 0x55, 0x55, 0x55, 0x77, + 0x00, 0xEE, 0x28, 0x4C, 0x48, 0x48, 0x00, 0xFE, + 0x00, 0x06, 0x1F, 0x3B, 0x70, 0xFE, 0x70, 0xF8, + 0xE0, 0xE0, 0xEE, 0xFC, 0x70, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x38, 0x6C, 0x54, 0xF6, 0xEE, + 0x6C, 0x7C, 0x28, 0x38, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x38, 0x38, 0x30, 0x60, 0x00, + 0x00, 0x1F, 0x3F, 0x38, 0x38, 0x70, 0x7C, 0x7C, + 0x70, 0xE0, 0xE0, 0xE0, 0xE0, 0xC0, 0xC0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xEE, 0xEE, 0xCC, 0x98, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xDB, 0xDB, 0xDB, 0x00, 0x00, 0x00, + 0x00, 0x1C, 0x1C, 0x1C, 0x1C, 0x7F, 0x7F, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, + 0x00, 0x1C, 0x1C, 0x1C, 0x7F, 0x7F, 0x1C, 0xFE, + 0xFE, 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, + 0x00, 0x3E, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x67, 0x1C, + 0x38, 0x70, 0xE0, 0xDB, 0x1B, 0x00, 0x00, 0x00, + 0x77, 0x3E, 0x00, 0x3E, 0x7F, 0x77, 0x70, 0x7C, + 0x3E, 0x0E, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x1C, + 0x38, 0x70, 0x38, 0x1C, 0x0E, 0x06, 0x00, 0x00, + 0x00, 0x3F, 0x7F, 0x77, 0x77, 0x77, 0x77, 0xEF, + 0xEE, 0xEE, 0xEE, 0xFF, 0x7F, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x38, 0x6C, 0x54, 0xF6, 0xEE, + 0x6C, 0x7C, 0x28, 0x38, 0x10, 0x00, 0x00, 0x00, + 0x77, 0x3E, 0x00, 0x7F, 0x7F, 0x07, 0x0E, 0x1C, + 0x38, 0x70, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x38, 0x6C, 0x54, 0xF6, 0xEE, + 0x6C, 0x7C, 0x28, 0x38, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x38, 0x6C, 0x54, 0xF6, 0xEE, + 0x6C, 0x7C, 0x28, 0x38, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0C, 0x18, 0x18, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1B, 0x36, 0x36, 0x36, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1B, 0x1B, 0x1B, 0x36, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x7E, + 0x7E, 0x7E, 0x7E, 0x3C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3B, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x79, 0x7F, 0x2F, 0x29, 0x29, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x77, 0x3E, 0x1C, 0x00, 0x1F, 0x3E, 0x70, + 0x7C, 0x3E, 0x0E, 0x7C, 0xF8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x38, 0x38, + 0x1C, 0x0E, 0x1C, 0x38, 0x70, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x7F, 0xFA, + 0xDE, 0xDE, 0xFC, 0xFE, 0x6E, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x38, 0x6C, 0x54, 0xF6, 0xEE, + 0x6C, 0x7C, 0x28, 0x38, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x77, 0x3E, 0x1C, 0x00, 0x7F, 0x7E, 0x1E, + 0x3C, 0x78, 0xF0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x3B, 0x00, 0x77, 0x77, 0x77, 0x77, 0x3E, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x1C, 0x00, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x08, 0x3E, 0x7F, 0xD6, + 0xD0, 0xD0, 0xD6, 0xFE, 0x7C, 0x10, 0x10, 0x00, + 0x00, 0x1E, 0x3F, 0x3B, 0x38, 0x7E, 0x7E, 0xFC, + 0x70, 0x76, 0xFE, 0xFE, 0xDC, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x3E, 0xFE, + 0xFE, 0xFE, 0xFE, 0x7C, 0xEE, 0xEE, 0x00, 0x00, + 0x00, 0x00, 0x77, 0x77, 0x77, 0x3E, 0x1C, 0xFE, + 0x38, 0xFE, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1C, 0x1C, 0x1C, 0x1C, 0x00, + 0x00, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x1E, 0x3E, 0x3E, 0x38, 0x1E, 0x3F, 0x66, + 0x7E, 0x3C, 0x0E, 0x3E, 0x3E, 0x3C, 0x00, 0x00, + 0x00, 0x77, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1E, 0x3F, 0x61, 0x4D, 0x5D, 0x51, 0xA1, + 0xA5, 0xBD, 0x99, 0xC3, 0x7E, 0x3C, 0x00, 0x00, + 0x00, 0x3C, 0x06, 0x3E, 0x66, 0x3E, 0x00, 0xFC, + 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, + 0x7C, 0xF8, 0xF8, 0x7C, 0x3E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3F, 0x3F, 0x3F, 0x03, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7E, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1E, 0x3F, 0x61, 0x59, 0x5D, 0x55, 0xB9, + 0xB9, 0xA5, 0xA5, 0xC3, 0x7E, 0x3C, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7F, 0x7F, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3C, 0x7E, 0x66, 0x7E, 0x3C, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1C, 0x1C, 0x7F, 0x7F, 0x7F, 0x38, + 0x38, 0x00, 0xFE, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x78, 0x7C, 0x0C, 0x3C, 0x78, 0xC0, + 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x78, 0x7C, 0x0C, 0x18, 0x0C, 0xF8, + 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1C, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0xFC, 0xE0, 0xE0, 0xC0, + 0x00, 0x00, 0x00, 0x3F, 0x6D, 0x6D, 0x6D, 0x7A, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x38, + 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x1C, 0x0C, 0x1C, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x30, 0x70, 0x30, 0x30, 0x30, 0xF0, + 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x7C, 0x44, 0x7C, 0x38, 0x00, 0xF8, + 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, + 0x6C, 0x36, 0x36, 0x6C, 0xD8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x30, 0x70, 0x31, 0x33, 0x7F, 0x1C, + 0x38, 0x76, 0xEE, 0xD6, 0x3E, 0x3E, 0x06, 0x00, + 0x00, 0x00, 0x30, 0x70, 0x31, 0x33, 0x7F, 0x1C, + 0x38, 0x70, 0xFC, 0xC6, 0x0C, 0x18, 0x1E, 0x00, + 0x00, 0x00, 0x70, 0x18, 0x31, 0x1B, 0x77, 0x1C, + 0x3A, 0x76, 0xEE, 0xD6, 0x3E, 0x3E, 0x06, 0x00, + 0x00, 0x00, 0x0E, 0x0E, 0x0E, 0x00, 0x0E, 0x1C, + 0x7C, 0xF8, 0xE0, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, + 0x00, 0x70, 0x38, 0x00, 0x08, 0x1C, 0x3E, 0xEE, + 0xFE, 0xFE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0x07, 0x0E, 0x00, 0x08, 0x1C, 0x3E, 0xEE, + 0xFE, 0xFE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0x1C, 0x36, 0x63, 0x08, 0x1C, 0x3E, 0xEE, + 0xFE, 0xFE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0x3B, 0x6E, 0x00, 0x08, 0x1C, 0x3E, 0xEE, + 0xFE, 0xFE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0x77, 0x77, 0x08, 0x1C, 0x3E, 0x76, 0xFE, + 0xFE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0x1C, 0x36, 0x1C, 0x1C, 0x3E, 0x76, 0xFE, + 0xFE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0x0F, 0x1F, 0x3F, 0x7F, 0x77, 0x7F, 0xFF, + 0xFE, 0xEE, 0xEF, 0xEF, 0xEF, 0x00, 0x00, 0x00, + 0x00, 0x3E, 0x7F, 0x77, 0x70, 0x70, 0x70, 0xE0, + 0xE0, 0xE0, 0xEE, 0xFE, 0x7C, 0x0E, 0x6E, 0x7C, + 0x00, 0x38, 0x1C, 0x00, 0x7F, 0x7F, 0x70, 0xE0, + 0xF8, 0xE0, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x0E, 0x1C, 0x00, 0x7F, 0x7F, 0x70, 0xE0, + 0xF8, 0xE0, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x3E, 0x77, 0x00, 0x7F, 0x7F, 0x70, 0xE0, + 0xF8, 0xE0, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x77, 0x77, 0x00, 0x7F, 0x7F, 0x70, 0x70, 0xF8, + 0xF8, 0xE0, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x1C, 0x00, 0x1C, 0x1C, 0x1C, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x0E, 0x1C, 0x00, 0x1C, 0x1C, 0x1C, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x1C, 0x36, 0x1C, 0x1C, 0x1C, 0x1C, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x77, 0x77, 0x00, 0x1C, 0x1C, 0x1C, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7C, 0x7E, 0x77, 0x77, 0x76, 0xFE, + 0xEE, 0xEE, 0xEE, 0xFC, 0xF8, 0x00, 0x00, 0x00, + 0x00, 0x3B, 0x6E, 0x00, 0x77, 0x77, 0x76, 0xF6, + 0xFE, 0xDE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x1C, 0x00, 0x3E, 0x7F, 0x76, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x0E, 0x1C, 0x00, 0x3E, 0x7F, 0x76, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x3E, 0x77, 0x00, 0x3E, 0x7F, 0x76, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x3B, 0x6E, 0x00, 0x3E, 0x7F, 0x76, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x77, 0x77, 0x00, 0x3E, 0x7F, 0x77, 0x76, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x76, 0x7C, + 0x38, 0x38, 0x7C, 0xEE, 0xC6, 0x00, 0x00, 0x00, + 0x00, 0x3D, 0x7E, 0x77, 0x77, 0x77, 0x7E, 0xFE, + 0xFE, 0xEE, 0xEE, 0xFE, 0x7C, 0x80, 0x00, 0x00, + 0x00, 0x38, 0x1C, 0x00, 0x77, 0x77, 0x76, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x0E, 0x1C, 0x00, 0x77, 0x77, 0x76, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x3E, 0x77, 0x00, 0x77, 0x77, 0x76, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x77, 0x77, 0x00, 0x77, 0x77, 0x77, 0x76, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x0E, 0x1C, 0x00, 0x77, 0x77, 0x76, 0xEE, + 0x7C, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x70, 0x70, 0x7E, 0x7F, 0x76, 0xEE, + 0xEE, 0xFE, 0xFC, 0xE0, 0xE0, 0x00, 0x00, 0x00, + 0x00, 0x3E, 0x7F, 0x77, 0x77, 0x77, 0x7E, 0xFC, + 0xEE, 0xEE, 0xEE, 0xFE, 0xFC, 0xE0, 0xC0, 0x00, + 0x00, 0x00, 0x70, 0x38, 0x00, 0x3C, 0x3E, 0x0E, + 0x3E, 0x7E, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1C, 0x38, 0x00, 0x3C, 0x3E, 0x0E, + 0x3E, 0x7E, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x7C, 0xEE, 0x00, 0x3C, 0x3E, 0x0E, + 0x3E, 0x7E, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x76, 0xDC, 0x00, 0x3C, 0x3E, 0x0E, + 0x3E, 0x7E, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xEE, 0xEE, 0x00, 0x3C, 0x3E, 0x0E, + 0x3E, 0x7E, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6C, 0x38, 0x00, 0x3C, 0x3E, 0x0E, + 0x3E, 0x7E, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3A, 0x3F, 0x3F, 0x1A, + 0x7E, 0xFE, 0xD8, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0xFE, + 0xEE, 0xE0, 0xEE, 0xFE, 0x7C, 0x1C, 0x7E, 0x7C, + 0x00, 0x00, 0x38, 0x1C, 0x00, 0x3E, 0x7F, 0xEE, + 0xFE, 0xFE, 0xE0, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1C, 0x38, 0x00, 0x3E, 0x7F, 0xEE, + 0xFE, 0xFE, 0xE0, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x1C, 0x3E, 0x77, 0x00, 0x3E, 0x7F, 0xEE, + 0xFE, 0xFE, 0xE0, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x77, 0x77, 0x00, 0x3E, 0x7F, 0xEE, + 0xFE, 0xFE, 0xE0, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x1C, 0x00, 0x1C, 0x1C, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0E, 0x1C, 0x00, 0x1C, 0x1C, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x1C, 0x3E, 0x77, 0x00, 0x1C, 0x1C, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x77, 0x77, 0x00, 0x1C, 0x1C, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x76, 0x3E, 0x7C, 0x7E, 0x3F, 0x7E, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x3B, 0x7F, 0x6E, 0x00, 0x7E, 0x7F, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x70, 0x38, 0x00, 0x3C, 0x7E, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFC, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1C, 0x38, 0x00, 0x3C, 0x7E, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFC, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x1C, 0x3E, 0x77, 0x00, 0x3C, 0x7E, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFC, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x3B, 0x7F, 0x6E, 0x00, 0x3C, 0x7E, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFC, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x77, 0x77, 0x00, 0x3C, 0x7E, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFC, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1C, 0x1C, 0x00, 0xFE, + 0xFE, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x3E, 0x7E, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7C, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x70, 0x38, 0x00, 0x77, 0x76, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1C, 0x38, 0x00, 0x77, 0x76, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x1C, 0x3E, 0x77, 0x00, 0x77, 0x76, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x77, 0x77, 0x00, 0x77, 0x76, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0E, 0x1C, 0x00, 0x77, 0x76, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7E, 0x0E, 0xFE, 0xFC, + 0x00, 0x00, 0x70, 0x70, 0x7E, 0x7F, 0x76, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xFE, 0xFC, 0xE0, 0xE0, + 0x00, 0x00, 0x77, 0x77, 0x00, 0x77, 0x76, 0xEE, + 0xEE, 0xEE, 0xEE, 0xFE, 0x7E, 0x0E, 0xFE, 0xFC, +}; + +const struct fb_font_desc font_italic_bold = { + .name = "NetSurf Italic Bold", + .width = 8, + .height = 16, + .encoding = "CP1252", + .data = fontdata_italic_bold, +}; + + +static const uint32_t fontdata_regular[FONTDATAMAX] = { + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0xE4, 0xAC, 0xA4, 0xA4, 0xEE, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0xEC, 0xA2, 0xA4, 0xA8, 0xEE, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0xEC, 0xA2, 0xAC, 0xA2, 0xEC, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0xEA, 0xAA, 0xAE, 0xA2, 0xE2, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0xEE, 0xA8, 0xAE, 0xA2, 0xEE, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0xE6, 0xA8, 0xAE, 0xAA, 0xEE, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0xEE, 0xA2, 0xA4, 0xA4, 0xE4, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0xEE, 0xAA, 0xAE, 0xAA, 0xEE, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0xEE, 0xAA, 0xAE, 0xA2, 0xE2, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0xE4, 0xAA, 0xAE, 0xAA, 0xEA, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0xEC, 0xAA, 0xAC, 0xAA, 0xEC, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0xE4, 0xAA, 0xA8, 0xAA, 0xE4, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0xEC, 0xAA, 0xAA, 0xAA, 0xEC, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0xEE, 0xA8, 0xAC, 0xA8, 0xEE, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0xEE, 0xA8, 0xAC, 0xA8, 0xE8, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0x4E, 0xCA, 0x4A, 0x4A, 0xEE, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0x44, 0xCC, 0x44, 0x44, 0xEE, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0x4C, 0xC2, 0x44, 0x48, 0xEE, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0x4C, 0xC2, 0x4C, 0x42, 0xEC, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0x4A, 0xCA, 0x4E, 0x42, 0xE2, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0x4E, 0xC8, 0x4E, 0x42, 0xEE, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0x46, 0xC8, 0x4E, 0x4A, 0xEE, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0x4E, 0xC2, 0x44, 0x44, 0xE4, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0x4E, 0xCA, 0x4E, 0x4A, 0xEE, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0x4E, 0xCA, 0x4E, 0x42, 0xE2, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0x44, 0xCA, 0x4E, 0x4A, 0xEA, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0x4C, 0xCA, 0x4C, 0x4A, 0xEC, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0x44, 0xCA, 0x48, 0x4A, 0xE4, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0x4C, 0xCA, 0x4A, 0x4A, 0xEC, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0x4E, 0xC8, 0x4C, 0x48, 0xEE, 0x00, 0xFE, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0x4E, 0xC8, 0x4C, 0x48, 0xE8, 0x00, 0xFE, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x6C, 0x6C, 0x6C, 0x6C, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x6C, 0x6C, 0x6C, 0xFE, 0xFE, 0x6C, 0x6C, + 0xFE, 0xFE, 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x7C, 0xFE, 0xD6, 0xD0, 0xF0, 0x7C, + 0x1E, 0x16, 0xD6, 0xFE, 0x7C, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xCE, 0x1C, + 0x38, 0x70, 0xE6, 0xC6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x70, 0xF8, 0xD8, 0xD8, 0xF8, 0x72, 0xFE, + 0xDE, 0xCC, 0xCC, 0xFE, 0x7A, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x0E, 0x1C, 0x18, 0x38, 0x30, 0x30, 0x30, + 0x30, 0x38, 0x18, 0x1C, 0x0E, 0x06, 0x00, 0x00, + 0x60, 0x70, 0x38, 0x18, 0x1C, 0x0C, 0x0C, 0x0C, + 0x0C, 0x1C, 0x18, 0x38, 0x70, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x6C, 0x6C, 0x38, 0xFE, + 0xFE, 0x38, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, 0x7E, + 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x38, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0E, 0x1C, + 0x38, 0x70, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0xFE, 0xC6, 0xCE, 0xCE, 0xD6, 0xD6, + 0xE6, 0xE6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x38, 0x78, 0x78, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0xFE, 0xC6, 0x06, 0x06, 0x3E, 0x7C, + 0xE0, 0xC0, 0xC0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0xFE, 0xC6, 0x06, 0x06, 0x3C, 0x3C, + 0x06, 0x06, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x0C, 0x1C, 0x3C, 0x7C, 0xEC, 0xFE, + 0xFE, 0x0C, 0x0C, 0x0C, 0x0C, 0x00, 0x00, 0x00, + 0x00, 0xFE, 0xFE, 0xC0, 0xC0, 0xC0, 0xFC, 0xFE, + 0x06, 0x06, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x3C, 0x7C, 0xE0, 0xC0, 0xC0, 0xFC, 0xFE, + 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0xFE, 0xFE, 0xC6, 0x0E, 0x0C, 0x1C, 0x18, + 0x38, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0xFE, 0xC6, 0xC6, 0xC6, 0x7C, 0x7C, + 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0xFE, 0xC6, 0xC6, 0xC6, 0xFE, 0x7E, + 0x06, 0x06, 0x0E, 0x7C, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, + 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, + 0x00, 0x18, 0x18, 0x38, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x06, 0x0E, 0x1C, 0x38, 0x70, 0x70, + 0x38, 0x1C, 0x0E, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x00, 0x00, + 0x7E, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x60, 0x70, 0x38, 0x1C, 0x0E, 0x0E, + 0x1C, 0x38, 0x70, 0x60, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0xFE, 0xC6, 0xC6, 0x06, 0x1E, 0x3C, + 0x30, 0x30, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0xFE, 0xC6, 0xCE, 0xDE, 0xD6, 0xD6, + 0xDE, 0xCC, 0xC0, 0xFC, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0xFE, 0xC6, 0xC6, 0xC6, 0xFE, 0xFE, + 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, + 0x00, 0xFC, 0xFE, 0xC6, 0xC6, 0xC6, 0xFC, 0xFC, + 0xC6, 0xC6, 0xC6, 0xFE, 0xFC, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0xFE, 0xC6, 0xC0, 0xC0, 0xC0, 0xC0, + 0xC0, 0xC0, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0xF8, 0xFC, 0xCE, 0xC6, 0xC6, 0xC6, 0xC6, + 0xC6, 0xC6, 0xCE, 0xFC, 0xF8, 0x00, 0x00, 0x00, + 0x00, 0xFE, 0xFE, 0xC0, 0xC0, 0xC0, 0xF8, 0xF8, + 0xC0, 0xC0, 0xC0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0xFE, 0xFE, 0xC0, 0xC0, 0xC0, 0xF8, 0xF8, + 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0xFE, 0xC6, 0xC0, 0xC0, 0xDE, 0xDE, + 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xFE, 0xFE, + 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, + 0x00, 0x7E, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x7E, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, + 0x0C, 0x0C, 0xCC, 0xFC, 0x78, 0x00, 0x00, 0x00, + 0x00, 0xC0, 0xC6, 0xCE, 0xDC, 0xF8, 0xF0, 0xE0, + 0xF0, 0xF8, 0xDC, 0xCE, 0xC6, 0x00, 0x00, 0x00, + 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, + 0xC0, 0xC0, 0xC0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0xC6, 0xC6, 0xEE, 0xFE, 0xFE, 0xFE, 0xD6, + 0xD6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, + 0x00, 0xC6, 0xC6, 0xE6, 0xE6, 0xF6, 0xF6, 0xDE, + 0xDE, 0xCE, 0xCE, 0xC6, 0xC6, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, + 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0xFC, 0xFE, 0xC6, 0xC6, 0xC6, 0xFE, 0xFC, + 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, + 0xC6, 0xD6, 0xDE, 0xFE, 0x7C, 0x06, 0x00, 0x00, + 0x00, 0xFC, 0xFE, 0xC6, 0xC6, 0xC6, 0xFC, 0xFC, + 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0xFE, 0xC6, 0xC0, 0xC0, 0xFC, 0x7E, + 0x06, 0x06, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x7E, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, + 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xEE, + 0x6C, 0x7C, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, + 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xD6, + 0xD6, 0xFE, 0xFE, 0xEE, 0x44, 0x00, 0x00, 0x00, + 0x00, 0xC6, 0xC6, 0xC6, 0xEE, 0x7C, 0x38, 0x38, + 0x7C, 0xEE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, + 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xEE, 0x7C, 0x38, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0xFE, 0xFE, 0x0E, 0x0C, 0x1C, 0x18, 0x38, + 0x30, 0x70, 0x60, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x3E, 0x3E, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x3E, 0x3E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE0, 0x70, + 0x38, 0x1C, 0x0E, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0x7C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, + 0x0C, 0x0C, 0x0C, 0x7C, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x7C, 0xEE, 0xC6, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, + 0x00, 0x00, 0x30, 0x30, 0x18, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x7E, 0x06, + 0x7E, 0xFE, 0xC6, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0xFC, 0xFE, 0xC6, + 0xC6, 0xC6, 0xC6, 0xFE, 0xFC, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xFE, 0xC6, + 0xC0, 0xC0, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x06, 0x06, 0x06, 0x06, 0x7E, 0xFE, 0xC6, + 0xC6, 0xC6, 0xC6, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xFE, 0xC6, + 0xFE, 0xFE, 0xC0, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x1E, 0x3E, 0x30, 0x30, 0x30, 0x78, 0x78, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xFE, 0xC6, + 0xC6, 0xC6, 0xC6, 0xFE, 0x7E, 0x06, 0x7E, 0x7C, + 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xDC, 0xFE, 0xE6, + 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x38, 0x18, + 0x18, 0x18, 0x18, 0x3C, 0x3C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0C, 0x0C, 0x00, 0x1C, 0x1C, 0x0C, + 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x7C, 0x78, + 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0xC6, 0xCE, 0xDC, + 0xF8, 0xF8, 0xDC, 0xCE, 0xC6, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0xFE, 0xFE, + 0xD6, 0xD6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0xFE, 0xE6, + 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xFE, 0xC6, + 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFE, 0xC6, + 0xC6, 0xC6, 0xC6, 0xFE, 0xFC, 0xC0, 0xC0, 0xC0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xFE, 0xC6, + 0xC6, 0xC6, 0xC6, 0xFE, 0x7E, 0x06, 0x07, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xDE, 0xFE, 0xE0, + 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xFE, 0xC0, + 0xFC, 0x7C, 0x06, 0xFE, 0xFC, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x30, 0x30, 0x30, 0x7C, 0xFC, 0x30, + 0x30, 0x30, 0x30, 0x3E, 0x1E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, + 0xC6, 0xC6, 0xCE, 0xFE, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, + 0xC6, 0xEE, 0x7C, 0x38, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, + 0xD6, 0xD6, 0xFE, 0xFE, 0x6C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xEE, + 0x7C, 0x7C, 0xEE, 0xC6, 0xC6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, + 0xC6, 0xC6, 0xC6, 0xFE, 0x7E, 0x06, 0xFE, 0xFC, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x0E, + 0x3C, 0x78, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x0E, 0x1E, 0x18, 0x18, 0x18, 0x70, 0x70, + 0x18, 0x18, 0x18, 0x1E, 0x0E, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, + 0x00, 0x70, 0x78, 0x18, 0x18, 0x18, 0x0E, 0x0E, + 0x18, 0x18, 0x18, 0x78, 0x70, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x76, 0xFE, 0xDC, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, + 0x00, 0xEE, 0x28, 0x4C, 0x48, 0x48, 0x00, 0xFE, + 0x00, 0x18, 0x3C, 0x66, 0x60, 0xFC, 0x60, 0xF8, + 0x60, 0x60, 0x66, 0x3C, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x38, 0x6C, 0x54, 0xF6, 0xEE, + 0x6C, 0x7C, 0x28, 0x38, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0x08, 0x10, 0x00, + 0x00, 0x1E, 0x3E, 0x30, 0x30, 0x30, 0x78, 0x78, + 0x30, 0x30, 0x30, 0x30, 0x30, 0xF0, 0x60, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x66, 0x66, 0x22, 0x44, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xDB, 0xDB, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x18, 0x18, 0x7E, 0x7E, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, + 0x00, 0x18, 0x18, 0x18, 0x7E, 0x7E, 0x18, 0x7E, + 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, + 0x00, 0x7C, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC2, 0xC6, 0x0C, + 0x18, 0x30, 0x60, 0xDB, 0x9B, 0x00, 0x00, 0x00, + 0xC6, 0x7C, 0x00, 0x7C, 0xFE, 0xC6, 0xC0, 0xFC, + 0x7E, 0x06, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x1C, + 0x38, 0x30, 0x38, 0x1C, 0x0C, 0x00, 0x00, 0x00, + 0x00, 0x7F, 0xFF, 0xCC, 0xCC, 0xCC, 0xCF, 0xCF, + 0xCC, 0xCC, 0xCC, 0xFF, 0x7F, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x38, 0x6C, 0x54, 0xF6, 0xEE, + 0x6C, 0x7C, 0x28, 0x38, 0x10, 0x00, 0x00, 0x00, + 0xC6, 0x7C, 0x00, 0xFE, 0xFE, 0x06, 0x0C, 0x18, + 0x30, 0x60, 0xC0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x38, 0x6C, 0x54, 0xF6, 0xEE, + 0x6C, 0x7C, 0x28, 0x38, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x38, 0x6C, 0x54, 0xF6, 0xEE, + 0x6C, 0x7C, 0x28, 0x38, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x20, 0x30, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x30, 0x30, 0x10, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x24, 0x48, 0x6C, 0x6C, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x36, 0x36, 0x12, 0x24, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x7E, + 0x7E, 0x7E, 0x7E, 0x3C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x32, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xF1, 0xFB, 0x5F, 0x55, 0x51, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xC6, 0x6C, 0x38, 0x00, 0x7E, 0xFE, 0xC0, + 0xFC, 0x7C, 0x06, 0xFE, 0xFC, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x38, + 0x1C, 0x0C, 0x1C, 0x38, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x6C, 0xFE, 0xDA, + 0xDE, 0xDE, 0xD8, 0xFE, 0x6E, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x38, 0x6C, 0x54, 0xF6, 0xEE, + 0x6C, 0x7C, 0x28, 0x38, 0x10, 0x00, 0x00, 0x00, + 0x00, 0xC6, 0x6C, 0x38, 0x00, 0xFE, 0xFE, 0x0E, + 0x3C, 0x78, 0xE0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x6C, 0x00, 0xC6, 0xC6, 0xC6, 0xEE, 0x7C, + 0x38, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x10, 0x7C, 0xFE, 0xD6, + 0xD0, 0xD0, 0xD6, 0xFE, 0x7C, 0x10, 0x10, 0x00, + 0x00, 0x3C, 0x7E, 0x66, 0x60, 0x60, 0xF8, 0xF8, + 0x60, 0x60, 0xE6, 0xFE, 0xDC, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x3C, 0x7E, + 0x66, 0x66, 0x7E, 0x3C, 0x66, 0x66, 0x00, 0x00, + 0x00, 0x00, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, + 0x18, 0x7E, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, + 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x3C, 0x7C, 0x60, 0x60, 0x3C, 0x7E, 0x66, + 0x7E, 0x3C, 0x06, 0x06, 0x3E, 0x3C, 0x00, 0x00, + 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3C, 0x7E, 0xC3, 0x99, 0xBD, 0xA5, 0xA1, + 0xA5, 0xBD, 0x99, 0xC3, 0x7E, 0x3C, 0x00, 0x00, + 0x00, 0x70, 0x08, 0x78, 0x88, 0x78, 0x00, 0xF8, + 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, + 0x6C, 0xD8, 0xD8, 0x6C, 0x36, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7E, 0x7E, 0x06, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3C, 0x7E, 0xC3, 0xB9, 0xBD, 0xA5, 0xB9, + 0xB9, 0xA5, 0xA5, 0xC3, 0x7E, 0x3C, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x78, 0xFC, 0xCC, 0xFC, 0x78, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, 0x7E, 0x18, + 0x18, 0x00, 0x7E, 0x7E, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xF0, 0xF8, 0x18, 0x78, 0xF0, 0xC0, + 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xF0, 0xF8, 0x18, 0x30, 0x18, 0xF8, + 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x7E, 0x7C, 0x60, 0x60, 0xC0, + 0x00, 0x00, 0x00, 0x7F, 0xDB, 0xDB, 0xDB, 0x7B, + 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x1C, 0x0C, 0x1C, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x60, 0xE0, 0x60, 0x60, 0x60, 0xF0, + 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x70, 0xF8, 0x88, 0xF8, 0x70, 0x00, 0xF8, + 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, + 0x6C, 0x36, 0x36, 0x6C, 0xD8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x40, 0xC0, 0x42, 0x46, 0xEC, 0x18, + 0x30, 0x64, 0xCC, 0x94, 0x3E, 0x04, 0x04, 0x00, + 0x00, 0x00, 0x40, 0xC0, 0x42, 0x46, 0xEC, 0x18, + 0x30, 0x60, 0xDC, 0x82, 0x0C, 0x10, 0x1E, 0x00, + 0x00, 0x00, 0xE0, 0x10, 0x62, 0x16, 0xEC, 0x18, + 0x30, 0x64, 0xCC, 0x96, 0x3E, 0x04, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, + 0x78, 0xF0, 0xC0, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, + 0x00, 0x60, 0x30, 0x00, 0x10, 0x38, 0x6C, 0xC6, + 0xFE, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, + 0x00, 0x0C, 0x18, 0x00, 0x10, 0x38, 0x6C, 0xC6, + 0xFE, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6C, 0x44, 0x10, 0x38, 0x6C, 0xC6, + 0xFE, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, + 0x00, 0x76, 0xDC, 0x00, 0x10, 0x38, 0x6C, 0xC6, + 0xFE, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, + 0x6C, 0x6C, 0x00, 0x10, 0x38, 0x6C, 0xC6, 0xFE, + 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x44, 0x38, 0x38, 0x6C, 0xC6, 0xFE, + 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, + 0x00, 0x1F, 0x3F, 0x7C, 0xEC, 0xCC, 0xFE, 0xFE, + 0xCC, 0xCC, 0xCC, 0xCF, 0xCF, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0xFE, 0xC6, 0xC0, 0xC0, 0xC0, 0xC0, + 0xC0, 0xC0, 0xC6, 0xFE, 0x7C, 0x0E, 0x66, 0x3C, + 0x00, 0x30, 0x18, 0x00, 0xFE, 0xFE, 0xC0, 0xF0, + 0xF0, 0xC0, 0xC0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x0C, 0x18, 0x00, 0xFE, 0xFE, 0xC0, 0xF0, + 0xF0, 0xC0, 0xC0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6C, 0x00, 0xFE, 0xFE, 0xC0, 0xF0, + 0xF0, 0xC0, 0xC0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x6C, 0x6C, 0x00, 0xFE, 0xFE, 0xC0, 0xC0, 0xF0, + 0xF0, 0xC0, 0xC0, 0xFE, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x0C, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x24, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x66, 0x66, 0x00, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x78, 0x7C, 0x6E, 0x66, 0x66, 0xF6, + 0x66, 0x66, 0x6E, 0x7C, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x76, 0xDC, 0x00, 0xC6, 0xC6, 0xE6, 0xF6, + 0xFE, 0xDE, 0xCE, 0xC6, 0xC6, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x18, 0x00, 0x7C, 0xFE, 0xC6, 0xC6, + 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x0C, 0x18, 0x00, 0x7C, 0xFE, 0xC6, 0xC6, + 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6C, 0x00, 0x7C, 0xFE, 0xC6, 0xC6, + 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x76, 0xDC, 0x00, 0x7C, 0xFE, 0xC6, 0xC6, + 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x6C, 0x00, 0x7C, 0xFE, 0xC6, 0xC6, 0xC6, + 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xEE, 0x7C, + 0x38, 0x38, 0x7C, 0xEE, 0xC6, 0x00, 0x00, 0x00, + 0x00, 0x7E, 0xFE, 0xC6, 0xC6, 0xCE, 0xCE, 0xD6, + 0xD6, 0xE6, 0xE6, 0xFE, 0x7C, 0x80, 0x00, 0x00, + 0x00, 0x30, 0x18, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, + 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x0C, 0x18, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, + 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6C, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, + 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x6C, 0x6C, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, + 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x0C, 0x18, 0x00, 0x66, 0x66, 0x66, 0x7E, + 0x3C, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x60, 0x60, 0x7C, 0x7E, 0x66, 0x66, + 0x7E, 0x7C, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, + 0x00, 0x3C, 0x7E, 0x66, 0x66, 0x66, 0x7E, 0x7C, + 0x66, 0x66, 0x66, 0x7E, 0x7C, 0xE0, 0xC0, 0x00, + 0x00, 0x00, 0x30, 0x18, 0x00, 0x7E, 0xFE, 0xC6, + 0xC6, 0xCE, 0xCE, 0xFE, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x30, 0x00, 0x7E, 0xFE, 0xC6, + 0xC6, 0xC6, 0xCE, 0xFE, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6C, 0x00, 0x7E, 0xFE, 0xC6, + 0xC6, 0xC6, 0xCE, 0xFE, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x76, 0xDC, 0x00, 0x7E, 0xFE, 0xC6, + 0xC6, 0xC6, 0xCE, 0xFE, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x6C, 0x6C, 0x00, 0x7E, 0xFE, 0xC6, + 0xC6, 0xC6, 0xCE, 0xFE, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6C, 0x38, 0x00, 0x7E, 0xFE, 0xC6, + 0xC6, 0xC6, 0xCE, 0xFE, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x7E, 0x1A, + 0x3E, 0x7E, 0xD8, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xFE, + 0xC6, 0xC0, 0xC6, 0xFE, 0x7C, 0x18, 0x7C, 0x78, + 0x00, 0x00, 0x30, 0x18, 0x00, 0x7C, 0xFE, 0xC6, + 0xFE, 0xFE, 0xC0, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x30, 0x00, 0x7C, 0xFE, 0xC6, + 0xFE, 0xFE, 0xC0, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6C, 0x00, 0x7C, 0xFE, 0xC6, + 0xFE, 0xFE, 0xC0, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x6C, 0x6C, 0x00, 0x7C, 0xFE, 0xC6, + 0xFE, 0xFE, 0xC0, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x30, 0x18, 0x00, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0C, 0x18, 0x00, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x3C, 0x66, 0x00, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x66, 0x66, 0x00, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x6C, 0x7C, 0xF8, 0xDC, 0x7C, 0xFE, 0xC6, + 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x76, 0xFE, 0xDC, 0x00, 0xFC, 0xFE, 0xC6, + 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x60, 0x30, 0x00, 0x7C, 0xFE, 0xC6, + 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x30, 0x00, 0x7C, 0xFE, 0xC6, + 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6C, 0x00, 0x7C, 0xFE, 0xC6, + 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x76, 0xFE, 0xDC, 0x00, 0x7C, 0xFE, 0xC6, + 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x6C, 0x6C, 0x00, 0x7C, 0xFE, 0xC6, + 0xC6, 0xC6, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7E, + 0x7E, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x7C, 0xFE, 0xCE, + 0xD6, 0xD6, 0xE6, 0xFE, 0x7C, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x60, 0x30, 0x00, 0xC6, 0xC6, 0xC6, + 0xC6, 0xC6, 0xC6, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x30, 0x00, 0xC6, 0xC6, 0xC6, + 0xC6, 0xC6, 0xC6, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6C, 0x00, 0xC6, 0xC6, 0xC6, + 0xC6, 0xC6, 0xC6, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x6C, 0x6C, 0x00, 0xC6, 0xC6, 0xC6, + 0xC6, 0xC6, 0xC6, 0xFE, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0C, 0x18, 0x00, 0xC6, 0xC6, 0xC6, + 0xC6, 0xC6, 0xC6, 0xFE, 0x7E, 0x06, 0xFC, 0xF8, + 0x00, 0x00, 0x60, 0x60, 0x60, 0x7C, 0x7E, 0x66, + 0x66, 0x66, 0x66, 0x7E, 0x7C, 0x60, 0x60, 0x60, + 0x00, 0x00, 0x6C, 0x6C, 0x00, 0xC6, 0xC6, 0xC6, + 0xC6, 0xC6, 0xC6, 0xFE, 0x7E, 0x06, 0xFE, 0xFC, +}; + +const struct fb_font_desc font_regular = { + .name = "NetSurf Regular", + .width = 8, + .height = 16, + .encoding = "CP1252", + .data = fontdata_regular, +}; + +#endif diff --git a/frontends/atari/plot/font_internal.h b/frontends/atari/plot/font_internal.h new file mode 100644 index 000000000..9bfbbedef --- /dev/null +++ b/frontends/atari/plot/font_internal.h @@ -0,0 +1,37 @@ +/* + * Copyright 2008 Vincent Sanders <vince@simtec.co.uk> + * Copyright 2011 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifdef WITH_INTERNAL_FONT_DRIVER +#ifndef FONT_PLOTTER_INTERNAL +#define FONT_PLOTTER_INTERNAL + +#include "atari/plot/plot.h" + +int ctor_font_plotter_internal( FONT_PLOTTER self ); + +struct fb_font_desc { + const char *name; + int width, height; + const char *encoding; + const uint32_t *data; +}; + + +#endif +#endif diff --git a/frontends/atari/plot/font_vdi.c b/frontends/atari/plot/font_vdi.c new file mode 100644 index 000000000..ef5499207 --- /dev/null +++ b/frontends/atari/plot/font_vdi.c @@ -0,0 +1,310 @@ +/* + * Copyright 2010 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifdef WITH_VDI_FONT_DRIVER + +#include <mt_gemx.h> + +#include "atari/plot/plot.h" +#include "atari/plot/font_vdi.h" + +#include "utils/utf8.h" +#include "utils/log.h" + +#include "atari/encoding.h" + + +//static char * lstr = NULL; + +static int dtor( FONT_PLOTTER self ); +static int str_width( FONT_PLOTTER self,const plot_font_style_t *fstyle, const char * str, size_t length, int * width ); +static int str_split( FONT_PLOTTER self, const plot_font_style_t *fstyle,const char *string, + size_t length,int x, size_t *char_offset, int *actual_x ); +static int pixel_pos( FONT_PLOTTER self, const plot_font_style_t *fstyle,const char *string, + size_t length,int x, size_t *char_offset, int *actual_x ); +static int text( FONT_PLOTTER self, int x, int y, const char *text, size_t length, const plot_font_style_t *fstyle ); + +static bool init = false; +static int vdih; + +extern struct s_vdi_sysinfo vdi_sysinfo; + +static inline void atari_to_vdi_str(char *lstr, int length) +{ + int i, z; + + for (i=z=0; i<length; ) { + if (((char)lstr[i]==(char)0xC2) && ((char)lstr[i+1] == (char)0xA0)) { + lstr[z] = ' '; + lstr[z+1] = ' '; + i=i+2; + z=z+2; + } + else { + lstr[z] = lstr[i]; + i++; + z++; + } + } +} + +int ctor_font_plotter_vdi( FONT_PLOTTER self ) +{ + self->dtor = dtor; + self->str_width = str_width; + self->str_split = str_split; + self->pixel_pos = pixel_pos; + self->text = text; + LOG("%s: %s\n", (char *)__FILE__, __FUNCTION__); + if( !init ) { + vdih = self->vdi_handle; + } + init = true; + return( 1 ); +} + +static int dtor( FONT_PLOTTER self ) +{ + return( 1 ); +} + +static int str_width( FONT_PLOTTER self,const plot_font_style_t *fstyle, const char * str, + size_t length, int * width ) +{ + short cw, ch, cellw, cellh; + short pxsize; + short fx=0; + char * lstr = NULL; + + utf8_to_local_encoding(str, length, &lstr); + assert( lstr != NULL ); + int slen = strlen(lstr); + + + atari_to_vdi_str(lstr, slen); + + if( fstyle->flags & FONTF_ITALIC ) + fx |= 4; + if( fstyle->flags & FONTF_OBLIQUE ) + fx |= 16; + if( fstyle->weight > 450 ) + fx |= 1; + vst_effects( self->vdi_handle, fx ); + /* TODO: replace 90 with global dpi setting */ + //pxsize = ceil( (fstyle->size/FONT_SIZE_SCALE) * 90 / 72 ); + //vst_height( self->vdi_handle, pxsize ,&cw, &ch, &cellw, &cellh); + pxsize = ceil( (fstyle->size/FONT_SIZE_SCALE) * 90 ); + vst_point( self->vdi_handle, pxsize, &cw, &ch, &cellw, &cellh); +/* + if(slen != utf8_bounded_length(str, length)){ + printf("sl: %d, utl: %d\n ", slen, utf8_bounded_length(str, length)); + printf("s: %s // %s\n", str, lstr ); + }*/ + + + *width = slen * cellw; + free((void*)lstr); + return( 0 ); +} + +static int str_split( FONT_PLOTTER self, const plot_font_style_t * fstyle, const char *string, + size_t length,int x, size_t *char_offset, int *actual_x ) +{ + short cw, ch, cellw, cellh; + short pxsize; + short fx=0; + char *lstr = NULL; + size_t slen = 0; + int last_space_x = 0; + int last_space_idx = 0; + size_t nxtchr = 0; + + utf8_to_local_encoding(string, length, &lstr ); + assert( lstr != NULL ); + slen = strlen(lstr); + + + atari_to_vdi_str(lstr, slen); + + if( fstyle->flags & FONTF_ITALIC ) + fx |= 4; + if( fstyle->flags & FONTF_OBLIQUE ) + fx |= 16; + if( fstyle->weight > 450 ) + fx |= 1; + vst_effects( self->vdi_handle, fx ); + //pxsize = ceil( (fstyle->size/FONT_SIZE_SCALE) * 90 / 72 ); + //vst_height( self->vdi_handle, pxsize ,&cw, &ch, &cellw, &cellh); + + pxsize = ceil( (fstyle->size/FONT_SIZE_SCALE) * 90 ); + vst_point( self->vdi_handle, pxsize, &cw, &ch, &cellw, &cellh); + *actual_x = 0; + //*char_offset = 0; + while (nxtchr < slen) { + if( lstr[nxtchr] == ' ' ) { + last_space_x = *actual_x; + last_space_idx = nxtchr; + } + *actual_x += cellw; + if (*actual_x > x && last_space_idx != 0) { + *actual_x = last_space_x; + *char_offset = last_space_idx; + //printf("at: %s\n", lstr); + return(0); + } + + nxtchr++; + } + if(nxtchr >= length){ + nxtchr = length-1; + } + + *char_offset = nxtchr; + +// for( i=0; i<slen; i++) { +// if( lstr[i] == ' ' ) { +// last_space_x = *actual_x; +// last_space_idx = cpos; +// } +// if( *actual_x > x ) { +// *actual_x = last_space_x; +// *char_offset = last_space_idx; +// return true; +// } +// *actual_x += cellw; +// cpos++; +// } +// *char_offset = cpos; + free( (void*)lstr ); + return( 0 ); +} + +static int pixel_pos( FONT_PLOTTER self, const plot_font_style_t * fstyle,const char *string, + size_t length,int x, size_t *char_offset, int *actual_x ) +{ + short cw, ch, cellw, cellh; + short pxsize=0; + short fx=0; + + char *lstr = NULL; + int i=0; + utf8_to_local_encoding(string, length, &lstr ); + assert( lstr != NULL ); + int slen = strlen(lstr); + + atari_to_vdi_str(lstr, slen); + + if( fstyle->flags & FONTF_ITALIC ) + fx |= 4; + if( fstyle->flags & FONTF_OBLIQUE ) + fx |= 16; + if( fstyle->weight > 450 ) + fx |= 1; + vst_effects(self->vdi_handle, fx); + pxsize = ceil( (fstyle->size/FONT_SIZE_SCALE) * 90 / 72 ); + vst_height( self->vdi_handle, pxsize ,&cw, &ch, &cellw, &cellh); + *actual_x = 0; + *char_offset = 0; + for( i=0; i<slen; i++) { + *actual_x += cellw; + if( *actual_x > x) { + *actual_x -= cellw; + *char_offset = i; + break; + } + } + free((void*)lstr); + lstr = NULL; + return( 0 ); +} + +static inline void vst_rgbcolor( short vdih, uint32_t cin ) +{ +#ifdef WITH_8BPP_SUPPORT + if( vdi_sysinfo.scr_bpp > 8 ) { +#endif + //unsigned short c[4]; + RGB1000 c; + + rgb_to_vdi1000( (unsigned char*)&cin, &c ); + vs_color( vdih, OFFSET_CUSTOM_COLOR, (unsigned short*)&c); + vst_color( vdih, OFFSET_CUSTOM_COLOR ); +#ifdef WITH_8BPP_SUPPORT + } else { + if( vdi_sysinfo.scr_bpp >= 4 ) + vst_color( vdih, RGB_TO_VDI(cin) ); + else + vst_color( vdih, BLACK ); + } +#endif +} + +static int text( FONT_PLOTTER self, int x, int y, const char *text, size_t length, + const plot_font_style_t *fstyle ) +{ + /* todo: either limit the string to max 80 chars, or use v_ftext instead of v_gtext */ + short cw, ch, cellw, cellh; + short pxsize=8; + short fx=0; + GRECT canvas; + char *lstr = NULL; + assert( utf8_to_local_encoding(text, length, &lstr) == NSERROR_OK); + assert( lstr != NULL ); + + int slen = strlen(lstr); + if(slen > 800){ + lstr[800]=0; + } + + + atari_to_vdi_str(lstr, slen); + + if( fstyle->flags & FONTF_ITALIC ) + fx |= 4; + if( fstyle->flags & FONTF_OBLIQUE ) + fx |= 4; + if( fstyle->weight > 450 ) + fx |= 1; + + /* TODO: netsurf uses 90 as default dpi ( somewhere defined in libcss), + use that value or pass it as arg, to reduce netsurf dependency */ + //pxsize = ceil( (fstyle->size/FONT_SIZE_SCALE) * 90 / 72 ); + pxsize = ceil( (fstyle->size/FONT_SIZE_SCALE) * 90 / 72 ); + + plot_get_dimensions(&canvas); + x += canvas.g_x; + y += canvas.g_y; + vst_effects( self->vdi_handle, fx ); + vst_alignment(vdih, 0, 0, &cw, &ch ); + vst_point( self->vdi_handle, pxsize, &cw, &ch, &cellw, &cellh); + //vst_height( self->vdi_handle, pxsize, &cw, &ch, &cellw, &cellh); + vswr_mode( self->vdi_handle, MD_TRANS ); + vst_rgbcolor(self->vdi_handle, fstyle->foreground); + + if( atari_sysinfo.gdos_FSMC ){ + //printf("\nftext\n"); + v_ftext( self->vdi_handle, x, y, (char*)lstr ); + } else { + //printf("\ngtext\n"); + v_gtext( self->vdi_handle, x, y, (char*)lstr ); + } + free( lstr ); + return( 0 ); +} + +#endif diff --git a/frontends/atari/plot/font_vdi.h b/frontends/atari/plot/font_vdi.h new file mode 100644 index 000000000..3a1fdb54b --- /dev/null +++ b/frontends/atari/plot/font_vdi.h @@ -0,0 +1,26 @@ +/* + * Copyright 2010 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifdef WITH_VDI_FONT_DRIVER +#ifndef FONT_PLOTTER_VDI +#define FONT_PLOTTER_VDI + +int ctor_font_plotter_vdi( FONT_PLOTTER self ); + +#endif +#endif diff --git a/frontends/atari/plot/fontplot.c b/frontends/atari/plot/fontplot.c new file mode 100644 index 000000000..9f0edd9a4 --- /dev/null +++ b/frontends/atari/plot/fontplot.c @@ -0,0 +1,132 @@ +/* + * Copyright 2010 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdbool.h> +#include <assert.h> +#include <stdlib.h> +#include <mt_gem.h> + +#include "desktop/mouse.h" +#include "desktop/plot_style.h" + +#include "atari/bitmap.h" +#include "atari/plot/fontplot.h" + +const struct s_font_driver_table_entry font_driver_table[] = +{ +#ifdef WITH_VDI_FONT_DRIVER + {"vdi", ctor_font_plotter_vdi, 0}, +#endif +#ifdef WITH_FREETYPE_FONT_DRIVER + {"freetype", ctor_font_plotter_freetype, 0}, +#endif +#ifdef WITH_INTERNAL_FONT_DRIVER + {"internal", ctor_font_plotter_internal, 0}, +#endif + {(char*)NULL, NULL, 0} +}; + +void dump_font_drivers(void) +{ + int i = 0; + while( font_driver_table[i].name != NULL ) { + printf("%s -> flags: %d\n", font_driver_table[i].name, + font_driver_table[i].flags); + i++; + } +} + + +/** + * Create an new text plotter object. + * + * Available: "vdi", "freetype", "internal" + * + * \param vdihandle the vdi handle to act upon, + * \param name selector ID (string) of the font plotter. + * \param flags configration flags of the plotter, available flags: + * FONTPLOT_FLAG_MONOGLYPH - Enable 1 bit font plotting + * \param error set to != 0 when errors occur + * \return the new font plotter instance on success, or NULL on failure. + */ +FONT_PLOTTER new_font_plotter(int vdihandle, char * name, unsigned long flags, + int * error) +{ + int i=0; + int res = 0-ERR_PLOTTER_NOT_AVAILABLE; + FONT_PLOTTER fplotter = NULL; + + /* set the default error code: */ + *error = 0-ERR_PLOTTER_NOT_AVAILABLE; + + + /* Find the selector string in the font plotter table, */ + /* and bail out when the font plotter is not available: */ + for (i = 0; font_driver_table[i].name != NULL; i++) { + + /* found selector in driver table? */ + if (strcmp(name, font_driver_table[i].name) == 0) { + + /* allocate the font plotter instance: */ + fplotter = (FONT_PLOTTER)malloc(sizeof(struct s_font_plotter)); + if (fplotter == NULL) { + *error = 0-ERR_NO_MEM; + return(NULL); + } + + /* Initialize the font plotter with the requested settings: */ + memset( fplotter, 0, sizeof(FONT_PLOTTER)); + fplotter->vdi_handle = vdihandle; + fplotter->name = name; + fplotter->flags = 0; + fplotter->flags |= flags; + + /* Execute the constructor: */ + assert(font_driver_table[i].ctor); + res = font_driver_table[i].ctor(fplotter); + + /* success? */ + if (res < 0) { + /* NO success! */ + free(fplotter); + *error = res; + return(NULL); + } + *error = 0; + break; + } + } + + return(fplotter); +} + +/* + Free an font plotter +*/ +int delete_font_plotter(FONT_PLOTTER p) +{ + if (p) { + p->dtor(p); + free(p); + p = NULL; + } + else + return(-1); + return(0); +} + diff --git a/frontends/atari/plot/fontplot.h b/frontends/atari/plot/fontplot.h new file mode 100644 index 000000000..6690bff2c --- /dev/null +++ b/frontends/atari/plot/fontplot.h @@ -0,0 +1,86 @@ +/* + * Copyright 2010 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FONT_PLOT_H +#define FONT_PLOT_H + +typedef struct s_font_plotter * FONT_PLOTTER; + +struct s_font_driver_table_entry +{ + const char * name; + int (*ctor)( FONT_PLOTTER self ); + int flags; +}; + +/* declaration of font plotter member functions: (_fpmf_ prefix) */ +typedef int (*_fpmf_str_width)( FONT_PLOTTER self, const plot_font_style_t *fstyle, + const char * str, size_t length, int * width); +typedef int (*_fpmf_str_split)( FONT_PLOTTER self, const plot_font_style_t *fstyle, + const char *string, size_t length, + int x, size_t *char_offset, int *actual_x); +typedef int (*_fpmf_pixel_pos)( FONT_PLOTTER self, const plot_font_style_t *fstyle, + const char *string, size_t length, + int x, size_t *char_offset, int *actual_x); +typedef int (*_fpmf_text)( FONT_PLOTTER self, int x, int y, const char *text, + size_t length, const plot_font_style_t *fstyle); + +typedef void (*_fpmf_draw_glyph)(FONT_PLOTTER self, GRECT * clip, GRECT * loc, + uint8_t * pixdata, int pitch, uint32_t colour); +typedef int (*_fpmf_dtor)( FONT_PLOTTER self ); + + +/* prototype of the font plotter "object" */ +struct s_font_plotter +{ + char * name; + int flags; + int vdi_handle; + void * priv_data; + + _fpmf_str_width str_width; + _fpmf_str_split str_split; + _fpmf_pixel_pos pixel_pos; + _fpmf_text text; + _fpmf_draw_glyph draw_glyph; + _fpmf_dtor dtor; +}; + + +FONT_PLOTTER plot_get_text_plotter(void); +/* Set the font plotting engine. +*/ +void plot_set_text_plotter(FONT_PLOTTER font_plotter); +void dump_font_drivers(void); +FONT_PLOTTER new_font_plotter( int vdihandle, char * name, unsigned long flags, + int * error); +int delete_font_plotter( FONT_PLOTTER p ); + +#ifdef WITH_VDI_FONT_DRIVER + #include "atari/plot/font_vdi.h" +#endif +#ifdef WITH_INTERNAL_FONT_DRIVER + #include "atari/plot/font_internal.h" +#endif +#ifdef WITH_FREETYPE_FONT_DRIVER + #include "atari/plot/font_freetype.h" +#endif + + + +#endif diff --git a/frontends/atari/plot/plot.c b/frontends/atari/plot/plot.c new file mode 100644 index 000000000..45e4cead2 --- /dev/null +++ b/frontends/atari/plot/plot.c @@ -0,0 +1,2247 @@ +/* + * Copyright 2010 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <assert.h> +#include <sys/types.h> +#include <stdint.h> +#include <string.h> +#include <limits.h> +#include <math.h> +#include <stdbool.h> +#include <mt_gem.h> +#include <mint/osbind.h> + +#include "utils/log.h" +#include "utils/utf8.h" +#include "utils/utils.h" +#include "image/bitmap.h" +#include "desktop/plotters.h" +#include "desktop/mouse.h" + +#include "atari/gui.h" +#include "atari/osspec.h" +#include "atari/misc.h" +#include "atari/bitmap.h" +#include "utils/nsoption.h" +#include "atari/plot/eddi.h" +#include "atari/plot/fontplot.h" +#include "atari/plot/plot.h" + +void vq_scrninfo(VdiHdl handle, short *work_out); + +struct s_view { + short x; /* drawing (screen) offset x */ + short y; /* drawing (screen) offset y */ + short w; /* width of buffer, not in sync with vis_w */ + short h; /* height of buffer, not in sync with vis_w */ + short vis_x; /* visible rectangle of the screen buffer */ + short vis_y; /* coords are relative to plot location */ + short vis_w; /* clipped to screen dimensions */ + short vis_h; /* visible width */ + struct rect abs_clipping; /* The toplevel clipping rectangle */ + struct rect clipping; /* actual clipping rectangle */ + float scale; +}; + +/* +* Capture the screen at x,y location +* param self instance +* param x absolute screen coords +* param y absolute screen coords +* param w width +* param h height +* +* This creates an snapshot in RGBA format (NetSurf's native format) +* +*/ +static struct bitmap * snapshot_create(int x, int y, int w, int h); + +/* Garbage collection of the snapshot routine */ +/* this should be called after you are done with the data returned by snapshot_create */ +/* don't access the screenshot after you called this function */ +static void snapshot_suspend(void); + +/* destroy memory used by screenshot */ +static void snapshot_destroy(void); + +#ifdef WITH_8BPP_SUPPORT +static unsigned short sys_pal[256][3]; /*RGB*/ +static unsigned short pal[256][3]; /*RGB*/ +static char rgb_lookup[256][4]; +short web_std_colors[6] = {0, 51, 102, 153, 204, 255}; + +unsigned short vdi_web_pal[216][3] = { + {0x000,0x000,0x000}, {0x0c8,0x000,0x000}, {0x190,0x000,0x000}, {0x258,0x000,0x000}, {0x320,0x000,0x000}, {0x3e8,0x000,0x000}, + {0x000,0x0c8,0x000}, {0x0c8,0x0c8,0x000}, {0x190,0x0c8,0x000}, {0x258,0x0c8,0x000}, {0x320,0x0c8,0x000}, {0x3e8,0x0c8,0x000}, + {0x000,0x190,0x000}, {0x0c8,0x190,0x000}, {0x190,0x190,0x000}, {0x258,0x190,0x000}, {0x320,0x190,0x000}, {0x3e8,0x190,0x000}, + {0x000,0x258,0x000}, {0x0c8,0x258,0x000}, {0x190,0x258,0x000}, {0x258,0x258,0x000}, {0x320,0x258,0x000}, {0x3e8,0x258,0x000}, + {0x000,0x320,0x000}, {0x0c8,0x320,0x000}, {0x190,0x320,0x000}, {0x258,0x320,0x000}, {0x320,0x320,0x000}, {0x3e8,0x320,0x000}, + {0x000,0x3e8,0x000}, {0x0c8,0x3e8,0x000}, {0x190,0x3e8,0x000}, {0x258,0x3e8,0x000}, {0x320,0x3e8,0x000}, {0x3e8,0x3e8,0x000}, + {0x000,0x000,0x0c8}, {0x0c8,0x000,0x0c8}, {0x190,0x000,0x0c8}, {0x258,0x000,0x0c8}, {0x320,0x000,0x0c8}, {0x3e8,0x000,0x0c8}, + {0x000,0x0c8,0x0c8}, {0x0c8,0x0c8,0x0c8}, {0x190,0x0c8,0x0c8}, {0x258,0x0c8,0x0c8}, {0x320,0x0c8,0x0c8}, {0x3e8,0x0c8,0x0c8}, + {0x000,0x190,0x0c8}, {0x0c8,0x190,0x0c8}, {0x190,0x190,0x0c8}, {0x258,0x190,0x0c8}, {0x320,0x190,0x0c8}, {0x3e8,0x190,0x0c8}, + {0x000,0x258,0x0c8}, {0x0c8,0x258,0x0c8}, {0x190,0x258,0x0c8}, {0x258,0x258,0x0c8}, {0x320,0x258,0x0c8}, {0x3e8,0x258,0x0c8}, + {0x000,0x320,0x0c8}, {0x0c8,0x320,0x0c8}, {0x190,0x320,0x0c8}, {0x258,0x320,0x0c8}, {0x320,0x320,0x0c8}, {0x3e8,0x320,0x0c8}, + {0x000,0x3e8,0x0c8}, {0x0c8,0x3e8,0x0c8}, {0x190,0x3e8,0x0c8}, {0x258,0x3e8,0x0c8}, {0x320,0x3e8,0x0c8}, {0x3e8,0x3e8,0x0c8}, + {0x000,0x000,0x190}, {0x0c8,0x000,0x190}, {0x190,0x000,0x190}, {0x258,0x000,0x190}, {0x320,0x000,0x190}, {0x3e8,0x000,0x190}, + {0x000,0x0c8,0x190}, {0x0c8,0x0c8,0x190}, {0x190,0x0c8,0x190}, {0x258,0x0c8,0x190}, {0x320,0x0c8,0x190}, {0x3e8,0x0c8,0x190}, + {0x000,0x190,0x190}, {0x0c8,0x190,0x190}, {0x190,0x190,0x190}, {0x258,0x190,0x190}, {0x320,0x190,0x190}, {0x3e8,0x190,0x190}, + {0x000,0x258,0x190}, {0x0c8,0x258,0x190}, {0x190,0x258,0x190}, {0x258,0x258,0x190}, {0x320,0x258,0x190}, {0x3e8,0x258,0x190}, + {0x000,0x320,0x190}, {0x0c8,0x320,0x190}, {0x190,0x320,0x190}, {0x258,0x320,0x190}, {0x320,0x320,0x190}, {0x3e8,0x320,0x190}, + {0x000,0x3e8,0x190}, {0x0c8,0x3e8,0x190}, {0x190,0x3e8,0x190}, {0x258,0x3e8,0x190}, {0x320,0x3e8,0x190}, {0x3e8,0x3e8,0x190}, + {0x000,0x000,0x258}, {0x0c8,0x000,0x258}, {0x190,0x000,0x258}, {0x258,0x000,0x258}, {0x320,0x000,0x258}, {0x3e8,0x000,0x258}, + {0x000,0x0c8,0x258}, {0x0c8,0x0c8,0x258}, {0x190,0x0c8,0x258}, {0x258,0x0c8,0x258}, {0x320,0x0c8,0x258}, {0x3e8,0x0c8,0x258}, + {0x000,0x190,0x258}, {0x0c8,0x190,0x258}, {0x190,0x190,0x258}, {0x258,0x190,0x258}, {0x320,0x190,0x258}, {0x3e8,0x190,0x258}, + {0x000,0x258,0x258}, {0x0c8,0x258,0x258}, {0x190,0x258,0x258}, {0x258,0x258,0x258}, {0x320,0x258,0x258}, {0x3e8,0x258,0x258}, + {0x000,0x320,0x258}, {0x0c8,0x320,0x258}, {0x190,0x320,0x258}, {0x258,0x320,0x258}, {0x320,0x320,0x258}, {0x3e8,0x320,0x258}, + {0x000,0x3e8,0x258}, {0x0c8,0x3e8,0x258}, {0x190,0x3e8,0x258}, {0x258,0x3e8,0x258}, {0x320,0x3e8,0x258}, {0x3e8,0x3e8,0x258}, + {0x000,0x000,0x320}, {0x0c8,0x000,0x320}, {0x190,0x000,0x320}, {0x258,0x000,0x320}, {0x320,0x000,0x320}, {0x3e8,0x000,0x320}, + {0x000,0x0c8,0x320}, {0x0c8,0x0c8,0x320}, {0x190,0x0c8,0x320}, {0x258,0x0c8,0x320}, {0x320,0x0c8,0x320}, {0x3e8,0x0c8,0x320}, + {0x000,0x190,0x320}, {0x0c8,0x190,0x320}, {0x190,0x190,0x320}, {0x258,0x190,0x320}, {0x320,0x190,0x320}, {0x3e8,0x190,0x320}, + {0x000,0x258,0x320}, {0x0c8,0x258,0x320}, {0x190,0x258,0x320}, {0x258,0x258,0x320}, {0x320,0x258,0x320}, {0x3e8,0x258,0x320}, + {0x000,0x320,0x320}, {0x0c8,0x320,0x320}, {0x190,0x320,0x320}, {0x258,0x320,0x320}, {0x320,0x320,0x320}, {0x3e8,0x320,0x320}, + {0x000,0x3e8,0x320}, {0x0c8,0x3e8,0x320}, {0x190,0x3e8,0x320}, {0x258,0x3e8,0x320}, {0x320,0x3e8,0x320}, {0x3e8,0x3e8,0x320}, + {0x000,0x000,0x3e8}, {0x0c8,0x000,0x3e8}, {0x190,0x000,0x3e8}, {0x258,0x000,0x3e8}, {0x320,0x000,0x3e8}, {0x3e8,0x000,0x3e8}, + {0x000,0x0c8,0x3e8}, {0x0c8,0x0c8,0x3e8}, {0x190,0x0c8,0x3e8}, {0x258,0x0c8,0x3e8}, {0x320,0x0c8,0x3e8}, {0x3e8,0x0c8,0x3e8}, + {0x000,0x190,0x3e8}, {0x0c8,0x190,0x3e8}, {0x190,0x190,0x3e8}, {0x258,0x190,0x3e8}, {0x320,0x190,0x3e8}, {0x3e8,0x190,0x3e8}, + {0x000,0x258,0x3e8}, {0x0c8,0x258,0x3e8}, {0x190,0x258,0x3e8}, {0x258,0x258,0x3e8}, {0x320,0x258,0x3e8}, {0x3e8,0x258,0x3e8}, + {0x000,0x320,0x3e8}, {0x0c8,0x320,0x3e8}, {0x190,0x320,0x3e8}, {0x258,0x320,0x3e8}, {0x320,0x320,0x3e8}, {0x3e8,0x320,0x3e8}, + {0x000,0x3e8,0x3e8}, {0x0c8,0x3e8,0x3e8}, {0x190,0x3e8,0x3e8}, {0x258,0x3e8,0x3e8}, {0x320,0x3e8,0x3e8}, {0x3e8,0x3e8,0x3e8} +}; +#endif + +/* Error code translations: */ +static const char * plot_error_codes[] = { + "None", + "ERR_BUFFERSIZE_EXCEEDS_SCREEN", + "ERR_NO_MEM", + "ERR_PLOTTER_NOT_AVAILABLE" +}; + +FONT_PLOTTER fplotter = NULL; + +extern short vdih; + +/* temp buffer for bitmap conversion: */ +static void * buf_packed; +static int size_buf_packed; + +/* temp buffer for bitmap conversion: */ +void * buf_planar; +int size_buf_planar; + +/* buffer for plot operations that require device format, */ +/* currently used for transparent mfdb blits and snapshots: */ +static MFDB buf_scr; +static int size_buf_scr; + +/* buffer for std form, used during 8bpp snapshot */ +MFDB buf_std; +int size_buf_std; + +struct bitmap * buf_scr_compat; + +/* intermediate bitmap format */ +static HermesFormat vfmt; + +/* no screen format here, hermes may not suitable for it */ + +/* netsurf source bitmap format */ +static HermesFormat nsfmt; + +struct s_vdi_sysinfo vdi_sysinfo; +/* bit depth of framebuffers: */ +static int atari_plot_bpp_virt; +static struct s_view view; + +//static HermesHandle hermes_pal_h; /* hermes palette handle */ +static HermesHandle hermes_cnv_h; /* hermes converter instance handle */ +static HermesHandle hermes_res_h; + +//static short prev_vdi_clip[4]; +static struct bitmap snapshot; + +VdiHdl atari_plot_vdi_handle = -1; +unsigned long atari_plot_flags; +unsigned long atari_font_flags; + +typedef bool (*bitmap_convert_fnc)( struct bitmap * img, int x, int y, + GRECT * clip, uint32_t bg, uint32_t flags, MFDB *out ); +static bitmap_convert_fnc bitmap_convert; + +const char* plot_err_str(int i) +{ + return(plot_error_codes[abs(i)]); +} + +/** + * Set line drawing color by passing netsurf XBGR "colour" type. + * + * \param vdih The vdi handle + * \param cin The netsurf colour value + */ +inline static void vsl_rgbcolor(short vdih, colour cin) +{ + #ifdef WITH_8BPP_SUPPORT + if( vdi_sysinfo.scr_bpp > 8 ) { + #endif + RGB1000 c; /* a struct with three (RGB) shorts */ + rgb_to_vdi1000( (unsigned char*)&cin, &c); + vs_color(vdih, OFFSET_CUSTOM_COLOR, (short *)&c); + vsl_color(vdih, OFFSET_CUSTOM_COLOR); + #ifdef WITH_8BPP_SUPPORT + } else { + if( vdi_sysinfo.scr_bpp >= 4 ){ + vsl_color(vdih, RGB_TO_VDI(cin)); + } + else + vsl_color(vdih, BLACK); + } + #endif +} + +/** + * Set fill color by passing netsurf XBGR "colour" type. + * + * \param vdih The vdi handle + * \param cin The netsurf colour value + */ +inline static void vsf_rgbcolor(short vdih, colour cin) +{ + #ifdef WITH_8BPP_SUPPORT + if( vdi_sysinfo.scr_bpp > 8 ) { + #endif + RGB1000 c; /* a struct with three (RGB) shorts */ + rgb_to_vdi1000( (unsigned char*)&cin, &c); + vs_color( vdih, OFFSET_CUSTOM_COLOR, (short *)&c); + vsf_color( vdih, OFFSET_CUSTOM_COLOR ); + #ifdef WITH_8BPP_SUPPORT + } else { + if( vdi_sysinfo.scr_bpp >= 4 ){ + vsf_color( vdih, RGB_TO_VDI(cin) ); + } + else + vsf_color( vdih, WHITE ); + } + #endif +} + + + +/** + * Get current visible coords + */ +inline static void plot_get_visible_grect(GRECT * out) +{ + out->g_x = view.vis_x; + out->g_y = view.vis_y; + out->g_w = view.vis_w; + out->g_h = view.vis_h; +} + + + +/* calculate visible area of framebuffer in coords relative to framebuffer */ +/* position */ +/* result: */ +/* this function should calculates an rectangle relative to the plot origin*/ +/* and size. */ +/* If the ploter coords do not fall within the screen region, */ +/* all values of the region are set to zero. */ +inline static void update_visible_rect(void) +{ + GRECT screen; // dimensions of the screen + GRECT frame; // dimensions of the drawing area + GRECT common; // dimensions of intersection of both + + screen.g_x = 0; + screen.g_y = 0; + screen.g_w = vdi_sysinfo.scr_w; + screen.g_h = vdi_sysinfo.scr_h; + + common.g_x = frame.g_x = view.x; + common.g_y = frame.g_y = view.y; + common.g_w = frame.g_w = view.w; + common.g_h = frame.g_h = view.h; + + if (rc_intersect(&screen, &common)) { + view.vis_w = common.g_w; + view.vis_h = common.g_h; + if (view.x < screen.g_x) + view.vis_x = frame.g_w - common.g_w; + else + view.vis_x = 0; + if (view.y <screen.g_y) + view.vis_y = frame.g_h - common.g_h; + else + view.vis_y = 0; + } else { + view.vis_w = view.vis_h = 0; + view.vis_x = view.vis_y = 0; + } +} + +/* Returns the visible parts of the box (relative coords within framebuffer),*/ +/* relative to screen coords (normally starting at 0,0 ) */ +inline static bool fbrect_to_screen(GRECT box, GRECT * ret) +{ + GRECT out, vis, screen; + + screen.g_x = 0; + screen.g_y = 0; + screen.g_w = vdi_sysinfo.scr_w; + screen.g_h = vdi_sysinfo.scr_h; + + /* get visible region: */ + vis.g_x = view.x; + vis.g_y = view.y; + vis.g_w = view.w; + vis.g_h = view.h; + + if ( !rc_intersect( &screen, &vis ) ) { + return( false ); + } + vis.g_x = view.w - vis.g_w; + vis.g_y = view.h - vis.g_h; + + /* clip box to visible region: */ + if( !rc_intersect(&vis, &box) ) { + return( false ); + } + out.g_x = box.g_x + view.x; + out.g_y = box.g_y + view.y; + out.g_w = box.g_w; + out.g_h = box.g_h; + *ret = out; + return ( true ); +} + +/* copy an rectangle from the plot buffer to screen */ +/* because this is an on-screen plotter, this is an screen to screen copy. */ +bool plot_copy_rect(GRECT src, GRECT dst) +{ + MFDB devmf; + MFDB scrmf; + short pxy[8]; + GRECT vis; + + /* clip to visible rect, only needed for onscreen renderer: */ + plot_get_visible_grect(&vis ); + + if( !rc_intersect(&vis, &src) ) + return(true); + if( !rc_intersect(&vis, &dst) ) + return(true); + + src.g_x = view.x + src.g_x; + src.g_y = view.y + src.g_y; + dst.g_x = view.x + dst.g_x; + dst.g_y = view.y + dst.g_y; + + devmf.fd_addr = NULL; + devmf.fd_w = src.g_w; + devmf.fd_h = src.g_h; + devmf.fd_wdwidth = 0; + devmf.fd_stand = 0; + devmf.fd_nplanes = 0; + devmf.fd_r1 = devmf.fd_r2 = devmf.fd_r3 = 0; + + scrmf.fd_addr = NULL; + scrmf.fd_w = dst.g_w; + scrmf.fd_h = dst.g_h; + scrmf.fd_wdwidth = 0 ; + scrmf.fd_stand = 0; + scrmf.fd_nplanes = 0; + scrmf.fd_r1 = scrmf.fd_r2 = scrmf.fd_r3 = 0; + + pxy[0] = src.g_x; + pxy[1] = src.g_y; + pxy[2] = pxy[0] + src.g_w-1; + pxy[3] = pxy[1] + src.g_h-1; + pxy[4] = dst.g_x; + pxy[5] = dst.g_y; + pxy[6] = pxy[4] + dst.g_w-1; + pxy[7] = pxy[5] + dst.g_h-1; + plot_lock(); + vro_cpyfm( atari_plot_vdi_handle, S_ONLY, (short*)&pxy, &devmf, &scrmf); + plot_unlock(); + + return(true); +} + +/** + * Fill the screen info structure. + * + * \param vdhi The handle + * \param[out] info The infor structure to fill. + */ +static void read_vdi_sysinfo(short vdih, struct s_vdi_sysinfo * info) { + + unsigned long cookie_EdDI=0; /** \todo this long is being cast to a pointer */ + short out[300]; + memset( info, 0, sizeof(struct s_vdi_sysinfo) ); + + info->vdi_handle = vdih; + if ( tos_getcookie(C_EdDI, (long *)&cookie_EdDI) == C_NOTFOUND ) { + info->EdDiVersion = 0; + } else { + info->EdDiVersion = EdDI_version( (void *)cookie_EdDI ); + } + + memset( &out, 0, sizeof(short)*300 ); + vq_extnd( vdih, 0, (short*)&out ); + info->scr_w = out[0]+1; + info->scr_h = out[1]+1; + if( out[39] == 2 ) { + info->scr_bpp = 1; + info->colors = out[39]; + } else { + info->colors = out[39]; + } + + memset( &out, 0, sizeof(short)*300 ); + vq_extnd( vdih, 1, (short*)&out ); + info->scr_bpp = out[4]; + info->maxpolycoords = out[14]; + info->maxintin = out[15]; + if( out[30] & 1 ) { + info->rasterscale = true; + } else { + info->rasterscale = false; + } + + switch( info->scr_bpp ) { + case 8: + info->pixelsize=1; + break; + case 15: + case 16: + info->pixelsize=2; + break; + case 24: + info->pixelsize=3; + break; + case 32: + info->pixelsize=4; + break; + case 64: + info->pixelsize=8; + break; + default: + info->pixelsize=1; + break; + + } + info->pitch = info->scr_w * info->pixelsize; + info->vdiformat = ( (info->scr_bpp <= 8) ? VDI_FORMAT_INTER : VDI_FORMAT_PACK); + info->screensize = ( info->scr_w * info->pixelsize ) * info->scr_h; + + if( info->EdDiVersion >= EDDI_10 ) { + memset( &out, 0, sizeof(short)*300 ); + vq_scrninfo(vdih, (short*)&out); + info->vdiformat = out[0]; + info->clut = out[1]; + info->scr_bpp = out[2]; + info->hicolors = *((unsigned long*) &out[3]); + if( info->EdDiVersion >= EDDI_11 ) { + info->pitch = out[5]; + info->screen = (void *) *((unsigned long *) &out[6]); + } + + switch( info->clut ) { + + case VDI_CLUT_HARDWARE: { + + } + break; + + case VDI_CLUT_SOFTWARE: { + int component; /* red, green, blue, alpha, overlay */ + int num_bit; + unsigned short *tmp_p; + + /* We can build masks with info here */ + tmp_p = (unsigned short *) &out[16]; + for (component=0; component<5; component++) { + for (num_bit=0; num_bit<16; num_bit++) { + unsigned short val; + + val = *tmp_p++; + + if (val == 0xffff) { + continue; + } + + switch(component) { + case 0: + info->mask_r |= 1<< val; + break; + case 1: + info->mask_g |= 1<< val; + break; + case 2: + info->mask_b |= 1<< val; + break; + case 3: + info->mask_a |= 1<< val; + break; + } + } + } + } + + /* Remove lower green bits for Intel endian screen */ + if ((info->mask_g == ((7<<13)|3)) || (info->mask_g == ((7<<13)|7))) { + info->mask_g &= ~(7<<13); + } + break; + + case VDI_CLUT_NONE: + break; + } + } +} + + +/* + Convert an RGB color to an VDI Color +*/ +inline void rgb_to_vdi1000(unsigned char * in, RGB1000 *out) +{ + double r = ((double)in[3]/255); /* prozentsatz red */ + double g = ((double)in[2]/255); /* prozentsatz green */ + double b = ((double)in[1]/255); /* prozentsatz blue */ + out->red = 1000 * r + 0.5; + out->green = 1000 * g + 0.5; + out->blue = 1000 * b + 0.5; + return; +} + +inline void vdi1000_to_rgb(unsigned short * in, unsigned char * out) +{ + double r = ((double)in[0]/1000); /* prozentsatz red */ + double g = ((double)in[1]/1000); /* prozentsatz green */ + double b = ((double)in[2]/1000); /* prozentsatz blue */ + out[2] = 255 * r + 0.5; + out[1] = 255 * g + 0.5; + out[0] = 255 * b + 0.5; + return; +} + + +#ifdef WITH_8BPP_SUPPORT +/** + * Set pixel within an 8 bit VDI standard bitmap. + */ +inline static void set_stdpx( MFDB * dst, int wdplanesz, int x, int y, unsigned char val ) +{ + short * buf; + short whichbit = (1<<(15-(x%16))); + + buf = dst->fd_addr; + buf += ((dst->fd_wdwidth*(y))+(x>>4)); + + *buf = (val&1) ? ((*buf)|(whichbit)) : ((*buf)&~(whichbit)); + + buf += wdplanesz; + *buf = (val&(1<<1)) ? ((*buf)|(whichbit)) : ((*buf)&~(whichbit)); + + buf += wdplanesz; + *buf = (val&(1<<2)) ? ((*buf)|(whichbit)) : ((*buf)&~(whichbit)); + + buf += wdplanesz; + *buf = (val&(1<<3)) ? ((*buf)|(whichbit)) : ((*buf)&~(whichbit)); + + buf += wdplanesz; + *buf = (val&(1<<4)) ? ((*buf)|(whichbit)) : ((*buf)&~(whichbit)); + + buf += wdplanesz; + *buf = (val&(1<<5)) ? ((*buf)|(whichbit)) : ((*buf)&~(whichbit)); + + buf += wdplanesz; + *buf = (val&(1<<6)) ? ((*buf)|(whichbit)) : ((*buf)&~(whichbit)); + + buf += wdplanesz; + *buf = (val&(1<<7)) ? ((*buf)|(whichbit)) : ((*buf)&~(whichbit)); +} + +/** + * Read pixel from an 8 bit VDI standard bitmap. + */ +inline static unsigned char get_stdpx(MFDB * dst, int wdplanesz, int x, int y) +{ + unsigned char ret=0; + short * buf; + short whichbit = (1<<(15-(x%16))); + + buf = dst->fd_addr; + buf += ((dst->fd_wdwidth*(y))+(x>>4)); + + if( *buf & whichbit ) + ret |= 1; + + buf += wdplanesz; + if( *buf & whichbit ) + ret |= 2; + + buf += wdplanesz; + if( *buf & whichbit ) + ret |= 4; + + buf += wdplanesz; + if( *buf & whichbit ) + ret |= 8; + + buf += wdplanesz; + if( *buf & whichbit ) + ret |= 16; + + buf += wdplanesz; + if( *buf & whichbit ) + ret |= 32; + + buf += wdplanesz; + if( *buf & whichbit ) + ret |= 64; + + buf += wdplanesz; + if( *buf & whichbit ) + ret |= 128; + + return( ret ); +} + +/* + Convert an RGB color into an index into the 216 colors web pallette +*/ +inline short rgb_to_666_index(unsigned char r, unsigned char g, unsigned char b) +{ + short i; + unsigned char rgb[3] = {r,g,b}; + unsigned char tval[3]; + + int diff_a, diff_b, diff_c; + diff_a = abs(r-g); + diff_b = abs(r-b); + diff_c = abs(r-b); + if( diff_a < 2 && diff_b < 2 && diff_c < 2 ) { + if( (r!=0XFF) && (g!=0XFF) && (b!=0XFF) ) { + if( ((r&0xF0)>>4) != 0 ) + //printf("conv gray: %x -> %d\n", ((r&0xF0)>>4) , (OFFSET_CUST_PAL) + ((r&0xF0)>>4) ); + return( (OFFSET_CUST_PAL - OFFSET_WEB_PAL) + ((r&0xF0)>>4) ); + } + } + + /* convert each 8bit color to 6bit web color: */ + for( i=0; i<3; i++) { + if(0 == rgb[i] % web_std_colors[1] ) { + tval[i] = rgb[i] / web_std_colors[1]; + } else { + int pos = ((short)rgb[i] / web_std_colors[1]); + if( abs(rgb[i] - web_std_colors[pos]) > abs(rgb[i] - web_std_colors[pos+1]) ) + tval[i] = pos+1; + else + tval[i] = pos; + } + } + return(tval[2]*36+tval[1]*6+tval[0]); +} +#endif + + +static void dump_vdi_info(short vdih) +{ + struct s_vdi_sysinfo temp; + read_vdi_sysinfo( vdih, &temp ); + printf("struct s_vdi_sysinfo {\n"); + printf(" short vdi_handle: %d\n", temp.vdi_handle); + printf(" short scr_w: %d \n", temp.scr_w); + printf(" short scr_h: %d\n", temp.scr_h); + printf(" short scr_bpp: %d\n", temp.scr_bpp); + printf(" int colors: %d\n", temp.colors); + printf(" ulong hicolors: %lu\n", temp.hicolors); + printf(" short pixelsize: %d\n", temp.pixelsize); + printf(" unsigned short pitch: %d\n", temp.pitch); + printf(" unsigned short vdiformat: %d\n", temp.vdiformat); + printf(" unsigned short clut: %d\n", temp.clut); + printf(" void * screen: 0x0%p\n", temp.screen); + printf(" unsigned long screensize: %lu\n", temp.screensize); + printf(" unsigned long mask_r: 0x0%08lx\n", temp.mask_r); + printf(" unsigned long mask_g: 0x0%08lx\n", temp.mask_g); + printf(" unsigned long mask_b: 0x0%08lx\n", temp.mask_b); + printf(" unsigned long mask_a: 0x0%08lx\n", temp.mask_a); + printf(" short maxintin: %d\n", temp.maxintin); + printf(" short maxpolycoords: %d\n", temp.maxpolycoords); + printf(" unsigned long EdDiVersion: 0x0%03lx\n", temp.EdDiVersion); + printf(" unsigned short rasterscale: 0x%2x\n", temp.rasterscale); + printf("};\n"); +} + +/** + * Create an snapshot of the screen image in device format. + */ +static MFDB * snapshot_create_native_mfdb(int x, int y, int w, int h) +{ + MFDB scr; + short pxy[8]; + + /* allocate memory for the snapshot */ + { + int scr_stride = MFDB_STRIDE( w ); + int scr_size = ( ((scr_stride >> 3) * h) * vdi_sysinfo.scr_bpp ); + if(size_buf_scr == 0 ){ + /* init screen mfdb */ + buf_scr.fd_addr = malloc( scr_size ); + size_buf_scr = scr_size; + } else { + if( scr_size >size_buf_scr ) { + buf_scr.fd_addr = realloc( + buf_scr.fd_addr, scr_size + ); + size_buf_scr = scr_size; + } + } + if(buf_scr.fd_addr == NULL ) { + size_buf_scr = 0; + return( NULL ); + } + buf_scr.fd_nplanes = vdi_sysinfo.scr_bpp; + buf_scr.fd_w = scr_stride; + buf_scr.fd_h = h; + buf_scr.fd_wdwidth = scr_stride >> 4; + assert(buf_scr.fd_addr != NULL ); + } + init_mfdb( 0, w, h, 0, &scr ); + pxy[0] = x; + pxy[1] = y; + pxy[2] = pxy[0] + w-1; + pxy[3] = pxy[1] + h-1; + pxy[4] = 0; + pxy[5] = 0; + pxy[6] = w-1; + pxy[7] = h-1; + vro_cpyfm( + atari_plot_vdi_handle, S_ONLY, (short*)&pxy, + &scr, &buf_scr + ); + + return( &buf_scr ); +} + +/** + * Create an snapshot of the screen image in VDI standard format (8 bit). + */ +static MFDB * snapshot_create_std_mfdb(int x, int y, int w, int h) +{ + /* allocate memory for the snapshot */ + { + int scr_stride = MFDB_STRIDE( w ); + int scr_size = ( ((scr_stride >> 3) * h) * vdi_sysinfo.scr_bpp ); + if(size_buf_std == 0 ){ + /* init screen mfdb */ + buf_std.fd_addr = malloc( scr_size ); + size_buf_std = scr_size; + } else { + if( scr_size >size_buf_std ) { + buf_std.fd_addr = realloc( + buf_std.fd_addr, scr_size + ); + size_buf_std = scr_size; + } + } + if(buf_std.fd_addr == NULL ) { + size_buf_std = 0; + return( NULL ); + } + buf_std.fd_nplanes = 8; + buf_std.fd_w = scr_stride; + buf_std.fd_h = h; + buf_std.fd_stand = 1; + buf_std.fd_wdwidth = scr_stride >> 4; + assert(buf_std.fd_addr != NULL ); + } + MFDB * native = snapshot_create_native_mfdb(x,y,w,h ); + assert( native ); + + vr_trnfm(atari_plot_vdi_handle, native, &buf_std); + return( &buf_std ); +} + +/* + * Create an snapshot of the screen in netsurf ABGR format + */ +static struct bitmap * snapshot_create(int x, int y, int w, int h) +{ + int err; + MFDB * native; + // uint32_t start = clock(); + + // FIXME: This can be optimized a lot. + // 1. do not copy the snapshot to the bitmap buffer + // when the format of screen and bitmap equals. + // just point the bitmap to the native mfdb. + // 2. if we have eddi 1.1, we could optimize that further + // make snapshot_create_native_mfdb just returning a pointer + // to the screen. + + native = snapshot_create_native_mfdb(x, y, w, h ); + + if(vfmt.bits == 32 ) + goto no_copy; + + /* allocate buffer for result bitmap: */ + if(buf_scr_compat == NULL ) { + buf_scr_compat = atari_bitmap_create(w, h, 0); + } else { + buf_scr_compat = atari_bitmap_realloc( w, h, + buf_scr_compat->bpp, + w *buf_scr_compat->bpp, + BITMAP_GROW, + buf_scr_compat ); + } + + /* convert screen buffer to ns format: */ + err = Hermes_ConverterRequest( hermes_cnv_h, + &vfmt, + &nsfmt + ); + assert( err != 0 ); + err = Hermes_ConverterCopy( hermes_cnv_h, + native->fd_addr, + 0, /* x src coord of top left in pixel coords */ + 0, /* y src coord of top left in pixel coords */ + w, h, + native->fd_w * vdi_sysinfo.pixelsize, /* stride as bytes */ + buf_scr_compat->pixdata, + 0, /* x dst coord of top left in pixel coords */ + 0, /* y dst coord of top left in pixel coords */ + w, h, + atari_bitmap_get_rowstride(buf_scr_compat) /* stride as bytes */ + ); + assert( err != 0 ); + return( (struct bitmap * )buf_scr_compat ); + +no_copy: + + snapshot.width = w; + snapshot.height = h; + snapshot.pixdata = native->fd_addr; + snapshot.native = *native; + snapshot.rowstride = MFDB_STRIDE( w )*4; + + uint32_t row, col; + for (row = 0; row<(uint32_t)h; row++) { + // fd_w matches stride! + uint32_t *rowptr = ((uint32_t*)native->fd_addr + ((row*native->fd_w))); + for (col=0; col<(uint32_t)w; col++) { + *(rowptr+col) = (*(rowptr+col)<<8); + } + } + return( &snapshot ); +} + +/** + * Notify the snapshot interface that the last snapshot is no longer in use. + */ +static void snapshot_suspend(void) +{ + if(size_buf_scr > CONV_KEEP_LIMIT ) { + buf_scr.fd_addr = realloc( + buf_scr.fd_addr, CONV_KEEP_LIMIT + ); + if(buf_scr.fd_addr != NULL ) { + size_buf_scr = CONV_KEEP_LIMIT; + } else { + size_buf_scr = 0; + } + } + +#ifdef WITH_8BPP_SUPPORT + if(size_buf_std > CONV_KEEP_LIMIT ) { + buf_std.fd_addr = realloc( + buf_std.fd_addr, CONV_KEEP_LIMIT + ); + if(buf_std.fd_addr != NULL ) { + size_buf_std = CONV_KEEP_LIMIT; + } else { + size_buf_std = 0; + } + } +#endif + + if(buf_scr_compat != NULL ) { + size_t bs = atari_bitmap_buffer_size(buf_scr_compat ); + if( bs > CONV_KEEP_LIMIT ) { + int w = 0; + int h = 1; + w = (CONV_KEEP_LIMIT /buf_scr_compat->bpp); + assert( CONV_KEEP_LIMIT == w*buf_scr_compat->bpp ); + buf_scr_compat = atari_bitmap_realloc( w, h, + buf_scr_compat->bpp, + CONV_KEEP_LIMIT, BITMAP_SHRINK,buf_scr_compat + ); + } + } +} + +/** + * Shut down the snapshot interface. + */ +static void snapshot_destroy(void) +{ + + free(buf_scr.fd_addr); + if( buf_scr_compat != NULL) { + atari_bitmap_destroy(buf_scr_compat); + } + + buf_scr.fd_addr = NULL; + buf_scr_compat = NULL; + +#ifdef WITH_8BPP_SUPPORT + free(buf_std.fd_addr); + buf_std.fd_addr = NULL; +#endif +} + + +inline static uint32_t ablend(uint32_t pixel, uint32_t scrpixel) +{ + int opacity = pixel & 0xFF; + int transp = 0x100 - opacity; + uint32_t rb, g; + pixel >>= 8; + scrpixel >>= 8; + rb = ((pixel & 0xFF00FF) * opacity + + (scrpixel & 0xFF00FF) * transp) >> 8; + g = ((pixel & 0x00FF00) * opacity + + (scrpixel & 0x00FF00) * transp) >> 8; + + return ((rb & 0xFF00FF) | (g & 0xFF00)) << 8; +} + +/* + Alpha blends an image, using one pixel as the background. + The bitmap receives the result. +*/ +inline static bool ablend_pixel(struct bitmap * img, uint32_t bg, GRECT * clip) +{ + uint32_t * imgrow; + int img_x, img_y, img_stride; + + img_stride= atari_bitmap_get_rowstride(img); + + for( img_y = 0; img_y < clip->g_h; img_y++) { + imgrow = (uint32_t *)(img->pixdata + (img_stride * img_y)); + for( img_x = 0; img_x < clip->g_w; img_x++ ) { + imgrow[img_x] = ablend( imgrow[img_x], bg ); + } + } + return(true); +} + + +/* + Aplha blends the foreground image (img) onto the + background images (bg). The background receives the blended + image pixels. +*/ +inline static bool ablend_bitmap( struct bitmap * img, struct bitmap * bg, + GRECT * img_clip, GRECT * bg_clip ) +{ + uint32_t * imgrow; + uint32_t * screenrow; + int img_x, img_y, bg_x, bg_y, img_stride, bg_stride; + + bg_clip = bg_clip; + img_stride = atari_bitmap_get_rowstride(img); + bg_stride = atari_bitmap_get_rowstride(bg); + + for( img_y = img_clip->g_y, bg_y = 0; bg_y < img_clip->g_h; bg_y++, img_y++) { + imgrow = (uint32_t *)(img->pixdata + (img_stride * img_y)); + screenrow = (uint32_t *)(bg->pixdata + (bg_stride * bg_y)); + for( img_x = img_clip->g_x, bg_x = 0; bg_x < img_clip->g_w; bg_x++, img_x++ ) { + + // when the pixel isn't fully transparent,...: + if( (imgrow[img_x] & 0x0FF) != 0 ){ + screenrow[bg_x] = ablend( imgrow[img_x], screenrow[bg_x]); + } + + // FIXME, maybe this loop would be faster??: + // --- + //if( (imgrow[img_x] & 0x0FF) != 0xFF ){ + // imgrow[bg_x] = ablend( imgrow[img_x], screenrow[bg_x]); + //} + + // or maybe even this??? + // --- + //if( (imgrow[img_x] & 0x0FF) == 0xFF ){ + // screenrow[bg_x] = imgrow[img_x]; + //} else if( (imgrow[img_x] & 0x0FF) != 0x00 ) { + // screenrow[bg_x] = ablend( imgrow[img_x], screenrow[bg_x]); + //} + } + } + return(false); +} + + +#ifdef WITH_8BPP_SUPPORT +/** + * Convert an bitmap to an 8 bit device dependant MFDB + * \param img the bitmap (only tested with 32bit bitmaps) + * \param x screen coord of the background + * \param y screen coord of the background + * \param clip the region of the image that get's converted + * \param bg the background used for cheap transparency + * \param flags + * \param out receives the converted bitmap (still owned by the plot API) + * + */ +static bool bitmap_convert_8(struct bitmap * img, int x, + int y, GRECT * clip, uint32_t bg, uint32_t flags, + MFDB *out ) +{ + MFDB native; + MFDB stdform; + int dststride; /* stride of dest. image */ + int dstsize; /* size of dest. in byte */ + int bw, bh; + struct bitmap * scrbuf = NULL; + bool cache = ( flags & BITMAPF_BUFFER_NATIVE ); + bool opaque = atari_bitmap_get_opaque( img ); + + if( opaque == false ){ + if( ( (atari_plot_flags & PLOT_FLAG_TRANS) == 0) + && + ((flags & (BITMAPF_MONOGLYPH|BITMAPF_BUFFER_NATIVE))==0) ){ + opaque = true; + } + } + + assert( clip->g_h > 0 ); + assert( clip->g_w > 0 ); + + bw = atari_bitmap_get_width( img ); + bh = atari_bitmap_get_height( img ); + + // The converted bitmap can be saved for subsequent blits, when + // the bitmap is fully opaque + + if( (opaque == true) || (flags & BITMAPF_BUFFER_NATIVE ) ){ + if( img->converted == true ){ + *out = img->native; + return( 0 ); + } + if( ( flags & BITMAPF_MONOGLYPH ) == 0 ){ + cache = true; + } + } + if( ( flags & BITMAPF_MONOGLYPH ) != 0 ){ + assert(cache == false); + } + + /* (re)allocate buffer for out image: */ + /* altough the buffer is named "buf_packed" on 8bit systems */ + /* it's not... */ + if( cache == false ){ + // the size of the output will match the size of the clipping: + dststride = MFDB_STRIDE( clip->g_w ); + dstsize = ( ((dststride >> 3) * clip->g_h) * atari_plot_bpp_virt); + if( dstsize > size_buf_packed) { + int blocks = (dstsize / (CONV_BLOCK_SIZE-1))+1; + if( buf_packed == NULL ) + buf_packed =(void*)malloc( blocks * CONV_BLOCK_SIZE); + else + buf_packed =(void*)realloc(buf_packed,blocks * CONV_BLOCK_SIZE); + assert( buf_packed ); + if( buf_packed == NULL ) { + return( 0-ERR_NO_MEM ); + } + size_buf_packed = blocks * CONV_BLOCK_SIZE; + } + native.fd_addr = buf_packed; + } + else { + // the output image will be completly saved, so size of the output + // image will match the input image size. + dststride = MFDB_STRIDE( bw ); + dstsize = ( ((dststride >> 3) * bh) * atari_plot_bpp_virt); + assert( out->fd_addr == NULL ); + native.fd_addr = (void*)malloc( dstsize ); + if (native.fd_addr == NULL){ + if (scrbuf != NULL) + atari_bitmap_destroy(scrbuf); + return( 0-ERR_NO_MEM ); + } + } + + + /* + on 8 bit systems we must convert the TC (ABGR) image + to vdi standard format. ( only tested for 256 colors ) + and then convert it to native format with v_trnfm() + */ + // realloc mem for stdform + if( opaque == false ){ + // point image to snapshot buffer, otherwise allocate mem + MFDB * bg = snapshot_create_std_mfdb(x, y, clip->g_w, clip->g_h); + stdform.fd_addr = bg->fd_addr; + bh = clip->g_h; + } else { + if( dstsize > size_buf_planar) { + int blocks = (dstsize / (CONV_BLOCK_SIZE-1))+1; + if( buf_planar == NULL ) + buf_planar =(void*)malloc( blocks * CONV_BLOCK_SIZE ); + else + buf_planar =(void*)realloc(buf_planar, blocks * CONV_BLOCK_SIZE); + assert(buf_planar); + if( buf_planar == NULL ) { + return( 0-ERR_NO_MEM ); + } + size_buf_planar = blocks * CONV_BLOCK_SIZE; + } + stdform.fd_addr = buf_planar; + } + stdform.fd_w = dststride; + stdform.fd_h = bh; + stdform.fd_wdwidth = dststride >> 4; + stdform.fd_stand = 1; + stdform.fd_nplanes = (short)atari_plot_bpp_virt; + stdform.fd_r1 = stdform.fd_r2 = stdform.fd_r3 = 0; + + int img_stride = atari_bitmap_get_rowstride(img); + uint32_t prev_pixel = 0x12345678; //TODO: check for collision in first pixel + unsigned long col = 0; + unsigned char val = 0; + uint32_t * row; + uint32_t pixel; + int wdplanesize = stdform.fd_wdwidth*stdform.fd_h; + + if( opaque == false ){ + // apply transparency and convert to vdi std format + unsigned long bgcol = 0; + unsigned char prev_col = 0; + for( y=0; y<clip->g_h; y++ ){ + row = (uint32_t *)(img->pixdata + (img_stride * (y+clip->g_y))); + for( x=0; x<clip->g_w; x++ ){ + pixel = row[x+clip->g_x]; + if( (pixel&0xFF) == 0 ){ + continue; + } + if( (pixel&0xFF) < 0xF0 ){ + col = get_stdpx( &stdform, wdplanesize,x,y ); + if( (col != prev_col) || (y == 0) ) + bgcol = (((rgb_lookup[col][2] << 16) | (rgb_lookup[col][1] << 8) | (rgb_lookup[col][0]))<<8); + if( prev_col != col || prev_pixel != pixel ){ + prev_col = col; + pixel = ablend( pixel, bgcol ); + prev_pixel = pixel; + pixel = pixel >> 8; + /* convert pixel value to vdi color index: */ + col = ( ((pixel&0xFF)<<16) + | (pixel&0xFF00) + | ((pixel&0xFF0000)>>16) ); + val = RGB_TO_VDI( col ); + } + set_stdpx( &stdform, wdplanesize, x, y, val ); + } else { + if( pixel != prev_pixel ){ + /* convert pixel value to vdi color index: */ + pixel = pixel >> 8; + col = ( ((pixel&0xFF)<<16) + | (pixel&0xFF00) + | ((pixel&0xFF0000)>>16) ); + val = RGB_TO_VDI( col ); + prev_pixel = pixel; + } + set_stdpx( &stdform, wdplanesize, x, y, val ); + } + } + } + // adjust output position: + clip->g_x = 0; + clip->g_y = 0; + } else { + // convert the whole image data to vdi std format. + for( y=0; y < bh; y++ ){ + row = (uint32_t *)(img->pixdata + (img_stride * y)); + for( x=0; x < bw; x++ ){ + pixel = row[x]; + if( pixel != prev_pixel ){ + /* convert pixel value to vdi color index: */ + pixel = pixel >> 8; + col = ( ((pixel&0xFF)<<16) + | (pixel&0xFF00) + | ((pixel&0xFF0000)>>16) ); + val = RGB_TO_VDI( col ); + prev_pixel = pixel; + } + set_stdpx( &stdform, wdplanesize, x, y, val ); + } + } + } + + // convert into native format: + native.fd_w = stdform.fd_w; + native.fd_h = stdform.fd_h; + native.fd_wdwidth = stdform.fd_wdwidth; + native.fd_stand = 0; + native.fd_nplanes = (short)atari_plot_bpp_virt; + native.fd_r1 = native.fd_r2 = native.fd_r3 = 0; + vr_trnfm(atari_plot_vdi_handle, &stdform, &native ); + *out = native; + if( cache == true ){ + img->native = native; + img->converted = true; + } + + return(0); +} +#endif + + +/* +* +* Convert bitmap to the native screen format +* img: the bitmap +* x: coordinate where the bitmap REGION (described in clip) +* shall be drawn (screen coords) +* y: coordinate where the bitmap REGION (described in clip) +* shall be drawn (screen coords) +* clip: which area of the bitmap shall be drawn +* bg: background color +* flags: blit flags +* out: the result MFDB +*/ +static bool bitmap_convert_tc(struct bitmap * img, int x, int y, + GRECT * clip, uint32_t bg, uint32_t flags, MFDB *out ) +{ + int dststride; /* stride of dest. image */ + int dstsize; /* size of dest. in byte */ + int err; + int bw, bh; + struct bitmap * scrbuf = NULL; + struct bitmap * source = NULL; + bool cache = ( flags & BITMAPF_BUFFER_NATIVE ); + bool opaque = atari_bitmap_get_opaque( img ); + + if( opaque == false ){ + if( ( (atari_plot_flags & PLOT_FLAG_TRANS) == 0) + && + ((flags & (BITMAPF_MONOGLYPH|BITMAPF_BUFFER_NATIVE))==0) ){ + opaque = true; + } + } + + + assert( clip->g_h > 0 ); + assert( clip->g_w > 0 ); + + bw = atari_bitmap_get_width( img ); + bh = atari_bitmap_get_height( img ); + + // The converted bitmap can be saved for subsequent blits, WHEN: + // A.) the bitmap is fully opaque OR + // B.) the bitmap is completly inside the window + // the latter one is important for alpha blits, + // because we must get the window background to apply transparency + // If the image is not completly within the window, + // we can't get the whole background for the image. + // this only works if the image isn't used at several different places. + // In fact in case of alpha bitmap caching it is only used for the + // toolbar buttons right now. + + if( (opaque == true) || (flags & BITMAPF_BUFFER_NATIVE ) ){ + if( img->converted == true ){ + *out = img->native; + return( 0 ); + } + if( ( flags & BITMAPF_MONOGLYPH ) == 0 ){ + cache = true; + } + } + + /* rem. if eddi xy is installed, we could directly access the screen! */ + /* apply transparency to the image: */ + if (( opaque == false )) { + /* copy the screen to an temp buffer: */ + if ((flags & BITMAPF_BUFFER_NATIVE) == 0) { + scrbuf = snapshot_create(x, y, clip->g_w, clip->g_h); + if( scrbuf != NULL ) { + + assert( clip->g_w <= bw ); + assert( clip->g_h <= bh ); + + // copy blended pixels to the screen buffer: + ablend_bitmap( img, scrbuf, clip, NULL ); + /* adjust size which gets converted: */ + bw = clip->g_w; + bh = clip->g_h; + /* adjust output position: */ + clip->g_x = 0; + clip->g_y = 0; + /* set the source of conversion: */ + source = scrbuf; + } + } else { + /* + The whole bitmap can be transformed to an mfdb + (and get's cached) + */ + GRECT region = { 0, 0, bw, bh }; + ablend_pixel( img, bg, ®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<OFFSET_WEB_PAL ) { + pal[i][0] = sys_pal[i][0]; + pal[i][1] = sys_pal[i][1]; + pal[i][2] = sys_pal[i][2]; + } else if( vdi_sysinfo.scr_bpp >= 8 ) { + if ( i < OFFSET_CUST_PAL ){ + pal[i][0] = vdi_web_pal[i-OFFSET_WEB_PAL][0]; + pal[i][1] = vdi_web_pal[i-OFFSET_WEB_PAL][1]; + pal[i][2] = vdi_web_pal[i-OFFSET_WEB_PAL][2]; + //set the new palette color to websafe value: + vs_color(atari_plot_vdi_handle, i, &pal[i][0]); + } + if( i >= OFFSET_CUST_PAL && i<OFFSET_CUST_PAL+16 ) { + /* here we define 20 additional gray colors... */ + rgbcol[1] = rgbcol[2] = rgbcol[3] = ((graytone&0x0F) << 4); + rgb_to_vdi1000( &rgbcol[0], &pal[i][0] ); + vs_color(atari_plot_vdi_handle, i, &pal[i][0]); + graytone++; + } + + } + vdi1000_to_rgb( &pal[i][0], &rgb_lookup[i][0] ); + } + + } else { + /* no need to change the palette - its application specific */ + } +#else + bitmap_convert = bitmap_convert_tc; +#endif + + /* Setup Hermes conversion handles */ + unsigned long hermesflags = (atari_plot_flags & PLOT_FLAG_DITHER) ? HERMES_CONVERT_DITHER : 0; + hermes_cnv_h = Hermes_ConverterInstance(hermesflags); + assert( hermes_cnv_h ); + hermes_res_h = Hermes_ConverterInstance(hermesflags); + assert( hermes_res_h ); + + /* set up the src & dst format: */ + /* netsurf uses RGBA ... */ + nsfmt.a = 0xFFUL; + nsfmt.b = 0x0FF00UL; + nsfmt.g = 0x0FF0000UL; + nsfmt.r = 0x0FF000000UL; + nsfmt.bits = 32; + nsfmt.indexed = false; + nsfmt.has_colorkey = false; + + vfmt.r = vdi_sysinfo.mask_r; + vfmt.g = vdi_sysinfo.mask_g; + vfmt.b = vdi_sysinfo.mask_b; + vfmt.a = vdi_sysinfo.mask_a; + vfmt.bits = atari_plot_bpp_virt; + vfmt.indexed = (atari_plot_bpp_virt <= 8) ? 1 : 0; + vfmt.has_colorkey = 0; + + return( err ); +} + +int plot_finalise( void ) +{ + + delete_font_plotter(fplotter); + +#ifdef WITH_8BPP_SUPPORT + if (vfmt.indexed) { + int i; + for (i=OFFSET_WEB_PAL; i<OFFSET_CUST_PAL+16; i++) { + vs_color(atari_plot_vdi_handle, i, &sys_pal[i][0]); + } + } +#endif + + /* close Hermes stuff: */ + Hermes_ConverterReturn(hermes_cnv_h); + Hermes_Done(); + + /* free up temporary buffers */ + free(buf_packed ); + free(buf_planar); + snapshot_destroy(); + + return 0; +} + +bool plot_lock(void) +{ + if ((atari_plot_flags & PLOT_FLAG_LOCKED) != 0) + return(true); + if( !wind_update(BEG_UPDATE|0x100) ) + return(false); + if( !wind_update(BEG_MCTRL|0x100) ){ + wind_update(END_UPDATE); + return(false); + } + atari_plot_flags |= PLOT_FLAG_LOCKED; + graf_mouse(M_OFF, NULL); + return(true); +} + +bool plot_unlock(void) +{ + if( (atari_plot_flags & PLOT_FLAG_LOCKED) == 0 ) + return(true); + wind_update(END_MCTRL); + wind_update(END_UPDATE); + graf_mouse(M_ON, NULL); + vs_clip_off(atari_plot_vdi_handle); + atari_plot_flags &= ~PLOT_FLAG_LOCKED; + return(false); +} + +bool plot_rectangle(int x0, int y0, int x1, int y1, + const plot_style_t *pstyle ) +{ + short pxy[4]; + GRECT r, rclip, sclip; + int sw = pstyle->stroke_width; + uint32_t lt; + + /* current canvas clip: */ + rclip.g_x = view.clipping.x0; + rclip.g_y = view.clipping.y0; + rclip.g_w = view.clipping.x1 - view.clipping.x0; + rclip.g_h = view.clipping.y1 - view.clipping.y0; + + /* physical clipping: */ + sclip.g_x = rclip.g_x; + sclip.g_y = rclip.g_y; + sclip.g_w = view.vis_w; + sclip.g_h = view.vis_h; + + rc_intersect(&sclip, &rclip); + r.g_x = x0; + r.g_y = y0; + r.g_w = x1 - x0; + r.g_h = y1 - y0; + + if (!rc_intersect( &rclip, &r )) { + return(true); + } + if (pstyle->stroke_type != PLOT_OP_TYPE_NONE) { + /* + manually draw the line, because we do not need vdi clipping + for vertical / horizontal line draws. + */ + if( sw == 0) + sw = 1; + + NSLT2VDI(lt, pstyle); + vsl_type(atari_plot_vdi_handle, (lt&0x0F)); + /* + if the line style is not available within VDI system, + define own style: + */ + if( (lt&0x0F) == 7 ){ + vsl_udsty(atari_plot_vdi_handle, ((lt&0xFFFF00) >> 8)); + } + vsl_width(atari_plot_vdi_handle, (short)sw ); + vsl_rgbcolor(atari_plot_vdi_handle, pstyle->stroke_colour); + /* top border: */ + if( r.g_y == y0){ + pxy[0] = view.x + r.g_x; + pxy[1] = view.y + r.g_y ; + pxy[2] = view.x + r.g_x + r.g_w; + pxy[3] = view.y + r.g_y; + v_pline(atari_plot_vdi_handle, 2, (short *)&pxy); + } + + /* right border: */ + if( r.g_x + r.g_w == x1 ){ + pxy[0] = view.x + r.g_x + r.g_w; + pxy[1] = view.y + r.g_y; + pxy[2] = view.x + r.g_x + r.g_w; + pxy[3] = view.y + r.g_y + r.g_h; + v_pline(atari_plot_vdi_handle, 2, (short *)&pxy); + } + + /* bottom border: */ + if( r.g_y+r.g_h == y1 ){ + pxy[0] = view.x + r.g_x; + pxy[1] = view.y + r.g_y+r.g_h; + pxy[2] = view.x + r.g_x+r.g_w; + pxy[3] = view.y + r.g_y+r.g_h; + v_pline(atari_plot_vdi_handle, 2, (short *)&pxy); + } + + /* left border: */ + if( r.g_x == x0 ){ + pxy[0] = view.x + r.g_x; + pxy[1] = view.y + r.g_y; + pxy[2] = view.x + r.g_x; + pxy[3] = view.y + r.g_y + r.g_h; + v_pline(atari_plot_vdi_handle, 2, (short *)&pxy); + } + } + + if( pstyle->fill_type != PLOT_OP_TYPE_NONE ){ + short stroke_width = (short)(pstyle->stroke_type != PLOT_OP_TYPE_NONE) ? + pstyle->stroke_width : 0; + + vsf_rgbcolor(atari_plot_vdi_handle, pstyle->fill_colour); + vsf_perimeter(atari_plot_vdi_handle, 0); + vsf_interior(atari_plot_vdi_handle, FIS_SOLID); + + + pxy[0] = view.x + r.g_x + stroke_width; + pxy[1] = view.y + r.g_y + stroke_width; + pxy[2] = view.x + r.g_x + r.g_w -1 - stroke_width; + pxy[3] = view.y + r.g_y + r.g_h -1 - stroke_width; + + vsf_style(atari_plot_vdi_handle, 1); + v_bar(atari_plot_vdi_handle, (short*)&pxy); + } + return (true); +} + +bool plot_line(int x0, int y0, int x1, int y1, + const plot_style_t *pstyle ) +{ + short pxy[4]; + uint32_t lt; + int sw = pstyle->stroke_width; + + if((x0 < 0 && x1 < 0) || (y0 < 0 && y1 < 0)){ + return(true); + } + + pxy[0] = view.x + MAX(0,x0); + pxy[1] = view.y + MAX(0,y0); + pxy[2] = view.x + MAX(0,x1); + pxy[3] = view.y + MAX(0,y1); + + if((y0 > view.h-1) && (y1 > view.h-1)) + return(true); + + //printf("view: %d,%d,%d,%d\n", view.x, view.y, view.w, view.h); + //printf("line: %d,%d,%d,%d\n", x0, y0, x1, y1); + + + //plot_vdi_clip(true); + if( sw == 0) + sw = 1; + NSLT2VDI(lt, pstyle) + vsl_type(atari_plot_vdi_handle, (lt&0x0F)); + /* if the line style is not available within VDI system,define own style: */ + if( (lt&0x0F) == 7 ){ + vsl_udsty(atari_plot_vdi_handle, ((lt&0xFFFF00) >> 8)); + } + vsl_width(atari_plot_vdi_handle, (short)sw); + vsl_rgbcolor(atari_plot_vdi_handle, pstyle->stroke_colour); + v_pline(atari_plot_vdi_handle, 2, (short *)&pxy ); + //plot_vdi_clip(false); + return (true); +} + +static bool plot_polygon(const int *p, unsigned int n, + const plot_style_t *pstyle) +{ + short pxy[n*2]; + unsigned int i=0; + if (vdi_sysinfo.maxpolycoords > 0) + assert( (signed int)n < vdi_sysinfo.maxpolycoords); + + vsf_interior(atari_plot_vdi_handle, FIS_SOLID); + vsf_style(atari_plot_vdi_handle, 1); + for (i = 0; i<n*2; i=i+2) { + pxy[i] = (short)view.x+p[i]; + pxy[i+1] = (short)view.y+p[i+1]; + } + if (pstyle->fill_type == PLOT_OP_TYPE_SOLID) { + vsf_rgbcolor(atari_plot_vdi_handle, pstyle->fill_colour); + v_fillarea(atari_plot_vdi_handle, n, (short*)&pxy); + } else { + pxy[n*2]=pxy[0]; + pxy[n*2+1]=pxy[1]; + vsl_rgbcolor(atari_plot_vdi_handle, pstyle->stroke_colour); + v_pline(atari_plot_vdi_handle, n+1, (short *)&pxy); + } + + return ( true ); +} + +/*** + * Set plot origin and canvas size + * \param x the x origin + * \param y the y origin + * \param w the width of the plot area + * \param h the height of the plot area + */ +bool plot_set_dimensions(int x, int y, int w, int h) +{ + bool doupdate = false; + struct rect newclip = {0, 0, w, h}; + GRECT absclip = {x, y, w, h}; + + if (!(w == view.w && h == view.h)) { + view.w = (short)w; + view.h = (short)h; + doupdate = true; + } + if (!(x == view.x && y == view.y)) { + view.x = (short)x; + view.y = (short)y; + doupdate = true; + } + if (doupdate==true) + update_visible_rect(); + + //dbg_rect("plot_set_dimensions", &newclip); + + plot_set_abs_clipping(&absclip); + plot_clip(&newclip); + return(true); +} + +/*** + * Get current canvas size + * \param dst the GRECT * which receives the canvas size + * + */ +bool plot_get_dimensions(GRECT *dst) +{ + dst->g_x = view.x; + dst->g_y = view.y; + dst->g_w = view.w; + dst->g_h = view.h; + return(true); +} + +/** + * set scale of plotter. + * \param scale the new scale value + * \return the old scale value + */ + +float plot_set_scale(float scale) +{ + float ret = view.scale; + + view.scale = scale; + + return(ret); +} + +float plot_get_scale(void) +{ + return(view.scale); +} + + +/** + * + * Subsequent calls to plot_clip will be clipped by the absolute clip. + * \param area the maximum clipping rectangle (absolute screen coords) + * +*/ +void plot_set_abs_clipping(const GRECT *area) +{ + GRECT canvas; + + plot_get_dimensions(&canvas); + + if(!rc_intersect(area, &canvas)){ + view.abs_clipping.x0 = 0; + view.abs_clipping.x1 = 0; + view.abs_clipping.y0 = 0; + view.abs_clipping.y1 = 0; + } + else { + view.abs_clipping.x0 = area->g_x; + view.abs_clipping.x1 = area->g_x + area->g_w; + view.abs_clipping.y0 = area->g_y; + view.abs_clipping.y1 = area->g_y + area->g_h; + } +} + + +/*** + * Get the maximum clip extent, in absolute screen coords + * \param dst the structure that receives the absolute clipping + */ +void plot_get_abs_clipping(struct rect *dst) +{ + *dst = view.abs_clipping; +} + + +/*** + * Get the maximum clip extent, in absolute screen coords + * \param dst the structure that receives the absolute clipping + */ +void plot_get_abs_clipping_grect(GRECT *dst) +{ + dst->g_x = view.abs_clipping.x0; + dst->g_w = view.abs_clipping.x1 - view.abs_clipping.x0; + dst->g_y = view.abs_clipping.y0; + dst->g_h = view.abs_clipping.y1 - view.abs_clipping.y0; +} + +bool plot_clip(const struct rect *clip) +{ + GRECT canvas, screen, gclip, maxclip; + short pxy[4]; + + screen.g_x = 0; + screen.g_y = 0; + screen.g_w = vdi_sysinfo.scr_w; + screen.g_h = vdi_sysinfo.scr_h; + + plot_get_dimensions(&canvas); + + view.clipping.y0 = clip->y0; + view.clipping.y1 = clip->y1; + view.clipping.x0 = clip->x0; + view.clipping.x1 = clip->x1; + + plot_get_clip_grect(&gclip); + + gclip.g_x += canvas.g_x; + gclip.g_y += canvas.g_y; + + rc_intersect(&canvas, &gclip); + + if(gclip.g_h < 0){ + gclip.g_h = 0; + } + + if (!rc_intersect(&screen, &gclip)) { + //dbg_rect("cliprect: ", &view.clipping); + //dbg_grect("screen: ", &canvas); + //dbg_grect("canvas clipped: ", &gclip); + //assert(1 == 0); + } + + // When setting VDI clipping, obey to maximum cliping rectangle: + plot_get_abs_clipping_grect(&maxclip); + rc_intersect(&maxclip, &gclip); + + //dbg_grect("canvas clipped to screen", &gclip); + + pxy[0] = gclip.g_x; + pxy[1] = gclip.g_y; + pxy[2] = pxy[0] + gclip.g_w; + pxy[3] = pxy[1] + gclip.g_h; + + vs_clip(atari_plot_vdi_handle, 1, (short*)&pxy); + + return ( true ); +} + +VdiHdl plot_get_vdi_handle(void) +{ + return(atari_plot_vdi_handle); +} + +long plot_get_flags(void) +{ + return(atari_plot_flags); +} + + +bool plot_get_clip(struct rect * out) +{ + out->x0 = view.clipping.x0; + out->y0 = view.clipping.y0; + out->x1 = view.clipping.x1; + out->y1 = view.clipping.y1; + return( true ); +} + +void plot_get_clip_grect(GRECT * out) +{ + struct rect clip={0,0,0,0}; + + plot_get_clip(&clip); + + out->g_x = clip.x0; + out->g_y = clip.y0; + out->g_w = clip.x1 - clip.x0; + out->g_h = clip.y1 - clip.y0; +} + +FONT_PLOTTER plot_get_text_plotter() +{ + return(fplotter); +} + +void plot_set_text_plotter(FONT_PLOTTER font_plotter) +{ + fplotter = font_plotter; +} + +static bool plot_text(int x, int y, const char *text, size_t length, const plot_font_style_t *fstyle ) +{ + if (view.scale != 1.0) { + plot_font_style_t newstyle = *fstyle; + newstyle.size = (int)((float)fstyle->size*view.scale); + fplotter->text(fplotter, x, y, text, length, &newstyle); + } else { + fplotter->text(fplotter, x, y, text, length, fstyle); + } + + return ( true ); +} + +static bool plot_disc(int x, int y, int radius, const plot_style_t *pstyle) +{ + if (pstyle->fill_type != PLOT_OP_TYPE_SOLID) { + vsf_rgbcolor(atari_plot_vdi_handle, pstyle->stroke_colour); + vsf_perimeter(atari_plot_vdi_handle, 1); + vsf_interior(atari_plot_vdi_handle, 0); + v_circle(atari_plot_vdi_handle, view.x + x, view.y + y, radius); + } else { + vsf_rgbcolor(atari_plot_vdi_handle, pstyle->fill_colour); + vsf_perimeter(atari_plot_vdi_handle, 0); + vsf_interior(atari_plot_vdi_handle, FIS_SOLID); + v_circle(atari_plot_vdi_handle, view.x + x, view.y + y, radius); + } + + return(true); +} + +static bool plot_arc(int x, int y, int radius, int angle1, int angle2, + const plot_style_t *pstyle) +{ + + vswr_mode(atari_plot_vdi_handle, MD_REPLACE ); + if (pstyle->fill_type == PLOT_OP_TYPE_NONE) + return(true); + if ( pstyle->fill_type != PLOT_OP_TYPE_SOLID) { + vsl_rgbcolor(atari_plot_vdi_handle, pstyle->stroke_colour); + vsf_perimeter(atari_plot_vdi_handle, 1); + vsf_interior(atari_plot_vdi_handle, 1 ); + v_arc(atari_plot_vdi_handle, view.x + x, view.y + y, radius, angle1*10, angle2*10); + } else { + vsf_rgbcolor(atari_plot_vdi_handle, pstyle->fill_colour); + vsl_width(atari_plot_vdi_handle, 1 ); + vsf_perimeter(atari_plot_vdi_handle, 1); + v_arc(atari_plot_vdi_handle, view.x + x, view.y + y, radius, angle1*10, angle2*10); + } + + return (true); +} + +static bool plot_bitmap(int x, int y, int width, int height, + struct bitmap *bitmap, colour bg, + bitmap_flags_t flags) +{ + struct bitmap * bm = NULL; + bool repeat_x = (flags & BITMAPF_REPEAT_X); + bool repeat_y = (flags & BITMAPF_REPEAT_Y); + int bmpw,bmph; + struct rect clip = {0,0,0,0}; + + bmpw = atari_bitmap_get_width(bitmap); + bmph = atari_bitmap_get_height(bitmap); + + if(view.scale != 1.0){ + width = (int)(((float)width)*view.scale); + height = (int)(((float)height)*view.scale); + } + + if ( repeat_x || repeat_y ) { + plot_get_clip(&clip); + if( repeat_x && width == 1 && repeat_y && height == 1 ) { + width = MAX( width, clip.x1 - x ); + height = MAX( height, clip.y1 - y ); + } else if( repeat_x && width == 1 ) { + width = MAX( width, clip.x1 - x); + } else if( repeat_y && height == 1) { + height = MAX( height, clip.y1 - y ); + } + } + + if( width != bmpw || height != bmph ) { + atari_bitmap_resize(bitmap, hermes_res_h, &nsfmt, width, height ); + if( bitmap->resized ) + bm = bitmap->resized; + else + bm = bitmap; + } else { + bm = bitmap; + } + + /* out of memory? */ + if( bm == NULL ) { + printf("plot: out of memory! bmp: %p, bmpres: %p\n", bitmap, bitmap->resized ); + return( true ); + } + + if (!(repeat_x || repeat_y) ) { + plot_blit_bitmap(bm, x, y, bg, flags ); + } else { + int xf,yf; + int xoff = x; + int yoff = y; + + if (yoff > clip.y0 ) + yoff = (clip.y0 - height) + ((yoff - clip.y0) % height); + if (xoff > clip.x0 ) + xoff = (clip.x0 - width) + ((xoff - clip.x0) % width); + /* for now, repeating just works in the rigth / down direction */ + /* + if( repeat_x == true ) + xoff = clip.x0; + if(repeat_y == true ) + yoff = clip.y0; + */ + + for( xf = xoff; xf < clip.x1; xf += width ) { + for( yf = yoff; yf < clip.y1; yf += height ) { + plot_blit_bitmap(bm, xf, yf, bg, flags ); + if (!repeat_y) + break; + } + if (!repeat_x) + break; + } + } + return ( true ); +} + +static bool plot_path(const float *p, unsigned int n, colour fill, float width, + colour c, const float transform[6]) +{ + return ( true ); +} + + + +const struct plotter_table atari_plotters = { + .rectangle = plot_rectangle, + .line = plot_line, + .polygon = plot_polygon, + .clip = plot_clip, + .text = plot_text, + .disc = plot_disc, + .arc = plot_arc, + .bitmap = plot_bitmap, + .path = plot_path, + .flush = NULL, + .group_start = NULL, + .group_end = NULL, + .option_knockout = true +}; diff --git a/frontends/atari/plot/plot.h b/frontends/atari/plot/plot.h new file mode 100644 index 000000000..22f8781c2 --- /dev/null +++ b/frontends/atari/plot/plot.h @@ -0,0 +1,158 @@ +/* + * Copyright 2010 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef NS_ATARI_PLOT_H +#define NS_ATARI_PLOT_H + +/** how much memory should be kept allocated for temp. conversion bitmaps: */ +#define CONV_KEEP_LIMIT 512000 + +/** how much memory to allocate if some is needed: */ +#define CONV_BLOCK_SIZE 32000 + +/* Plotter Option Flags: */ +#define PLOT_FLAG_DITHER 0x04 /**< set if the plotter shall dither images */ +#define PLOT_FLAG_TRANS 0x08 /**< set if the plotter supports transparent operations */ + +/* Plotter "feature" flags */ +#define PLOT_FLAG_HAS_DITHER 0x0400 +#define PLOT_FLAG_HAS_ALPHA 0x0800 +#define PLOT_FLAG_OFFSCREEN 0x1000 /**< offscreen plotter should set this flag */ + +/* Plotter "internal" flags */ +#define PLOT_FLAG_LOCKED 0x08000 /**< plotter should set this flag during screen updates */ + +/* Font Plotter flags: */ +#define FONTPLOT_FLAG_MONOGLYPH 0x01 + +/* Flags for init_mfdb function: */ +#define MFDB_FLAG_STAND 0x01 +#define MFDB_FLAG_ZEROMEM 0x02 +#define MFDB_FLAG_NOALLOC 0x04 + +/* Flags for blit functions: */ +#define BITMAPF_MONOGLYPH 4096 /**< The bitmap is an character bitmap */ +#define BITMAPF_BUFFER_NATIVE 8192 /**< Bitmap shall be kept converted */ + +/* Error codes: */ +#define ERR_BUFFERSIZE_EXCEEDS_SCREEN 1 /* The buffer allocated is larger than the screen */ +#define ERR_NO_MEM 2 /* Not enough memory for requested operation */ +#define ERR_PLOTTER_NOT_AVAILABLE 3 /* invalid plotter driver name passed */ + +struct s_vdi_sysinfo { + short vdi_handle; /**< vdi handle */ + short scr_w; /**< resolution horz. */ + short scr_h; /**< resolution vert. */ + short scr_bpp; /**< bits per pixel */ + int colors; /**< 0=hiclor, 2=mono */ + unsigned long hicolors; /**< if colors = 0 */ + short pixelsize; /**< bytes per pixel */ + unsigned short pitch; /**< row pitch */ + unsigned short vdiformat; /**< pixel format */ + unsigned short clut; /**< type of clut support */ + void *screen; /**< pointer to screen, or NULL */ + unsigned long screensize; /**< size of screen (in bytes) */ + unsigned long mask_r; /**< red color mask */ + unsigned long mask_g; /**< green color mask */ + unsigned long mask_b; /**< blue color mask */ + unsigned long mask_a; /**< alpha color mask */ + short maxintin; /* maximum pxy items */ + short maxpolycoords; /* max coords for p_line etc. */ + unsigned long EdDiVersion; /* EdDi Version or 0 */ + bool rasterscale; /* raster scaling support */ +}; + +struct rect; + +extern const struct plotter_table atari_plotters; + +int plot_init(char *); +int plot_finalise(void); + +/** + * translate an error number + */ +const char* plot_err_str(int i) ; + +bool plot_lock(void); +bool plot_unlock(void); +bool plot_set_dimensions( int x, int y, int w, int h ); +bool plot_get_dimensions(GRECT *dst); +float plot_get_scale(void); +float plot_set_scale(float); +void plot_set_abs_clipping(const GRECT *area); +void plot_get_abs_clipping(struct rect *dst); +void plot_get_abs_clipping_grect(GRECT *dst); +bool plot_get_clip(struct rect * out); +/* Get clipping for current framebuffer as GRECT */ +void plot_get_clip_grect(GRECT * out); +bool plot_clip(const struct rect *clip); +VdiHdl plot_get_vdi_handle(void); +long plot_get_flags(void); +bool plot_rectangle( int x0, int y0, int x1, int y1,const plot_style_t *style ); +bool plot_line( int x0, int y0, int x1, int y1, const plot_style_t *style ); +bool plot_blit_bitmap(struct bitmap * bmp, int x, int y, + unsigned long bg, unsigned long flags); +bool plot_blit_mfdb(GRECT * loc, MFDB * insrc, short fgcolor, uint32_t flags); +bool plot_copy_rect(GRECT src, GRECT dst); + +/* convert an vdi color to bgra */ +void vdi1000_to_rgb( unsigned short * in, unsigned char * out ); + +/* convert an bgra color to vdi1000 color */ +void rgb_to_vdi1000( unsigned char * in, RGB1000 *out); + +/* convert an rgb color to an index into the web palette */ +short rgb_to_666_index(unsigned char r, unsigned char g, unsigned char b); + +/* assign vdi line style to dst ( netsurf type ) */ +#define NSLT2VDI(dst, src) \ + dst = 0; \ + switch( src->stroke_type ) { \ + case PLOT_OP_TYPE_DOT: \ + dst = (0xAAAA00 | 7); \ + break; \ + case PLOT_OP_TYPE_DASH: \ + dst = 3; \ + break; \ + case PLOT_OP_TYPE_SOLID: \ + case PLOT_OP_TYPE_NONE: \ + default: \ + dst = 1; \ + break; \ + } + + +#ifdef WITH_8BPP_SUPPORT +/* some Well known indexes into the VDI palette */ +/* common indexes into the VDI palette */ +/* (only used when running with 256 colors or less ) */ +#define OFFSET_WEB_PAL 16 +#define OFFSET_CUST_PAL 232 +#define RGB_TO_VDI(c) rgb_to_666_index( (c&0xFF),(c&0xFF00)>>8,(c&0xFF0000)>>16)+OFFSET_WEB_PAL +#endif /* WITH_8BPP_SUPPORT*/ + +/* the name of this macro is crap - it should be named bgr_to_rgba ... or so */ +#define ABGR_TO_RGB(c) ( ((c&0xFF)<<16) | (c&0xFF00) | ((c&0xFF0000)>>16) ) << 8 + +/* this index into the palette is used by the TC renderer to set + * current draw color. + */ +#define OFFSET_CUSTOM_COLOR 255 + +#endif diff --git a/frontends/atari/redrawslots.c b/frontends/atari/redrawslots.c new file mode 100644 index 000000000..f5351866a --- /dev/null +++ b/frontends/atari/redrawslots.c @@ -0,0 +1,125 @@ +/* + * Copyright 2011 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdbool.h> + +#include "utils/utils.h" + +#include "atari/redrawslots.h" +#include "atari/gemtk/gemtk.h" + +void redraw_slots_init(struct s_redrw_slots * slots, short size) +{ + // TODO: allocate slots dynamically! + slots->size = MIN( MAX_REDRW_SLOTS , size); + slots->areas_used = 0; +} + +void redraw_slots_free(struct s_redrw_slots * slots) +{ + // TOOD: free areas... +} + + +static inline bool rect_intersect( struct rect * box1, struct rect * box2 ) +{ + if (box2->x1 < box1->x0) + return false; + + if (box2->y1 < box1->y0) + return false; + + if (box2->x0 > box1->x1) + return false; + + if (box2->y0 > box1->y1) + return false; + + return true; +} + + +void redraw_slot_schedule_grect(struct s_redrw_slots * slots, GRECT *area, + bool force) +{ + redraw_slot_schedule(slots, area->g_x, area->g_y, + area->g_x + area->g_w, area->g_y + area->g_h, force); +} + +/* + schedule redraw coords. +*/ +void redraw_slot_schedule(struct s_redrw_slots * slots, short x0, short y0, + short x1, short y1, bool force) +{ + int i = 0; + struct rect area; + + area.x0 = x0; + area.y0 = y0; + area.x1 = x1; + area.y1 = y1; + + if (force == false) { + for (i=0; i<slots->areas_used; i++) { + if (slots->areas[i].x0 <= x0 + && slots->areas[i].x1 >= x1 + && slots->areas[i].y0 <= y0 + && slots->areas[i].y1 >= y1) { + /* the area is already queued for redraw */ + return; + } else { + if (rect_intersect(&slots->areas[i], &area )) { + slots->areas[i].x0 = MIN(slots->areas[i].x0, x0); + slots->areas[i].y0 = MIN(slots->areas[i].y0, y0); + slots->areas[i].x1 = MAX(slots->areas[i].x1, x1); + slots->areas[i].y1 = MAX(slots->areas[i].y1, y1); + return; + } + } + } + } + + if (slots->areas_used < slots->size) { + slots->areas[slots->areas_used].x0 = x0; + slots->areas[slots->areas_used].x1 = x1; + slots->areas[slots->areas_used].y0 = y0; + slots->areas[slots->areas_used].y1 = y1; + slots->areas_used++; + } else { + /* + we are out of available slots, merge box with last slot + this is dumb... but also a very rare case. + */ + slots->areas[slots->size-1].x0 = MIN(slots->areas[i].x0, x0); + slots->areas[slots->size-1].y0 = MIN(slots->areas[i].y0, y0); + slots->areas[slots->size-1].x1 = MAX(slots->areas[i].x1, x1); + slots->areas[slots->size-1].y1 = MAX(slots->areas[i].y1, y1); + } + + return; +} + +void redraw_slots_remove_area(struct s_redrw_slots * slots, int i) +{ + int x; + for (x = i+1; i<slots->areas_used; x++) { + slots->areas[x-1] = slots->areas[x]; + } + slots->areas_used--; +} diff --git a/frontends/atari/redrawslots.h b/frontends/atari/redrawslots.h new file mode 100644 index 000000000..ca72a0172 --- /dev/null +++ b/frontends/atari/redrawslots.h @@ -0,0 +1,54 @@ +/* + * Copyright 2012 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef ATARI_REDRAW_SLOTS_H +#define ATARI_REDRAW_SLOTS_H + +#include <mt_gem.h> + +#include "utils/utils.h" + +/** + * This is the number of redraw requests that the slotlist can store. + * If a redraw is scheduled and all slots are used, the rectangle will + * be merged to one of the existing slots. + */ +#define MAX_REDRW_SLOTS 32 + +struct rect; + +/** + * This struct holds scheduled redraw requests. + */ +struct s_redrw_slots +{ + struct rect areas[MAX_REDRW_SLOTS]; + short size; + short volatile areas_used; +}; + +void redraw_slots_init(struct s_redrw_slots * slots, short size); +void redraw_slot_schedule(struct s_redrw_slots * slots, short x0, short y0, + short x1, short y1, bool force); +void redraw_slot_schedule_grect(struct s_redrw_slots * slots, GRECT *area, + bool force); +void redraw_slots_remove_area(struct s_redrw_slots * slots, int i); +void redraw_slots_free(struct s_redrw_slots * slots); + +#endif diff --git a/frontends/atari/res/blank b/frontends/atari/res/blank new file mode 100644 index 000000000..f21f228a1 --- /dev/null +++ b/frontends/atari/res/blank @@ -0,0 +1,39 @@ +<html> + <head> + <title>Blankpage</title> + </head> + <body> + <h1>Welcome to NetSurf!</h1> + </body> +</html> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/frontends/atari/res/favicon.ico b/frontends/atari/res/favicon.ico Binary files differnew file mode 100644 index 000000000..8b26a278f --- /dev/null +++ b/frontends/atari/res/favicon.ico diff --git a/frontends/atari/res/icons/toolbar/atfact/main.png b/frontends/atari/res/icons/toolbar/atfact/main.png Binary files differnew file mode 100644 index 000000000..64cf3bc54 --- /dev/null +++ b/frontends/atari/res/icons/toolbar/atfact/main.png diff --git a/frontends/atari/res/icons/toolbar/atfact/throbber.png b/frontends/atari/res/icons/toolbar/atfact/throbber.png Binary files differnew file mode 100644 index 000000000..44d949a1c --- /dev/null +++ b/frontends/atari/res/icons/toolbar/atfact/throbber.png diff --git a/frontends/atari/res/icons/toolbar/default/main.png b/frontends/atari/res/icons/toolbar/default/main.png Binary files differnew file mode 100644 index 000000000..964218076 --- /dev/null +++ b/frontends/atari/res/icons/toolbar/default/main.png diff --git a/frontends/atari/res/icons/toolbar/default/main.xcf b/frontends/atari/res/icons/toolbar/default/main.xcf Binary files differnew file mode 100644 index 000000000..48d6d168c --- /dev/null +++ b/frontends/atari/res/icons/toolbar/default/main.xcf diff --git a/frontends/atari/res/icons/toolbar/default/throbber.png b/frontends/atari/res/icons/toolbar/default/throbber.png Binary files differnew file mode 100644 index 000000000..be3bf9949 --- /dev/null +++ b/frontends/atari/res/icons/toolbar/default/throbber.png diff --git a/frontends/atari/res/icons/toolbar/default/throbber.xcf b/frontends/atari/res/icons/toolbar/default/throbber.xcf Binary files differnew file mode 100644 index 000000000..18646c9c9 --- /dev/null +++ b/frontends/atari/res/icons/toolbar/default/throbber.xcf 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 Binary files differnew file mode 100755 index 000000000..9c7d8dd74 --- /dev/null +++ b/frontends/atari/res/netsurf.rsc 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 i |