summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile8
-rw-r--r--Makefile.defaults39
-rw-r--r--atari/Makefile.target50
-rw-r--r--atari/bitmap.c384
-rw-r--r--atari/bitmap.h44
-rw-r--r--atari/browser.c944
-rw-r--r--atari/browser.h70
-rw-r--r--atari/browser_win.c459
-rw-r--r--atari/browser_win.h79
-rw-r--r--atari/clipboard.h25
-rw-r--r--atari/doc/bugs5
-rw-r--r--atari/doc/readme.txt30
-rw-r--r--atari/doc/todo33
-rw-r--r--atari/download.c67
-rw-r--r--atari/download.h22
-rw-r--r--atari/filetype.c63
-rw-r--r--atari/findfile.c144
-rw-r--r--atari/findfile.h24
-rw-r--r--atari/font.c120
-rw-r--r--atari/font.h31
-rw-r--r--atari/global_evnt.c760
-rw-r--r--atari/global_evnt.h78
-rw-r--r--atari/gui.c1131
-rw-r--r--atari/gui.h236
-rw-r--r--atari/history.c30
-rw-r--r--atari/history.h22
-rw-r--r--atari/hotlist.c165
-rw-r--r--atari/hotlist.h30
-rw-r--r--atari/login.c110
-rw-r--r--atari/login.h24
-rw-r--r--atari/misc.c184
-rw-r--r--atari/misc.h38
-rw-r--r--atari/options.h73
-rw-r--r--atari/plot.c222
-rw-r--r--atari/plot.h32
-rw-r--r--atari/plot/eddi.h54
-rw-r--r--atari/plot/eddi.s42
-rw-r--r--atari/plot/font_freetype.c512
-rw-r--r--atari/plot/font_freetype.h51
-rw-r--r--atari/plot/font_vdi.c216
-rw-r--r--atari/plot/font_vdi.h23
-rw-r--r--atari/plot/plotter.c723
-rw-r--r--atari/plot/plotter.h293
-rw-r--r--atari/plot/plotter_vdi.c998
-rw-r--r--atari/plot/plotter_vdi.h48
-rw-r--r--atari/res/netsurf.rsh97
-rw-r--r--atari/res/netsurf.rsm94
-rw-r--r--atari/schedule.c223
-rw-r--r--atari/schedule.h25
-rw-r--r--atari/scripts/mkpkg.sh223
-rw-r--r--atari/slider.c131
-rw-r--r--atari/slider.h57
-rw-r--r--atari/statusbar.c178
-rw-r--r--atari/statusbar.h25
-rw-r--r--atari/thumbnail.c25
-rw-r--r--atari/toolbar.c772
-rw-r--r--atari/toolbar.h51
-rw-r--r--atari/treeview.c220
-rw-r--r--atari/treeview.h51
-rw-r--r--atari/verify_ssl.c272
-rw-r--r--atari/verify_ssl.h24
-rw-r--r--desktop/options.c2
-rw-r--r--utils/utils.h8
63 files changed, 11211 insertions, 3 deletions
diff --git a/Makefile b/Makefile
index 9ed900e98..f35333af0 100644
--- a/Makefile
+++ b/Makefile
@@ -82,7 +82,7 @@ else
endif
ifeq ($(HOST),mint)
ifeq ($(TARGET),)
- TARGET := framebuffer
+ TARGET := atari
endif
endif
@@ -102,7 +102,9 @@ ifneq ($(TARGET),riscos)
ifneq ($(TARGET),amiga)
ifneq ($(TARGET),framebuffer)
ifneq ($(TARGET),windows)
- $(error Unknown TARGET "$(TARGET)", should either be "riscos", "gtk", "beos", "amiga", "framebuffer" or "windows")
+ ifneq ($(TARGET),atari)
+ $(error Unknown TARGET "$(TARGET)", should either be "riscos", "gtk", "beos", "amiga", "framebuffer", "windows" or "atari")
+ endif
endif
endif
endif
@@ -203,7 +205,7 @@ else
PKG_CONFIG := PKG_CONFIG_LIBDIR="$(GCCSDK_INSTALL_ENV)/lib/pkgconfig" pkg-config
endif
else
- # Building for GTK, Framebuffer
+ # Building for GTK, Framebuffer, Atari
PKG_CONFIG := pkg-config
endif
endif
diff --git a/Makefile.defaults b/Makefile.defaults
index 188f4f10f..c0d2e1b1a 100644
--- a/Makefile.defaults
+++ b/Makefile.defaults
@@ -306,6 +306,45 @@ ifeq ($(TARGET),windows)
endif
+# ----------------------------------------------------------------------------
+# Atari-specific options
+# ----------------------------------------------------------------------------
+ifeq ($(TARGET),atari)
+
+ # 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 libwebp/libvpx for displaying WebPs
+ # Valid options: YES, NO
+ NETSURF_USE_WEBP := 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
+
+ NETSURF_USE_MNG := NO
+
+ NETSURF_ATARI_USE_FREETYPE := YES
+
+ # Optimisation levels
+ CFLAGS += -m68000 -O2 -Wuninitialized -DNO_IPV6
+
+ WARNFLAGS = -W -Wundef -Wpointer-arith \
+ -Wcast-align -Wwrite-strings -Wstrict-prototypes \
+ -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls \
+ -Wnested-externs -Wl,-t
+
+endif
+
# Include any local configuration
-include Makefile.config
diff --git a/atari/Makefile.target b/atari/Makefile.target
new file mode 100644
index 000000000..8ceef2123
--- /dev/null
+++ b/atari/Makefile.target
@@ -0,0 +1,50 @@
+# ----------------------------------------------------------------------------
+# Atari target setup
+# ----------------------------------------------------------------------------
+
+$(eval $(call feature_enabled,MNG,-DWITH_MNG,-lmng,PNG/MNG/JNG (libmng)))
+$(eval $(call feature_enabled,PNG,-DWITH_PNG,-lpng,PNG (libpng) ))
+
+CFLAGS += -I/usr/GEM/include
+LDFLAGS += -L/usr/GEM/lib -lcflib
+
+CFLAGS += -DATARI_USE_FREETYPE $(shell freetype-config --cflags)
+LDFLAGS += $(shell freetype-config --libs)
+
+# define additional CFLAGS and LDFLAGS requirements for pkg-configed libs here
+NETSURF_FEATURE_RSVG_CFLAGS := -DWITH_RSVG
+NETSURF_FEATURE_HUBBUB_CFLAGS := -DWITH_HUBBUB
+NETSURF_FEATURE_BMP_CFLAGS := -DWITH_BMP
+NETSURF_FEATURE_GIF_CFLAGS := -DWITH_GIF
+
+$(eval $(call pkg_config_find_and_add,BMP,libnsbmp,BMP))
+$(eval $(call pkg_config_find_and_add,GIF,libnsgif,GIF))
+
+CFLAGS += -std=c99 -I. -Dsmall $(WARNFLAGS) -Dnsatari \
+ -D_BSD_SOURCE \
+ -D_XOPEN_SOURCE=600 \
+ -D_POSIX_C_SOURCE=200112L \
+ $(shell $(PKG_CONFIG) --cflags libhubbub libcss openssl) \
+ $(shell xml2-config --cflags) \
+ $(shell curl-config --cflags)
+
+LDFLAGS += $(shell curl-config --libs)
+LDFLAGS += $(shell $(PKG_CONFIG) --libs libhubbub openssl libcss)
+LDFLAGS += -L/usr/lib/ -lxml2 -lz -lHermes -liconv -L/usr/lib -lwindom -lldg -lgem -lm
+
+
+# S_ATARI are sources purely for the Atari FreeMiNT build
+S_ATARI := gui.c findfile.c filetype.c misc.c bitmap.c schedule.c \
+ download.c thumbnail.c login.c verify_ssl.c treeview.c hotlist.c history.c\
+ font.c \
+ plot.c plot/plotter.c plot/plotter_vdi.c plot/eddi.s \
+ plot/font_vdi.c plot/font_freetype.c \
+ browser_win.c toolbar.c statusbar.c browser.c \
+ global_evnt.c
+S_ATARI := $(addprefix atari/,$(S_ATARI))
+
+
+SOURCES := $(S_COMMON) $(S_IMAGE) $(S_BROWSER) $(S_ATARI)
+EXETARGET := ns$(SUBTARGET).prg
+
+
diff --git a/atari/bitmap.c b/atari/bitmap.c
new file mode 100644
index 000000000..d6bd13667
--- /dev/null
+++ b/atari/bitmap.c
@@ -0,0 +1,384 @@
+/*
+ * 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 <windom.h>
+
+
+#include "assert.h"
+#include "image/bitmap.h"
+#include "atari/bitmap.h"
+#include "atari/plot.h"
+#include "utils/log.h"
+
+
+
+/**
+ * Create a bitmap.
+ *
+ * \param width width of image in pixels
+ * \param height 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 *bitmap_create(int w, int h, unsigned int state)
+{
+ return bitmap_create_ex( w, h, NS_BMP_DEFAULT_BPP, w * NS_BMP_DEFAULT_BPP, state, NULL );
+}
+
+/**
+ * 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
+ */
+void * bitmap_create_ex( int w, int h, short bpp, int rowstride, unsigned int state, void * pixdata )
+{
+ struct bitmap * bitmap;
+
+ LOG(("width %d, height %d, state %u",w, 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 = 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;
+}
+
+void * 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 );
+ }
+
+ if( bitmap->pixdata == NULL ) {
+ assert( 1 == 0 );
+ /* add some buffer for bad code */
+ bitmap->pixdata = malloc( newsize + 128 );
+ } else {
+ int oldsize = bitmap->rowstride * bitmap->height;
+ bool doalloc = ( state == BITMAP_GROW) ? (newsize > oldsize) : (newsize != oldsize);
+ if( newsize > oldsize )
+ assert( doalloc == true );
+ if( doalloc ) {
+ bitmap->pixdata = realloc( bitmap->pixdata, newsize + 128 );
+ if( bitmap->pixdata == NULL )
+ return( NULL );
+ }
+ }
+
+ bitmap->width = w;
+ bitmap->height = h;
+ bitmap->opaque = false;
+ bitmap->bpp = bpp;
+ bitmap->resized = NULL;
+ bitmap->rowstride = rowstride;
+ bitmap_modified( bitmap );
+ return( bitmap );
+}
+
+void bitmap_to_mfdb(void * bitmap, MFDB * out)
+{
+ struct bitmap * bm;
+ uint32_t dstsize;
+ uint8_t * tmp;
+ size_t dststride, oldstride;
+
+ bm = bitmap;
+ assert( out != NULL );
+ assert( bm->pixdata != NULL );
+
+ oldstride = bitmap_get_rowstride( bm );
+ dststride = MFDB_STRIDE( bm->width );
+
+ if( oldstride != dststride * bm->bpp )
+ {
+ /* we need to convert the img to new rowstride */
+ tmp = bm->pixdata;
+ bm->pixdata = calloc(1, dststride * bm->bpp * bm->height );
+ if( tmp == NULL ){
+ bm->pixdata = tmp;
+ out->fd_addr = NULL;
+ return;
+ }
+ bm->rowstride = dststride * bm->bpp;
+ int i=0;
+ for( i=0; i<bm->height; i++) {
+ memcpy( (bm->pixdata+i*bm->rowstride), (tmp + i*oldstride), oldstride);
+ }
+ free( tmp );
+ }
+ out->fd_w = dststride;
+ out->fd_h = bm->height;
+ out->fd_wdwidth = dststride >> 4;
+ out->fd_addr = bm->pixdata;
+ out->fd_stand = 0;
+ out->fd_nplanes = (short)bm->bpp;
+ out->fd_r1 = out->fd_r2 = out->fd_r3 = 0;
+}
+
+
+/**
+ * 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().
+ */
+
+unsigned char *bitmap_get_buffer(void *bitmap)
+{
+ struct bitmap *bm = bitmap;
+
+ if (bitmap == NULL) {
+ LOG(("NULL bitmap!"));
+ return NULL;
+ }
+
+ return bm->pixdata;
+}
+
+size_t bitmap_buffer_size( void * bitmap )
+{
+ struct bitmap * bm = bitmap;
+ if( bm == NULL )
+ return 0;
+ return( bm->rowstride * bm->height );
+}
+
+
+/**
+ * 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 bitmap_get_rowstride(void *bitmap)
+{
+ struct bitmap *bm = bitmap;
+
+ if (bitmap == NULL) {
+ LOG(("NULL bitmap!"));
+ return 0;
+ }
+ return bm->rowstride;
+}
+
+
+/**
+ * Free a bitmap.
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ */
+
+void bitmap_destroy(void *bitmap)
+{
+ struct bitmap *bm = bitmap;
+
+ if (bitmap == NULL) {
+ LOG(("NULL bitmap!"));
+ return;
+ }
+
+ if( bm->resized != NULL ) {
+ bitmap_destroy(bm->resized);
+ }
+ 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
+ * \return true on success, false on error and error reported
+ */
+
+bool bitmap_save(void *bitmap, const char *path, unsigned flags)
+{
+ return true;
+}
+
+/**
+ * The bitmap image has changed, so flush any persistant cache.
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ */
+void bitmap_modified(void *bitmap)
+{
+ struct bitmap *bm = bitmap;
+
+ if( bm->resized != NULL ) {
+ bitmap_destroy( bm->resized );
+ bm->resized = NULL;
+ }
+}
+
+
+/**
+ * The bitmap image can be suspended.
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ * \param private_word a private word to be returned later
+ * \param suspend the function to be called upon suspension
+ * \param resume the function to be called when resuming
+ */
+void bitmap_set_suspendable(void *bitmap, void *private_word,
+ void (*invalidate)(void *bitmap, void *private_word)) {
+}
+
+/**
+ * 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
+ */
+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
+ */
+bool bitmap_test_opaque(void *bitmap)
+{
+ int tst;
+ struct bitmap *bm = bitmap;
+
+ if (bitmap == NULL) {
+ LOG(("NULL bitmap!"));
+ return false;
+ }
+
+ 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;
+}
+
+
+/**
+ * Gets whether a bitmap should be plotted opaque
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ */
+bool bitmap_get_opaque(void *bitmap)
+{
+ struct bitmap *bm = bitmap;
+
+ if (bitmap == NULL) {
+ LOG(("NULL bitmap!"));
+ return false;
+ }
+
+ return bm->opaque;
+}
+
+int bitmap_get_width(void *bitmap)
+{
+ struct bitmap *bm = bitmap;
+
+ if (bitmap == NULL) {
+ LOG(("NULL bitmap!"));
+ return 0;
+ }
+
+ return(bm->width);
+}
+
+int bitmap_get_height(void *bitmap)
+{
+ struct bitmap *bm = bitmap;
+
+ if (bitmap == NULL) {
+ LOG(("NULL bitmap!"));
+ return 0;
+ }
+ return(bm->height);
+}
+
+size_t bitmap_get_bpp(void *bitmap)
+{
+ struct bitmap *bm = bitmap;
+ return bm->bpp;
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset:8
+ * End:
+ */
diff --git a/atari/bitmap.h b/atari/bitmap.h
new file mode 100644
index 000000000..a1e381095
--- /dev/null
+++ b/atari/bitmap.h
@@ -0,0 +1,44 @@
+/*
+ * 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_BITMAP_H
+#define NS_ATARI_BITMAP_H
+
+#define BITMAP_SHRINK 0
+#define BITMAP_GROW 0x01
+
+struct bitmap {
+ int width;
+ int height;
+ uint8_t *pixdata;
+ bool opaque;
+ short bpp; /* number of BYTES! per pixel */
+ size_t rowstride;
+ struct bitmap * resized;
+};
+
+#define NS_BMP_DEFAULT_BPP 4
+/* calculate MFDB compatible rowstride (in number of pixels!) */
+#define MFDB_STRIDE( w ) (((w & 15) != 0) ? (w | 15)+1 : w)
+
+void * bitmap_create_ex( int w, int h, short bpp, int rowstride, unsigned int state, void * pixdata );
+void bitmap_to_mfdb(void * bitmap, MFDB * out);
+void * bitmap_realloc( int w, int h, short bpp, int rowstride, unsigned int state, void * bmp );
+size_t bitmap_buffer_size( void * bitmap ) ;
+
+#endif
diff --git a/atari/browser.c b/atari/browser.c
new file mode 100644
index 000000000..186900109
--- /dev/null
+++ b/atari/browser.c
@@ -0,0 +1,944 @@
+/*
+ * 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 <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <windom.h>
+#include <cflib.h>
+
+#include "desktop/gui.h"
+#include "desktop/netsurf.h"
+#include "desktop/browser.h"
+#include "desktop/mouse.h"
+#include "desktop/textinput.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+
+#include "atari/gui.h"
+#include "atari/browser_win.h"
+#include "atari/misc.h"
+#include "atari/global_evnt.h"
+#include "atari/browser_win.h"
+#include "atari/res/netsurf.rsh"
+#include "atari/browser.h"
+#include "atari/plot/plotter.h"
+#include "atari/plot.h"
+#include "atari/font.h"
+
+extern browser_mouse_state bmstate;
+extern GEM_PLOTTER plotter;
+extern struct gui_window *input_window;
+
+
+static void __CDECL browser_evnt_wdestroy( WINDOW * c, short buff[8], void * data);
+COMPONENT *comp_widget_create( APPvar *app, WINDOW *win, int size, int flex );
+
+static bool frameinit = true;
+
+
+/* create an browser component */
+struct s_browser * browser_create( struct gui_window * gw,
+ struct browser_window *bw,
+ struct browser_window * clone,
+ enum browser_type type,
+ int lt, int w, int flex )
+{
+ LGRECT cwork;
+ COMPONENT * scrollv, * scrollh, * drawable;
+
+ if( frameinit ) {
+ mt_FrameInit( &app );
+ frameinit = false;
+ }
+
+ CMP_BROWSER bnew = (CMP_BROWSER)malloc( sizeof(struct s_browser) );
+ if( bnew )
+ {
+ memset(bnew, 0, sizeof(struct s_browser) );
+ bnew->type = type;
+ bnew->bw = bw;
+ bnew->attached = false;
+ if(clone)
+ bw->scale = clone->scale;
+ else
+ bw->scale = 1;
+
+ bnew->compwin = mt_WindCreate( &app, VSLIDE|HSLIDE, 40, 40, app.w, app.h);
+ bnew->compwin->w_u = 1;
+ bnew->compwin->h_u = 1;
+ /* needs to be adjusted when content width is known: */
+ bnew->compwin->ypos_max = w;
+ bnew->compwin->xpos_max = w;
+ mt_WindSlider( &app, bnew->compwin, HSLIDER|VSLIDER);
+ bnew->comp = (COMPONENT*)comp_widget_create( (void*)&app, (WINDOW*)bnew->compwin, 100, 1 );
+ if( bnew->comp == NULL ) {
+ free(bnew);
+ return(NULL);
+ }
+ mt_EvntDataAdd( &app, bnew->compwin, WM_XBUTTON,
+ browser_evnt_mbutton, (void*)gw, EV_BOT );
+ mt_CompEvntDataAttach( &app, bnew->comp, WM_REDRAW,
+ browser_evnt_redraw, (void*)gw );
+ mt_EvntDataAttach( &app, bnew->compwin , WM_REDRAW, browser_evnt_redraw_x, NULL );
+ mt_EvntDataAttach( &app, bnew->compwin, WM_SLIDEXY,
+ browser_evnt_slider, gw );
+ mt_EvntDataAttach( &app, bnew->compwin, WM_ARROWED,
+ browser_evnt_arrowed, gw );
+ mt_CompEvntDataAttach( &app, bnew->comp, WM_DESTROY,
+ browser_evnt_destroy, (void*)bnew );
+ /* just stub, as an reminder: */
+ mt_EvntDataAttach( &app, bnew->compwin, WM_DESTROY,
+ browser_evnt_wdestroy, (void*)bnew );
+
+ mt_CompDataAttach( &app, bnew->comp, CDT_OWNER, gw );
+ }
+ return( bnew );
+}
+
+bool browser_destroy( struct s_browser * b )
+{
+ short type = BT_ROOT;
+ LGRECT restore;
+ /* only free the components if it is an root browser,
+ this should delete all attached COMPONENTS...
+ */
+
+ LOG(("%s (%s)\n", b->bw->name, (b->type == BT_ROOT) ? "ROOT" : "FRAME"));
+ assert( b != NULL );
+ assert( b->comp != NULL );
+ assert( b->bw != NULL );
+ struct gui_window * rootgw = browser_find_root( b->bw->window );
+
+ if( b->type == BT_ROOT ) {
+
+ } else if( BT_FRAME ){
+ type = BT_FRAME;
+ } else {
+ assert( 1 == 0 );
+ }
+
+ if( b->compwin != NULL ){
+ COMPONENT * old = b->comp;
+ WINDOW * oldwin = b->compwin;
+ b->comp = NULL;
+ b->compwin = NULL;
+ /* Im not sure if this is the right thing to do (after compdelete above,... */
+ /* listRemove should be used when we just remove an frame... */
+ /* (I encountered spurious events when not doing that...) */
+ /* listRemove( (LINKABLE*) oldwin ); */
+ /* listRemove( (LINKABLE*) old ); */
+ WindDelete( oldwin );
+ mt_CompDelete(&app, old );
+ }
+
+ if( type == BT_FRAME ) {
+ /* TODO: restore the remaining frameset (rebuild???) */
+ }
+ return( true );
+}
+
+bool browser_attach_frame( struct gui_window * container, struct gui_window * frame )
+{
+ struct browser_window * cbw = container->browser->bw;
+ int lt = CLT_STACK;
+ if (cbw->rows >= cbw->cols)
+ lt = CLT_VERTICAL;
+ else
+ lt = CLT_HORIZONTAL;
+ /* todo: if first frame, destroy compwin, create browser frame with old component interface :/ */
+ mt_CompAttach( &app, container->browser->comp, frame->browser->comp );
+ container->browser->comp->type = lt;
+ browser_update_rects( container );
+ container->browser->attached = true;
+ /*browser_update_rects( frame );
+ LGRECT brect;
+ browser_get_rect( frame, BR_CONTENT, &brect );
+ */
+
+}
+
+/* find the root of an frame ( or just return gw if is already the root) */
+struct gui_window * browser_find_root( struct gui_window * gw )
+{
+ if( gw->parent == NULL )
+ return( gw );
+ struct gui_window * g;
+ for( g=window_list; g; g=g->next){
+ if( g->root == gw->root && g->parent == NULL )
+ return( g );
+ }
+ return( NULL );
+}
+
+void browser_get_rect( struct gui_window * gw, enum browser_rect type, LGRECT * out)
+{
+ GRECT work;
+ assert( out != NULL);
+ int slider_v_w = 20;
+ int slider_v_h = 22;
+ int slider_h_w = 20;
+ int slider_h_h = 22;
+
+ WindGetGrect( gw->browser->compwin, WF_WORKXYWH, &work);
+ if( type == BR_CONTENT ){
+ out->g_w = work.g_w;
+ out->g_h = work.g_h;
+ out->g_x = work.g_x;
+ out->g_y = work.g_y;
+ return;
+ }
+
+ LGRECT cur;
+ mt_CompGetLGrect(&app, gw->browser->comp, WF_WORKXYWH, &cur);
+ if( type == BR_HSLIDER ){
+ out->g_x = cur.g_x;
+ out->g_y = cur.g_y + work.g_h;
+ out->g_h = cur.g_h - work.g_h;
+ out->g_w = cur.g_w;
+ }
+
+ if( type == BR_VSLIDER ){
+ out->g_x = cur.g_x + work.g_w;
+ out->g_y = cur.g_y;
+ out->g_w = cur.g_w - work.g_w;
+ out->g_h = work.g_h;
+ }
+
+}
+
+/* Report an resize to the COMPONENT interface */
+void browser_update_rects(struct gui_window * gw )
+{
+ short buff[8];
+ LGRECT cmprect;
+ mt_WindGetGrect( &app, gw->root->handle, WF_CURRXYWH, (GRECT*)&buff[4]);
+ buff[0] = CM_REFLOW;
+ buff[1] = _AESapid;
+ buff[2] = 0;
+ EvntExec(gw->root->handle, buff);
+}
+
+void browser_set_content_size(struct gui_window * gw, int w, int h)
+{
+ CMP_BROWSER b = gw->browser;
+ b->compwin->ypos = 0;
+ b->compwin->xpos = 0;
+ b->compwin->ypos_max = h;
+ b->compwin->xpos_max = w;
+ /* TODO: instead of zeroin, recalculate scroll? */
+ browser_scroll(gw, WA_LFLINE, 0, true );
+ browser_scroll(gw, WA_UPLINE, 0, true );
+ /* force update of scrollbars: */
+ b->scroll.required = true;
+}
+
+static void __CDECL browser_evnt_wdestroy( WINDOW * c, short buff[8], void * data)
+{
+ struct s_browser * b = (struct s_browser*)data;
+ LOG((""));
+}
+
+static void __CDECL browser_evnt_destroy( COMPONENT * c, long buff[8], void * data)
+{
+ struct s_browser * b = (struct s_browser*)data;
+ struct gui_window * gw = b->bw->window;
+ LOG(("%s: %s (%s)\n", __FUNCTION__ ,gw->browser->bw->name, ( gw->browser->type == BT_FRAME) ? "FRAME" : "NOFRAME"));
+
+ assert( b != NULL );
+ assert( gw != NULL );
+ /* TODO: inspect why this assert fails with frames / iframes
+ /* this should have been happened alrdy */
+ /* assert( b->comp == NULL ); */
+
+ free( b );
+ gw->browser = NULL;
+}
+
+
+static void __CDECL browser_evnt_arrowed( WINDOW *win, short buff[8], void * data)
+{
+ bool abs = false;
+ int value = BROWSER_SCROLL_SVAL;
+ struct gui_window * gw = data;
+ LGRECT cwork;
+ browser_get_rect( gw, BR_CONTENT, &cwork );
+
+ switch( buff[4] ) {
+ case WA_UPPAGE:
+ case WA_DNPAGE:
+ value = cwork.g_h;
+ break;
+
+ case WA_LFPAGE:
+ case WA_RTPAGE:
+ value = cwork.g_w;
+ break;
+
+ default:
+ break;
+ }
+ browser_scroll( gw, buff[4], value, abs );
+}
+
+void __CDECL browser_evnt_slider( WINDOW *win, short buff[8], void * data)
+{
+ int dx = buff[4];
+ int dy = buff[5];
+ struct gui_window * gw = data;
+ GRECT work, screen;
+
+ if (!dx && !dy) return;
+
+ /* update the sliders _before_ we call redraw (which might depend on the slider possitions) */
+ mt_WindSlider( &app, win, (dx?HSLIDER:0) | (dy?VSLIDER:0) );
+
+ if( dy > 0 )
+ browser_scroll( gw, WA_DNPAGE, abs(dy), false );
+ else if ( dy < 0)
+ browser_scroll( gw, WA_UPPAGE, abs(dy), false );
+ if( dx > 0 )
+ browser_scroll( gw, WA_RTPAGE, abs(dx), false );
+ else if( dx < 0 )
+ browser_scroll( gw, WA_LFPAGE, abs(dx), false );
+}
+
+static void __CDECL browser_evnt_mbutton( WINDOW * c, short buff[8], void * data)
+{
+ long lbuff[8];
+ short mx,my;
+ browser_mouse_state bms;
+ LGRECT cwork;
+ struct gui_window * gw = data;
+ input_window = gw;
+ window_set_focus( gw, BROWSER, (void*)gw->browser );
+ browser_get_rect( gw, BR_CONTENT, &cwork );
+ SBUF8_TO_LBUF8(buff, lbuff)
+ bms = global_track_evnt_mbutton( gw->root->handle, lbuff, data );
+ mx = evnt.mx - cwork.g_x + gw->browser->scroll.current.x;
+ my = evnt.my - cwork.g_y + gw->browser->scroll.current.y;
+ LOG(("mevent within %s at %d / %d", gw->browser->bw->name, mx, my ));
+ if( bms & BROWSER_MOUSE_DRAG_1) {
+ browser_window_mouse_track(gw->browser->bw, BROWSER_MOUSE_DRAG_1, mx, my );
+ bmstate |= BROWSER_MOUSE_HOLDING_1 | BROWSER_MOUSE_DRAG_ON;
+ LOG(("drag within %s at %d / %d", gw->browser->bw->name, mx, my ));
+ }
+ if( bms & BROWSER_MOUSE_DRAG_2) {
+ browser_window_mouse_track(gw->browser->bw, BROWSER_MOUSE_DRAG_2, mx, my );
+ bmstate |= BROWSER_MOUSE_HOLDING_2 | BROWSER_MOUSE_DRAG_ON;
+ LOG(("drag within %s at %d / %d", gw->browser->bw->name, mx, my ));
+ }
+ if( bms & BROWSER_MOUSE_CLICK_1) {
+ window_set_focus( gw, BROWSER, (void*)gw->browser );
+ browser_window_mouse_click(gw->browser->bw,BROWSER_MOUSE_PRESS_1,mx,my);
+ browser_window_mouse_click(gw->browser->bw,BROWSER_MOUSE_CLICK_1,mx,my);
+ LOG(("Click within %s at %d / %d", gw->browser->bw->name, mx, my ));
+ }
+ if( bms & BROWSER_MOUSE_CLICK_2) {
+ window_set_focus( gw, BROWSER, (void*)gw->browser );
+ browser_window_mouse_click(gw->browser->bw,BROWSER_MOUSE_PRESS_2,mx,my);
+ browser_window_mouse_click(gw->browser->bw,BROWSER_MOUSE_CLICK_2,mx,my);
+ LOG(("Click within %s at %d / %d", gw->browser->bw->name, mx, my ));
+ }
+}
+
+void browser_scroll( struct gui_window * gw, short mode, int value, bool abs )
+{
+ LGRECT work;
+ int max_y_scroll;
+ int max_x_scroll;
+ int oldx = gw->browser->scroll.current.x;
+ int oldy = gw->browser->scroll.current.y;
+ struct s_browser * b = gw->browser;
+ LOG((""));
+ if( gw->browser->bw->current_content == NULL ) {
+ assert( 1 == 0);
+ return;
+ }
+
+ browser_get_rect( gw, BR_CONTENT, &work);
+ max_y_scroll = (content_get_height( b->bw->current_content ) - work.g_h );
+ max_x_scroll = (content_get_width( b->bw->current_content ) - work.g_w);
+
+ switch( mode ) {
+ case WA_UPPAGE:
+ case WA_UPLINE:
+ if( abs == false )
+ b->scroll.requested.y -= value;
+ else
+ b->scroll.requested.y = value - b->scroll.current.y;
+ break;
+
+ case WA_DNPAGE:
+ case WA_DNLINE:
+ if( abs == false )
+ b->scroll.requested.y += value;
+ else
+ b->scroll.requested.y = value - b->scroll.current.y;
+ break;
+
+ case WA_LFPAGE:
+ case WA_LFLINE:
+ if( abs == false )
+ b->scroll.requested.x -= value;
+ else
+ b->scroll.requested.x = value - b->scroll.current.x;
+ break;
+
+ case WA_RTPAGE:
+ case WA_RTLINE:
+ if( abs == false )
+ b->scroll.requested.x += value;
+ else
+ b->scroll.requested.x = value - b->scroll.current.x;
+ break;
+
+ default: break;
+ }
+
+ if( b->scroll.current.y + b->scroll.requested.y < 0 ) {
+ b->scroll.requested.y = -b->scroll.current.y;
+ }
+
+ if( b->scroll.current.y + b->scroll.requested.y > max_y_scroll ) {
+ b->scroll.requested.y = max_y_scroll - b->scroll.current.y;
+ }
+
+ if( b->scroll.current.x + b->scroll.requested.x < 0 ) {
+ b->scroll.requested.x = -b->scroll.current.x;
+ }
+
+ if( b->scroll.current.x + b->scroll.requested.x > max_x_scroll ) {
+ b->scroll.requested.x = max_x_scroll - b->scroll.current.x;
+ }
+
+ if( oldy != b->scroll.current.y + b->scroll.requested.y ||
+ oldx != b->scroll.current.x + b->scroll.requested.x ) {
+ b->scroll.required = true;
+ }
+}
+
+/*
+ perform the requested scrolling.
+ gw -> the browser window to act upon.
+ bwrect -> the dimensions of the browser, so that this function
+ doesn't need to get it.
+*/
+static void browser_process_scroll( struct gui_window * gw, LGRECT bwrect )
+{
+ struct s_browser * b = gw->browser;
+ GRECT src;
+ GRECT dst;
+ short h,w;
+
+ h = (short) abs( b->scroll.requested.y );
+ w = (short) abs( b->scroll.requested.x );
+
+ /* if the request exceeds the browser size, redraw the whole area */
+ if ( b->scroll.requested.y > bwrect.g_h || b->scroll.requested.y < -bwrect.g_h ||
+ b->scroll.requested.x > bwrect.g_w || b->scroll.requested.x < -bwrect.g_w ) {
+ b->scroll.current.y += b->scroll.requested.y;
+ b->scroll.current.x += b->scroll.requested.x;
+ browser_schedule_redraw( gw, 0, 0, bwrect.g_w, bwrect.g_h);
+ /* don't scroll again: */
+ b->scroll.requested.y = 0;
+ b->scroll.requested.x = 0;
+ }
+ if( b->scroll.requested.y < 0 ) {
+ /* scroll up */
+ src.g_x = 0;
+ src.g_y = 0;
+ src.g_w = bwrect.g_w;
+ src.g_h = bwrect.g_h - h;
+ dst.g_x = 0;
+ dst.g_y = h;
+ dst.g_w = src.g_w;
+ dst.g_h = src.g_h;
+ plotter->copy_rect( plotter, src, dst );
+ b->scroll.current.y += b->scroll.requested.y;
+ browser_schedule_redraw( gw, 0, 0, bwrect.g_w, h ) ;
+ }
+
+ if( b->scroll.requested.y > 0 ) {
+ /* scroll down */
+ src.g_x = 0;
+ src.g_y = h;
+ src.g_w = bwrect.g_w;
+ src.g_h = bwrect.g_h - h;
+ dst.g_x = 0;
+ dst.g_y = 0;
+ dst.g_w = bwrect.g_w;
+ dst.g_h = bwrect.g_h - h;
+ plotter->copy_rect( plotter, src, dst );
+ b->scroll.current.y += b->scroll.requested.y;
+ browser_schedule_redraw( gw, 0, bwrect.g_h - h, bwrect.g_w, bwrect.g_h );
+ }
+
+ if( b->scroll.requested.x < 0 ) {
+ /* scroll to the left */
+ src.g_x = 0;
+ src.g_y = 0;
+ src.g_w = bwrect.g_w - w;
+ src.g_h = bwrect.g_h;
+ dst.g_x = w;
+ dst.g_y = 0;
+ dst.g_w = bwrect.g_w - w;
+ dst.g_h = bwrect.g_h;
+ plotter->copy_rect( plotter, src, dst );
+ b->scroll.current.x += b->scroll.requested.x;
+ browser_schedule_redraw( gw, 0, 0, w, bwrect.g_h );
+ }
+
+ if( b->scroll.requested.x > 0 ) {
+ /* scroll to the right */
+ src.g_x = w;
+ src.g_y = 0;
+ src.g_w = bwrect.g_w - w;
+ src.g_h = bwrect.g_h;
+ dst.g_x = 0;
+ dst.g_y = 0;
+ dst.g_w = bwrect.g_w - w;
+ dst.g_h = bwrect.g_h;
+ plotter->copy_rect( plotter, src, dst );
+ b->scroll.current.x += b->scroll.requested.x;
+ browser_schedule_redraw( gw, bwrect.g_w - w, 0, bwrect.g_w, bwrect.g_h );
+ }
+ b->scroll.requested.y = 0;
+ b->scroll.requested.x = 0;
+ gw->browser->compwin->xpos = b->scroll.current.x;
+ gw->browser->compwin->ypos = b->scroll.current.y;
+
+ mt_WindSlider( &app, gw->browser->compwin, HSLIDER|VSLIDER);
+}
+
+
+bool browser_input( struct gui_window * gw, unsigned short nkc )
+{
+ LGRECT work;
+ bool r = false;
+ unsigned char ascii = (nkc & 0xFF);
+ nkc = (nkc & (NKF_CTRL|NKF_SHIFT|0xFF));
+ browser_get_rect(gw, BR_CONTENT, &work);
+
+ if( (nkc & NKF_CTRL) != 0 ) {
+ switch ( ascii ) {
+ case 'A':
+ r = browser_window_key_press(gw->browser->bw, KEY_SELECT_ALL);
+ break;
+
+ case 'C':
+ r = browser_window_key_press(gw->browser->bw, KEY_COPY_SELECTION);
+ break;
+
+ case 'X':
+ r = browser_window_key_press(gw->browser->bw, KEY_CUT_SELECTION);
+ break;
+
+ case 'V':
+ r = browser_window_key_press(gw->browser->bw, KEY_PASTE);
+ break;
+
+ default:
+ break;
+ }
+ }
+ if( (nkc & NKF_SHIFT) != 0 ) {
+ switch( ascii ) {
+
+ case NK_TAB:
+ r = browser_window_key_press(gw->browser->bw, KEY_SHIFT_TAB);
+ break;
+
+ case NK_LEFT:
+ if( browser_window_key_press(gw->browser->bw, KEY_LINE_START) == false) {
+ browser_scroll( gw, WA_LFPAGE, work.g_w, false );
+ r = true;
+ }
+ break;
+
+ case NK_RIGHT:
+ if( browser_window_key_press(gw->browser->bw, KEY_LINE_END) == false) {
+ browser_scroll( gw, WA_RTPAGE, work.g_w, false );
+ r = true;
+ }
+ break;
+
+ case NK_UP:
+ if ( browser_window_key_press(gw->browser->bw, KEY_PAGE_UP) ==false ){
+ browser_scroll( gw, WA_UPPAGE, work.g_h, false );
+ r = true;
+ }
+ break;
+
+ case NK_DOWN:
+ if (browser_window_key_press(gw->browser->bw, KEY_PAGE_DOWN) == false) {
+ browser_scroll( gw, WA_DNPAGE, work.g_h, false );
+ r = true;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ if( (nkc & (NKF_SHIFT|NKF_CTRL) ) == 0 ) {
+ switch( ascii ) {
+ case NK_BS:
+ r = browser_window_key_press(gw->browser->bw, KEY_DELETE_LEFT);
+ break;
+
+ case NK_DEL:
+ r = browser_window_key_press(gw->browser->bw, KEY_DELETE_RIGHT);
+ break;
+
+ case NK_TAB:
+ r = browser_window_key_press(gw->browser->bw, KEY_TAB);
+ break;
+
+
+ case NK_ENTER:
+ r = browser_window_key_press(gw->browser->bw, KEY_NL);
+ break;
+
+ case NK_RET:
+ r = browser_window_key_press(gw->browser->bw, KEY_CR);
+ break;
+
+ case NK_ESC:
+ r = browser_window_key_press(gw->browser->bw, KEY_ESCAPE);
+ break;
+
+ case NK_CLRHOME:
+ r = browser_window_key_press(gw->browser->bw, KEY_TEXT_START);
+ break;
+
+ case NK_RIGHT:
+ if (browser_window_key_press(gw->browser->bw, KEY_RIGHT) == false){
+ browser_scroll( gw, WA_RTLINE, 16, false );
+ r = true;
+ }
+ break;
+
+ case NK_LEFT:
+ if (browser_window_key_press(gw->browser->bw, KEY_LEFT) == false) {
+ browser_scroll( gw, WA_LFLINE, 16, false );
+ r = true;
+ }
+ break;
+
+ case NK_UP:
+ if (browser_window_key_press(gw->browser->bw, KEY_UP) == false) {
+ browser_scroll( gw, WA_UPLINE, 16, false);
+ r = true;
+ }
+ break;
+
+ case NK_DOWN:
+ if (browser_window_key_press(gw->browser->bw, KEY_DOWN) == false) {
+ browser_scroll( gw, WA_DNLINE, 16, false);
+ r = true;
+ }
+ break;
+
+ case NK_M_PGUP:
+ if ( browser_window_key_press(gw->browser->bw, KEY_PAGE_UP) ==false ) {
+ browser_scroll( gw, WA_UPPAGE, work.g_h, false );
+ r = true;
+ }
+ break;
+
+ case NK_M_PGDOWN:
+ if (browser_window_key_press(gw->browser->bw, KEY_PAGE_DOWN) == false) {
+ browser_scroll( gw, WA_DNPAGE, work.g_h, false );
+ r = true;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if( r == false && ( (nkc & NKF_CTRL)==0) ) {
+ if (ascii >= 9 ) {
+ int ucs4 = atari_to_ucs4(ascii);
+ r = browser_window_key_press(gw->browser->bw, ucs4 );
+ }
+ }
+ return( r );
+
+
+/*
+ switch ( nkc ) {
+ case NKF_LSH|NK_UP:
+ case NKF_RSH|NK_UP:
+ case NK_M_PGUP:
+ if ( browser_window_key_press(gw->browser->bw, KEY_PAGE_UP) ==false )
+ browser_scroll( gw, WA_UPPAGE, work.g_h, false );
+ break;
+
+ case NKF_RSH|NK_DOWN:
+ case NKF_LSH|NK_DOWN:
+ case NK_M_PGDOWN:
+ if (browser_window_key_press(gw->browser->bw, KEY_PAGE_DOWN) == false)
+ browser_scroll( gw, WA_DNPAGE, work.g_h, false );
+ break;
+
+
+
+ default:
+ if (ascii != 0) {
+ int ucs4 = atari_to_ucs4(ascii);
+ r = browser_window_key_press(gw->browser->bw, ucs4 );
+ }
+ break;
+ }
+
+ return( r );
+*/
+}
+
+static void __CDECL browser_evnt_redraw_x( WINDOW * c, short buf[8], void * data)
+{
+ /* just an stub to prevent wndclear */
+ /* Probably the browser redraw is better placed here? dunno! */
+ return;
+}
+
+/* determines if a browser window needs redraw */
+bool browser_redraw_required( struct gui_window * gw)
+{
+ bool ret = true;
+ int frames = 0;
+ CMP_BROWSER b = gw->browser;
+
+ {
+ /* don't do redraws if we have subframes */
+ /* iframes will be an special case and must be handled special... */
+ struct gui_window * g;
+ for( g=window_list; g; g=g->next ) {
+ if ( g != gw && g->parent == gw ) {
+ if( g->browser->type == BT_FRAME ) {
+ frames++;
+ }
+ }
+ }
+ }
+ ret = ( (b->redraw.required && frames == 0) || b->scroll.required || b->caret.redraw );
+ return( ret );
+}
+
+
+/* schedule a redraw of content */
+/* coords are relative to the framebuffer */
+void browser_schedule_redraw(struct gui_window * gw, short x0, short y0, short x1, short y1)
+{
+ CMP_BROWSER b = gw->browser;
+ /* TODO: add rectangle to list, instead of summarizing the rect.? */
+ /* otherwise it can result in large areas, altough it isnt needed. ( like 1 px in the upper left,
+ and 1px in bottom right corner )
+ */
+ b->redraw.required = true;
+ b->redraw.area.x0 = MIN(b->redraw.area.x0, x0);
+ b->redraw.area.y0 = MIN(b->redraw.area.y0, y0);
+ b->redraw.area.x1 = MAX(b->redraw.area.x1, x1);
+ b->redraw.area.y1 = MAX(b->redraw.area.y1, y1);
+}
+
+static void browser_redraw_content( struct gui_window * gw, int xoff, int yoff )
+{
+ LGRECT work;
+ CMP_BROWSER b = gw->browser;
+ GRECT area;
+
+ current_redraw_browser = b->bw;
+ LOG(("%s clip: %d,%d - %d,%d\n", b->bw->name, b->redraw.area.x0,
+ b->redraw.area.y0, b->redraw.area.x1, b->redraw.area.y1
+ ));
+ area.g_x = b->redraw.area.x0;
+ area.g_y = b->redraw.area.y0;
+ area.g_w = b->redraw.area.x1 - b->redraw.area.x0;
+ area.g_h = b->redraw.area.y1 - b->redraw.area.y0;
+ assert( area.g_w > 0 && area.g_h > 0 );
+
+ content_redraw( b->bw->current_content,
+ xoff-b->scroll.current.x, yoff-b->scroll.current.y,
+ area.g_w, area.g_h,
+ b->redraw.area.x0, b->redraw.area.y0,
+ b->redraw.area.x1, b->redraw.area.y1,
+ b->bw->scale, 0xFFFFFF);
+ current_redraw_browser = NULL;
+ /* reset redraw area */
+ b->redraw.area.x0 = INT_MAX;
+ b->redraw.area.y0 = INT_MAX;
+ b->redraw.area.x1 = INT_MIN;
+ b->redraw.area.y1 = INT_MIN;
+}
+
+
+void browser_redraw_caret( struct gui_window * gw, GRECT * area )
+{
+ GRECT caret;
+ struct s_browser * b = gw->browser;
+ if( b->caret.redraw == true ){
+ caret = b->caret.requested;
+ caret.g_x -= gw->browser->scroll.current.x;
+ caret.g_y -= gw->browser->scroll.current.y;
+ struct s_clipping oldclip;
+ plot_get_clip( &oldclip );
+ /* clip to cursor: */
+ plot_clip( caret.g_x-1, caret.g_y -1,
+ caret.g_x + caret.g_w + 1, caret.g_y + caret.g_h + 1
+ );
+ plot_rectangle( caret.g_x, caret.g_y,
+ caret.g_x+caret.g_w, caret.g_y+caret.g_h,
+ plot_style_caret );
+ /* restore clip area: */
+ plot_clip( oldclip.x0, oldclip.y0, oldclip.x1,oldclip.y1);
+ b->caret.current = caret;
+ }
+}
+
+void browser_redraw( struct gui_window * gw )
+{
+ LGRECT bwrect;
+ struct s_browser * b = gw->browser;
+ short todo[4];
+
+ if( b->attached == false ) {
+ return;
+ }
+
+ browser_get_rect(gw, BR_CONTENT, &bwrect);
+
+ plotter->resize(plotter, bwrect.g_w, bwrect.g_h);
+ plotter->move(plotter, bwrect.g_x, bwrect.g_y );
+ plotter->clip( plotter, 0, 0, bwrect.g_w, bwrect.g_h );
+
+ if( b->scroll.required == true && b->bw->current_content != NULL) {
+ browser_process_scroll( gw, bwrect );
+ b->scroll.required = false;
+ }
+
+ if (b->redraw.required == true && b->bw->current_content != NULL ) {
+ if( (plotter->flags & PLOT_FLAG_OFFSCREEN) == 0 ) {
+ GRECT area;
+ BBOX cliporg;
+ todo[0] = bwrect.g_x;
+ todo[1] = bwrect.g_y;
+ todo[2] = todo[0] + bwrect.g_w;
+ todo[3] = todo[1] + bwrect.g_h;
+ vs_clip(plotter->vdi_handle, 1, (short*)&todo[0]);
+
+ area.g_x = b->redraw.area.x0;
+ area.g_y = b->redraw.area.y0;
+ area.g_w = b->redraw.area.x1 - b->redraw.area.x0;
+ area.g_h = b->redraw.area.y1 - b->redraw.area.y0;
+ if( wind_get(gw->root->handle->handle, WF_FIRSTXYWH,
+ &todo[0], &todo[1], &todo[2], &todo[3] )!=0 ) {
+ while (todo[2] && todo[3]) {
+ /* convert screen to framebuffer coords: */
+ todo[0] -= bwrect.g_x;
+ todo[1] -= bwrect.g_y;
+ if( todo[0] < 0 ){
+ todo[2] = todo[2] + todo[0];
+ todo[0] = 0;
+ }
+ if( todo[1] < 0 ){
+ todo[3] = todo[3] + todo[1];
+ todo[1] = 0;
+ }
+ if (rc_intersect((GRECT *)&area,(GRECT *)todo)) {
+ b->redraw.area.x0 = todo[0];
+ b->redraw.area.y0 = todo[1];
+ b->redraw.area.x1 = b->redraw.area.x0 + todo[2];
+ b->redraw.area.y1 = b->redraw.area.y0 + todo[3];
+ browser_redraw_content( gw, 0, 0 );
+ }
+ if (wind_get(gw->root->handle->handle, WF_NEXTXYWH,
+ &todo[0], &todo[1], &todo[2], &todo[3])==0) {
+ break;
+ }
+ }
+ }
+ vs_clip(plotter->vdi_handle, 0, (short*)&todo);
+ } else {
+ /* its save to do a complete redraw :) */
+ }
+ b->redraw.required = false;
+ }
+ if( b->caret.redraw == true && b->bw->current_content != NULL ) {
+ GRECT area;
+ todo[0] = bwrect.g_x;
+ todo[1] = bwrect.g_y;
+ todo[2] = todo[0] + bwrect.g_w;
+ todo[3] = todo[1] + bwrect.g_h;
+ area.g_x = bwrect.g_x;
+ area.g_y = bwrect.g_y;
+ area.g_w = bwrect.g_w;
+ area.g_h = bwrect.g_h;
+ vs_clip(plotter->vdi_handle, 1, (short*)&todo[0]);
+ browser_redraw_caret( gw, &area );
+ vs_clip(plotter->vdi_handle, 0, (short*)&todo[0]);
+ b->caret.redraw = false;
+ }
+ /* TODO: if we use offscreen bitmap, trigger content redraw here */
+}
+
+static void __CDECL browser_evnt_redraw( COMPONENT * c, long buff[8], void * data)
+{
+ short pxy[8];
+ WINDOW * w;
+ struct gui_window * gw = (struct gui_window *) data;
+ CMP_BROWSER b = gw->browser;
+ struct gui_window * rgw = browser_find_root( gw );
+ LGRECT work, lclip, rwork;
+ int xoff,yoff,width,heigth;
+ short cw, ch, cellw, cellh;
+ w = (WINDOW*)mt_CompGetPtr( &app, c, CF_WINDOW );
+ browser_get_rect( gw, BR_CONTENT, &work );
+ browser_get_rect( rgw, BR_CONTENT, &rwork );
+ lclip = work;
+ if ( !rc_lintersect( (LGRECT*)&buff[4], &lclip ) ) return;
+
+ if( b->bw->current_content == NULL )
+ return;
+
+ /* convert redraw coords to framebuffer coords: */
+ lclip.g_x -= work.g_x;
+ lclip.g_y -= work.g_y;
+ if( lclip.g_x < 0 ) {
+ lclip.g_w = work.g_w + lclip.g_x;
+ lclip.g_x = 0;
+ }
+ if( lclip.g_y < 0 ) {
+ lclip.g_h = work.g_h + lclip.g_y;
+ lclip.g_y = 0;
+ }
+ if( lclip.g_h > 0 && lclip.g_w > 0 ) {
+ browser_schedule_redraw( gw, lclip.g_x, lclip.g_y,
+ lclip.g_x + lclip.g_w, lclip.g_y + lclip.g_h
+ );
+ }
+
+ return;
+} \ No newline at end of file
diff --git a/atari/browser.h b/atari/browser.h
new file mode 100644
index 000000000..3c71238d0
--- /dev/null
+++ b/atari/browser.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NS_ATARI_BROWSER_H
+#define NS_ATARI_BROWSER_H
+
+/*
+ Each browser_window in the Atari Port is represented by an struct s_browser,
+ which cosnist mainly of an WinDom COMPONENT.
+*/
+
+#define BROWSER_SCROLL_SVAL 64 /* The small scroll inc. value */
+
+enum browser_type
+{
+ BT_ROOT=1,
+ BT_FRAME=2,
+ BT_FRAMESET=3,
+ BT_IFRAME=4
+};
+
+enum browser_rect
+{
+ BR_CONTENT = 1,
+ BR_FULL = 2,
+ BR_HSLIDER = 3,
+ BR_VSLIDER = 4
+};
+
+struct s_browser * browser_create( struct gui_window * gw, struct browser_window * clone, struct browser_window *bw, enum browser_type, int lt, int w, int flex );
+bool browser_destroy( struct s_browser * b );
+void browser_get_rect( struct gui_window * gw, enum browser_rect type, LGRECT * out);
+bool browser_input( struct gui_window * gw, unsigned short nkc ) ;
+void browser_redraw( struct gui_window * gw );
+void browser_set_content_size(struct gui_window * gw, int w, int h);
+void browser_scroll( struct gui_window * gw, short MODE, int value, bool abs );
+bool browser_attach_frame( struct gui_window * container, struct gui_window * frame );
+struct gui_window * browser_find_root( struct gui_window * gw );
+static void browser_process_scroll( struct gui_window * gw, LGRECT bwrect );
+bool browser_redraw_required( struct gui_window * gw);
+void browser_redraw_caret( struct gui_window * gw, GRECT * area );
+static void browser_redraw_content( struct gui_window * gw, int xoff, int yoff );
+
+/* update loc / size of the browser widgets: */
+void browser_update_rects(struct gui_window * gw );
+void browser_schedule_redraw(struct gui_window * gw, short x, short y, short w, short h );
+static void __CDECL browser_evnt_resize( COMPONENT * c, long buff[8], void * data);
+static void __CDECL browser_evnt_destroy( COMPONENT * c, long buff[8], void * data);
+static void __CDECL browser_evnt_mbutton( WINDOW * c, short buff[8], void * data);
+static void __CDECL browser_evnt_arrowed( WINDOW *win, short buff[8], void * data);
+static void __CDECL browser_evnt_slider( WINDOW *win, short buff[8], void * data);
+static void __CDECL browser_evnt_redraw( COMPONENT * c, long buff[8], void * data);
+static void __CDECL browser_evnt_redraw_x( WINDOW * c, short buff[8], void * data);
+
+#endif
diff --git a/atari/browser_win.c b/atari/browser_win.c
new file mode 100644
index 000000000..0f6391d6c
--- /dev/null
+++ b/atari/browser_win.c
@@ -0,0 +1,459 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <windom.h>
+#include <assert.h>
+#include <math.h>
+
+#include "utils/log.h"
+#include "desktop/gui.h"
+#include "desktop/history_core.h"
+#include "desktop/netsurf.h"
+#include "desktop/browser.h"
+#include "desktop/mouse.h"
+#include "desktop/plotters.h"
+
+#include "atari/gui.h"
+#include "atari/browser_win.h"
+#include "atari/browser.h"
+#include "atari/misc.h"
+#include "atari/global_evnt.h"
+#include "atari/res/netsurf.rsh"
+#include "atari/browser.h"
+#include "atari/toolbar.h"
+#include "atari/statusbar.h"
+#include "atari/plot/plotter.h"
+
+
+bool cfg_rt_resize = false;
+bool cfg_rt_move = false;
+extern void * h_gem_rsrc;
+extern struct gui_window *input_window;
+extern GEM_PLOTTER plotter;
+
+void __CDECL std_szd( WINDOW * win, short buff[8], void * );
+void __CDECL std_mvd( WINDOW * win, short buff[8], void * );
+
+/* -------------------------------------------------------------------------- */
+/* Module public functions: */
+/* -------------------------------------------------------------------------- */
+
+
+static void __CDECL evnt_window_arrowed( WINDOW *win, short buff[8], void *data )
+{
+ bool abs = false;
+ LGRECT cwork;
+ int value = BROWSER_SCROLL_SVAL;
+
+ if( input_window == NULL ) {
+ return;
+ }
+
+ browser_get_rect( input_window, BR_CONTENT, &cwork );
+
+ switch( buff[4] ) {
+ case WA_UPPAGE:
+ case WA_DNPAGE:
+ value = cwork.g_h;
+ break;
+
+
+ case WA_LFPAGE:
+ case WA_RTPAGE:
+ value = cwork.g_w;
+ break;
+
+ default:
+ break;
+ }
+ browser_scroll( input_window, buff[4], value, abs );
+}
+
+int window_create( struct gui_window * gw, struct browser_window * bw, unsigned long inflags)
+{
+ short buff[8];
+ OBJECT * tbtree;
+ int err = 0;
+ bool tb, sb;
+ tb = (inflags & WIDGET_TOOLBAR );
+ sb = (inflags & WIDGET_STATUSBAR);
+ short w,h, wx, wy, wh, ww;
+ int flags = CLOSER | MOVER | NAME | FULLER | SMALLER ;
+ gw->parent = NULL;
+ gw->root = malloc( sizeof(struct s_gui_win_root) );
+ if( gw->root == NULL )
+ return( -1 );
+ gw->root->handle = WindCreate( flags,40, 40, app.w, app.h );
+ gw->root->cmproot = mt_CompCreate(&app, CLT_VERTICAL, 1, 1);
+ WindSetPtr( gw->root->handle, WF_COMPONENT, gw->root->cmproot, NULL);
+
+ if( tb ) {
+ gw->root->toolbar = tb_create( gw );
+ assert( gw->root->toolbar );
+ mt_CompAttach( &app, gw->root->cmproot, gw->root->toolbar->comp );
+
+ } else {
+ gw->root->toolbar = NULL;
+ }
+
+ gw->browser = browser_create( gw, bw, NULL, BT_ROOT, CLT_HORIZONTAL, 1, 1 );
+ mt_CompAttach( &app, gw->root->cmproot, gw->browser->comp );
+
+ if( sb ) {
+ gw->root->statusbar = sb_create( gw );
+ mt_CompAttach( &app, gw->root->cmproot, gw->root->statusbar->comp );
+ } else {
+ gw->root->statusbar = NULL;
+ }
+
+ WindSetStr(gw->root->handle, WF_ICONTITLE, (char*)"NetSurf");
+ EvntDataAttach( gw->root->handle, WM_CLOSED, evnt_window_close, NULL );
+
+ /* capture resize/move events so we can handle that manually */
+ if( !cfg_rt_resize ) {
+ EvntAttach( gw->root->handle, WM_SIZED, evnt_window_resize);
+ } else {
+ EvntAdd( gw->root->handle, WM_SIZED, evnt_window_rt_resize, EV_BOT );
+ }
+ if( !cfg_rt_move ) {
+ EvntAttach( gw->root->handle, WM_MOVED, evnt_window_move );
+ } else {
+ EvntAdd( gw->root->handle, WM_MOVED, evnt_window_rt_resize, EV_BOT );
+ }
+ EvntAttach( gw->root->handle, WM_FORCE_MOVE, evnt_window_rt_resize );
+ EvntDataAdd( gw->root->handle, WM_DESTROY,evnt_window_destroy, NULL, EV_TOP );
+ EvntDataAdd( gw->root->handle, WM_ARROWED,evnt_window_arrowed, NULL, EV_TOP );
+ EvntDataAdd( gw->root->handle, WM_NEWTOP, evnt_window_newtop, &evnt_data, EV_BOT);
+ EvntDataAdd( gw->root->handle, WM_TOPPED, evnt_window_newtop, &evnt_data, EV_BOT);
+ EvntDataAttach( gw->root->handle, WM_ICONDRAW, evnt_window_icondraw, gw);
+
+ /*
+ OBJECT * tbut;
+ RsrcGaddr( h_gem_rsrc, R_TREE, FAVICO , &tbut );
+ window_set_icon(gw, &tbut[]);
+ */
+ /* TODO: check if window is openend as "foreground" window... */
+ window_set_focus( gw, BROWSER, gw->browser);
+ return (err);
+}
+
+int window_destroy( struct gui_window * gw)
+{
+ short buff[8];
+ int err = 0;
+
+ if( gw->browser->type != BT_ROOT ) {
+ return(0);
+ }
+
+ /* test this with frames: */
+ /* assert( gw->parent == NULL); */
+
+ if( input_window == gw )
+ input_window = NULL;
+
+ if( gw->root ) {
+ if( gw->root->toolbar )
+ tb_destroy( gw->root->toolbar );
+
+ if( gw->root->statusbar )
+ sb_destroy( gw->root->statusbar );
+ }
+
+ LOG(("Freeing browser window"));
+ if( gw->browser )
+ browser_destroy( gw->browser );
+
+ /* destroy the icon: */
+ /*window_set_icon(gw, NULL, false );*/
+
+ /* needed? */ /*listRemove( (LINKABLE*)gw->root->cmproot ); */
+ LOG(("Freeing root window"));
+ if( gw->root ) {
+ if( gw->root->cmproot )
+ mt_CompDelete( &app, gw->root->cmproot );
+ ApplWrite( _AESapid, WM_DESTROY, gw->root->handle->handle, 0, 0, 0, 0);
+ EvntWindom( MU_MESAG );
+ gw->root->handle = NULL;
+ free( gw->root );
+ gw->root = NULL;
+ }
+ return( err );
+}
+
+void window_open( struct gui_window * gw)
+{
+ LGRECT br;
+ WindOpen(gw->root->handle, 20, 20, app.w/2, app.h/2 );
+ /* apply focus to the root frame: */
+ long lfbuff[8] = { CM_GETFOCUS };
+ mt_CompEvntExec( gl_appvar, gw->browser->comp, lfbuff );
+ /* recompute the nested component sizes and positions: */
+ browser_update_rects( gw );
+ browser_get_rect( gw, BR_CONTENT, &br );
+ plotter->move( plotter, br.g_x, br.g_y );
+ plotter->resize( plotter, br.g_w, br.g_h );
+ gw->browser->attached = true;
+ snd_rdw( gw->root->handle );
+}
+
+/*
+TODO
+void window_set_icon(struct gui_window * gw, void * data, bool is_rsc )
+{
+ #define CDT_ICON_TYPE_OBJECT 1UL
+ #define CDT_ICON_TYPE_BITMAP 2UL
+ void * prev_type;
+ void * ico = DataSearch(&app, gw->root->handle, CDT_ICON );
+ if(ico != NULL) {
+ prev_type = DataSearch(&app, gw->root->handle, CDT_ICON_TYPE );
+ if( prev_type == (void*)CDT_ICON_TYPE_OBJECT ){
+ mt_ObjcFree( &app, (OBJECT*)ico );
+ }
+ if( prev_type == (void*)CDT_ICON_TYPE_BITMAP ){
+ bitmap_destroy(ico);
+ }
+ }
+ if( data != NULL ) {
+ DataAttach( &app, gw->root->handle, CDT_ICON, data);
+ if(is_rsc) {
+ DataAttach( &app, gw->root->handle, CDT_ICON_TYPE, CDT_ICON_TYPE_OBJECT);
+ } else {
+ DataAttach( &app, gw->root->handle, CDT_ICON_TYPE, CDT_ICON_TYPE_BITMAP);
+ }
+ }
+ #undef CDT_ICON_TYPE_OBJECT
+ #undef CDT_ICON_TYPE_BITMAP
+}
+*/
+
+
+/* update back forward buttons (see tb_update_buttons (bug) ) */
+void window_update_back_forward( struct gui_window * gw)
+{
+ tb_update_buttons( gw );
+}
+
+static void window_redraw_controls(struct gui_window *gw, uint32_t flags)
+{
+ LGRECT rect;
+ /* redraw sliders manually, dunno why this is needed (mt_WindSlider should do the job anytime)!*/
+
+ browser_get_rect( gw, BR_VSLIDER, &rect);
+ ApplWrite( _AESapid, WM_REDRAW, gw->root->handle->handle,
+ rect.g_x, rect.g_y, rect.g_w, rect.g_h );
+
+ browser_get_rect( gw, BR_HSLIDER, &rect);
+ ApplWrite( _AESapid, WM_REDRAW, gw->root->handle->handle,
+ rect.g_x, rect.g_y, rect.g_w, rect.g_h );
+
+ /* send redraw to toolbar & statusbar & scrollbars: */
+ mt_CompGetLGrect(&app, gw->root->toolbar->comp, WF_WORKXYWH, &rect);
+ ApplWrite( _AESapid, WM_REDRAW, gw->root->handle->handle,
+ rect.g_x, rect.g_y, rect.g_w, rect.g_h );
+ mt_CompGetLGrect(&app, gw->root->statusbar->comp, WF_WORKXYWH, &rect);
+ ApplWrite( _AESapid, WM_REDRAW, gw->root->handle->handle,
+ rect.g_x, rect.g_y, rect.g_w, rect.g_h );
+}
+
+/* set focus to an arbitary element */
+void window_set_focus( struct gui_window * gw, enum focus_element_type type, void * element )
+{
+ if( gw->root->focus.type != type || gw->root->focus.element != element ) {
+ LOG(("Set focus: %p (%d)\n", element, type));
+ gw->root->focus.type = type;
+ gw->root->focus.element = element;
+ }
+}
+
+/* check if the url widget has focus */
+bool window_url_widget_has_focus( struct gui_window * gw )
+{
+ assert( gw );
+ assert( gw->root );
+ if( gw->root->focus.type == URL_WIDGET && gw->root->focus.element != NULL ) {
+ assert( ( &gw->root->toolbar->url == (struct s_url_widget*)gw->root->focus.element ) );
+ assert( GUIWIN_VISIBLE(gw) );
+ return true;
+ }
+ return false;
+}
+
+/* check if an arbitary window widget / or frame has the focus */
+bool window_widget_has_focus( struct gui_window * gw, enum focus_element_type t, void * element )
+{
+ if( gw == NULL )
+ return( false );
+ if( element == NULL ){
+ assert( 1 != 0 );
+ return( (gw->root->focus.type == t ) );
+ }
+ assert( gw->root != NULL );
+ return( ( element == gw->root->focus.element && t == gw->root->focus.type) );
+}
+
+/* -------------------------------------------------------------------------- */
+/* Non Public Modul event handlers: */
+/* -------------------------------------------------------------------------- */
+static void __CDECL evnt_window_destroy( WINDOW *win, short buff[8], void *data )
+{
+ LOG(("%s\n", __FUNCTION__ ));
+
+ if( data )
+ free( data );
+}
+
+static void __CDECL evnt_window_close( WINDOW *win, short buff[8], void *data )
+{
+ struct gui_window * gw = find_root_gui_window( win );
+ if( gw != NULL ) {
+ browser_window_destroy( gw->browser->bw );
+ }
+}
+
+
+static void __CDECL evnt_window_newtop( WINDOW *win, short buff[8], void *data )
+{
+ input_window = find_root_gui_window( win );
+ LOG(("newtop: iw: %p, win: %p", input_window, win ));
+ assert( input_window != NULL );
+
+ window_redraw_controls(input_window, 0);
+}
+
+static void __CDECL evnt_window_shaded( WINDOW *win, short buff[8], void *data )
+{
+ if(buff[0] == WM_SHADED){
+ LOG(("WM_SHADED, vis: %d, state: %d", GEMWIN_VISIBLE(win), win->status ));
+ }
+ if(buff[0] == WM_UNSHADED){
+
+ }
+}
+
+static void __CDECL evnt_window_icondraw( WINDOW *win, short buff[8], void * data )
+{
+ short x,y,w,h;
+ struct gui_window * gw = (struct gui_window*)data;
+ bool has_favicon = false;
+
+ WindClear( win);
+ WindGet( win, WF_WORKXYWH, &x, &y, &w, &h);
+
+ if( has_favicon == false ) {
+ OBJECT * tree;
+ RsrcGaddr( h_gem_rsrc, R_TREE, ICONIFY , &tree );
+ tree->ob_x = x;
+ tree->ob_y = y;
+ tree->ob_width = w;
+ tree->ob_height = h;
+ mt_objc_draw( tree, 0, 8, buff[4], buff[5], buff[6], buff[7], app.aes_global );
+ }
+}
+
+static void __CDECL evnt_window_move( WINDOW *win, short buff[8] )
+{
+ short mx,my, mb, ks;
+ short wx, wy, wh, ww, nx, ny;
+ short r;
+ short xoff, yoff;
+ if( cfg_rt_move ) {
+ std_mvd( win, buff, &app );
+ evnt_window_rt_resize( win, buff );
+ } else {
+ wind_get( win->handle, WF_CURRXYWH, &wx, &wy, &ww, &wh );
+ if( graf_dragbox( ww, wh, wx, wy, app.x-ww, app.y, app.w+ww, app.h+wh, &nx, &ny )){
+ buff[4] = nx;
+ buff[5] = ny;
+ buff[6] = ww;
+ buff[7] = wh;
+ std_mvd( win, buff, &app );
+ evnt_window_rt_resize( win, buff );
+ }
+ }
+}
+
+void __CDECL evnt_window_resize( WINDOW *win, short buff[8] )
+{
+ short mx,my, mb, ks;
+ short wx, wy, wh, ww, nw, nh;
+ short r;
+ graf_mkstate( &mx, &my, &mb, &ks );
+ if( cfg_rt_resize ) {
+ std_szd( win, buff, &app );
+ evnt_window_rt_resize( win, buff );
+ } else {
+ wind_get( win->handle, WF_CURRXYWH, &wx, &wy, &ww, &wh );
+ r = graf_rubberbox(wx, wy, 20, 20, &nw, &nh);
+ if( nw < 40 && nw < 40 )
+ return;
+ buff[4] = wx;
+ buff[5] = wy;
+ buff[6] = nw;
+ buff[7] = nh;
+ std_szd( win, buff, &app );
+ evnt_window_rt_resize( win, buff );
+ }
+}
+
+/* perform the actual resize */
+static void __CDECL evnt_window_rt_resize( WINDOW *win, short buff[8] )
+{
+ short x,y,w,h;
+ struct gui_window * gw;
+ LGRECT rect;
+ bool resized;
+ bool moved;
+
+ if(buff[0] == WM_FORCE_MOVE ) {
+ std_mvd(win, buff, &app);
+ std_szd(win, buff, &app);
+ }
+
+ wind_get( win->handle, WF_WORKXYWH, &x, &y, &w, &h );
+ gw = find_root_gui_window( win );
+
+ assert( gw != NULL );
+
+ if(gw->root->loc.g_x != x || gw->root->loc.g_y != y ){
+ moved = true;
+ gw->root->loc.g_x = x;
+ gw->root->loc.g_y = y;
+ browser_update_rects( gw );
+ }
+
+ if(gw->root->loc.g_w != w || gw->root->loc.g_h != h ){
+ resized = true;
+ /* report resize to component interface: */
+ browser_update_rects( gw );
+ browser_get_rect( gw, BR_CONTENT, &rect );
+ if( gw->browser->bw->current_content != NULL )
+ browser_window_reformat(gw->browser->bw, rect.g_w, rect.g_h );
+ gw->root->toolbar->url.scrollx = 0;
+ window_redraw_controls(gw, 0);
+ /* TODO: recalculate scroll position, istead of zeroing? */
+ }
+}
diff --git a/atari/browser_win.h b/atari/browser_win.h
new file mode 100644
index 000000000..61f98bb64
--- /dev/null
+++ b/atari/browser_win.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NS_ATARI_BROWSER_WIN_H
+#define NS_ATARI_BROWSER_WIN_H
+
+#define GUIWIN_VISIBLE(gw) (gw->root->handle->status & WS_OPEN)
+#define GEMWIN_VISIBLE(win) (win->status & WS_OPEN)
+
+#define WIDGET_STATUSBAR 0x1
+#define WIDGET_TOOLBAR 0x2
+
+/* WinDom & Custom bindings for gui window */
+
+/* -------------------------------------------------------------------------- */
+/* Public module functions: */
+/* -------------------------------------------------------------------------- */
+
+/* Creates an normal Browser window with [toolbar], [statusbar] */
+int window_create( struct gui_window * gw, struct browser_window * bw, unsigned long flags );
+/* Destroys WinDom part of gui_window */
+int window_destroy( struct gui_window * gw );
+
+/* show the window */
+void window_open( struct gui_window * gw);
+
+void window_snd_redraw(struct gui_window * gw, short x, short y, short w, short h );
+/* Update Shade / Unshade state of the fwd/back buttons*/
+void window_update_back_forward(struct gui_window * gw);
+/* set root browser component: */
+void window_attach_browser( struct gui_window * gw, CMP_BROWSER b);
+
+/* set focus element */
+void window_set_focus( struct gui_window * gw, enum focus_element_type type, void * element );
+/* adjust scroll settings */
+void window_set_scroll_info(struct gui_window *gw, int content_h, int content_w);
+/* Shade / Unshade the forward/back bt. of toolbar, depending on history.*/
+bool window_widget_has_focus( struct gui_window * gw, enum focus_element_type t, void * element);
+bool window_url_widget_has_focus( struct gui_window * gw );
+void window_set_url( struct gui_window * gw, const char * text);
+void window_center(struct gui_window * gw);
+//void window_set_icon(struct gui_window * gw, void * data, bool is_rsc );
+
+
+/* -------------------------------------------------------------------------- */
+/* Public event handlers: */
+/* -------------------------------------------------------------------------- */
+
+
+/* -------------------------------------------------------------------------- */
+/* Static module methods follow here: */
+/* -------------------------------------------------------------------------- */
+static void evnt_toolbar_click(WINDOW * win, short buf[8]);
+static void __CDECL evnt_window_redraw( WINDOW *win, short buff[8], void *data );
+static void __CDECL evnt_window_icondraw( WINDOW *win, short buff[8], void *data );
+static void __CDECL evnt_window_newtop( WINDOW *win, short buff[8], void *data );
+void __CDECL evnt_window_resize( WINDOW *win, short buff[8] );
+static void __CDECL evnt_window_move( WINDOW *win, short buff[8] );
+static void __CDECL evnt_window_rt_resize( WINDOW *win, short buff[8] );
+static void __CDECL evnt_window_close( WINDOW *win, short buff[8], void *data );
+static void __CDECL evnt_window_destroy( WINDOW *win, short buff[8], void *data );
+static void __CDECL evnt_window_keybd(WINDOW *win, short buff[8], void *data );
+static void __CDECL evnt_window_mbutton(WINDOW *win, short buff[8], void *data );
+#endif
diff --git a/atari/clipboard.h b/atari/clipboard.h
new file mode 100644
index 000000000..e505d9f6d
--- /dev/null
+++ b/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( APPvar app, char *str);
+char *scrap_txt_read( APPvar app );
+
+#endif \ No newline at end of file
diff --git a/atari/doc/bugs b/atari/doc/bugs
new file mode 100644
index 000000000..232347a5d
--- /dev/null
+++ b/atari/doc/bugs
@@ -0,0 +1,5 @@
+BUGS
+
+ - On native Ataris there is an Problem with Redraw & Mouse Cursor
+ - Visiting pages that contain frames: undefined behavior
+ \ No newline at end of file
diff --git a/atari/doc/readme.txt b/atari/doc/readme.txt
new file mode 100644
index 000000000..39b34027a
--- /dev/null
+++ b/atari/doc/readme.txt
@@ -0,0 +1,30 @@
+Known bugs & Missing Features:
+------------------------------
+
+- Frames are not implemented - if you hit an page with frames, you are advised to close the window and open a
+ new one.
+- Many of the Menu items are not working yet.
+- No Bookmarks & No History
+- No Download Manager
+- The browser window can only be resized after a page has been loaded.
+- removing the selection from the URL bar just works with backspace key,
+ del doesn't work.
+
+Things to test:
+---------------
+
+- Networking code
+- SSL
+- Window Redraw - sometimes it looks like the page is redrawn all the times... (ebay...)
+ When you start to scroll, this stops.
+ Find out if the redraw stops at some point without the need of the user interaction.
+- Navigate to a lot of pages, note the ones that crashed, please don't report pages that you visited
+ after visiting pages with frames... Make sure you don't call pages with frames. I know that it's not working,
+ and I know that it can cause BUGS.
+- Have a look at the memory usage...
+- Copy & Paste ( please don't report unsupported characters, I know it's not perfect)
+ Doing selections with the mouse (Press mouse key and wait until statusbar says "selecting") is not working so well...
+ But you can use CTRL+A to select everything. Try it.
+
+
+ \ No newline at end of file
diff --git a/atari/doc/todo b/atari/doc/todo
new file mode 100644
index 000000000..1fe4abd04
--- /dev/null
+++ b/atari/doc/todo
@@ -0,0 +1,33 @@
+TODO's (no priority order)
+
+ - Optimize drawing of 1px width / height tiled bitmaps (stretch)
+ - Optimize remove / redraw of caret, use pixbuffer instead?
+ - Optimize drawing of bitmaps on Low-Memory machines
+ - Optimize Clipping for Plotters ( use OS clipping instead of own clipping )
+ - Restore the Palette when Windows get's the Focus
+ - Make drawing of tiled bitmaps optional
+ - Implement TreeView
+ - Implement TreeView Hotlits
+ - Implement TreeView History
+ - Implement TreeView SSL Dialog
+ - Implement Native Select Menu
+ - Implement Frames (?)
+ - Implement IFrames
+ - Implement offscreen plotter
+ - Implement Options Dialog
+ - Implement Favicon Display
+ - Optimize behaviour when windows gets the newtop,
+ set focus to the frame where the click occured,
+ not just the frame container.
+ - Replace RSC strings with string from messages file.
+ - Implement Selection within URL Widget by depressing SHIFT + Mouse Click
+ - Implement Home / End Cursors within the URL Widget
+ - Test pages that use a refferer.
+ - Optimize Offscreen Plotter: Save inactive framebuffers to disk?
+ - Ensure that a font-face is set to the default font when it couldn't be loaded.
+ - Loose focus for browser / url widget etc. when changing focus
+ ( at best, implement callback for this...)
+ - Yahoo.de / .com etc. still crashes - this is probably not an Atari-Version
+ fault, but applies to all other netsurf versions.
+
+ \ No newline at end of file
diff --git a/atari/download.c b/atari/download.c
new file mode 100644
index 000000000..b03af177c
--- /dev/null
+++ b/atari/download.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdbool.h>
+#include <windom.h>
+#include <hubbub/hubbub.h>
+
+#include "content/urldb.h"
+#include "content/fetch.h"
+#include "css/utils.h"
+#include "desktop/gui.h"
+#include "desktop/history_core.h"
+#include "desktop/plotters.h"
+#include "desktop/netsurf.h"
+#include "desktop/options.h"
+#include "desktop/save_complete.h"
+#include "desktop/selection.h"
+#include "desktop/textinput.h"
+#include "render/html.h"
+#include "utils/url.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/utils.h"
+
+#include "atari/gui.h"
+
+struct gui_download_window *gui_download_window_create(download_context *ctx,
+ struct gui_window *parent)
+{
+ return NULL;
+}
+
+nserror gui_download_window_data(struct gui_download_window *dw,
+ const char *data, unsigned int size)
+{
+ return NSERROR_OK;
+}
+
+void gui_download_window_error(struct gui_download_window *dw,
+ const char *error_msg)
+{
+}
+
+void gui_download_window_done(struct gui_download_window *dw)
+{
+} \ No newline at end of file
diff --git a/atari/download.h b/atari/download.h
new file mode 100644
index 000000000..e6bff590a
--- /dev/null
+++ b/atari/download.h
@@ -0,0 +1,22 @@
+/*
+ * 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
+
+#endif
diff --git a/atari/filetype.c b/atari/filetype.c
new file mode 100644
index 000000000..85cfc59cd
--- /dev/null
+++ b/atari/filetype.c
@@ -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/>.
+ */
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "utils/messages.h"
+#include "utils/utils.h"
+#include "utils/url.h"
+#include "utils/log.h"
+#include "content/fetch.h"
+
+
+/**
+ * filetype -- determine the MIME type of a local file
+ */
+const char *fetch_filetype(const char *unix_path)
+{
+ int l;
+ LOG(("unix path %s", unix_path));
+ l = strlen(unix_path);
+ /* This line is adding for devlopment versions running from the root dir: */
+ if (2 < l && strcasecmp(unix_path + l - 3, "f79") == 0)
+ return "text/css";
+ if (2 < l && strcasecmp(unix_path + l - 3, "css") == 0)
+ return "text/css";
+ if (2 < l && strcasecmp(unix_path + l - 3, "jpg") == 0)
+ return "image/jpeg";
+ if (3 < l && strcasecmp(unix_path + l - 4, "jpeg") == 0)
+ return "image/jpeg";
+ if (2 < l && strcasecmp(unix_path + l - 3, "gif") == 0)
+ return "image/gif";
+ if (2 < l && strcasecmp(unix_path + l - 3, "png") == 0)
+ return "image/png";
+ if (2 < l && strcasecmp(unix_path + l - 3, "jng") == 0)
+ return "image/jng";
+ if (2 < l && strcasecmp(unix_path + l - 3, "svg") == 0)
+ return "image/svg";
+ return "text/html";
+}
+
+
+char *fetch_mimetype(const char *ro_path)
+{
+ return strdup("text/plain");
+} \ No newline at end of file
diff --git a/atari/findfile.c b/atari/findfile.c
new file mode 100644
index 000000000..befe0eeb5
--- /dev/null
+++ b/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 <limits.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <curl/curl.h>
+
+#include "utils/log.h"
+#include "utils/url.h"
+
+#include "atari/findfile.h"
+
+char *path_to_url(const char *path)
+{
+ int urllen = strlen(path) + FILE_SCHEME_PREFIX_LEN + 1;
+ char *url = malloc(urllen);
+
+ if (*path == '/') {
+ path++; /* file: paths are already absolute */
+ }
+
+ snprintf(url, urllen, "%s%s", FILE_SCHEME_PREFIX, path);
+
+ return url;
+}
+
+
+char *url_to_path(const char *url)
+{
+ char *url_path = curl_unescape(url, 0);
+ char *path;
+
+ /* return the absolute path including leading / */
+ path = strdup(url_path + (FILE_SCHEME_PREFIX_LEN - 1));
+ curl_free(url_path);
+
+ return path;
+}
+
+/**
+ * Locate a shared resource file by searching known places in order.
+ *
+ * \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
+ *
+ * Search order is: ./, NETSURF_GEM_RESPATH, ./$HOME/.netsurf/, $NETSURFRES/ (where NETSURFRES is an
+ * environment variable),
+ */
+#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 (realpath(t, buf) != NULL) {
+ if (access(buf, R_OK) == 0) {
+ return buf;
+ }
+ }
+
+ strcpy(t, "./");
+ strcat(t, filename);
+ LOG(("checking %s", (char*)&t));
+ if (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 (realpath(t, buf) != NULL) {
+ if (access(buf, R_OK) == 0)
+ return buf;
+ }
+ }
+
+ cdir = getenv("NETSURFRES");
+
+ if (cdir != NULL) {
+ if (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 (realpath(t, buf) == NULL) {
+ strcpy(buf, t);
+ }
+ } else {
+ LOG(("checking %s", (char*)def));
+ if (realpath(def, buf) == NULL) {
+ strcpy(buf, def);
+ }
+ }
+
+ return buf;
+}
+
+
+/*
+ * Local Variables:
+ * c-basic-offset: 8
+ * End:
+ */
+
diff --git a/atari/findfile.h b/atari/findfile.h
new file mode 100644
index 000000000..8c806ba64
--- /dev/null
+++ b/atari/findfile.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2008 Daniel Silverstone <dsilvers@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_FINDFILE_H
+#define NS_ATARI_FINDFILE_H
+
+extern char *atari_find_resource(char *buf, const char *filename, const char *def);
+
+#endif /* NETSURF_ATARI_FINDFILE_H */
diff --git a/atari/font.c b/atari/font.c
new file mode 100644
index 000000000..fb23abd26
--- /dev/null
+++ b/atari/font.c
@@ -0,0 +1,120 @@
+/*
+ * 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 <windom.h>
+
+#include <ft2build.h>
+#include FT_CACHE_H
+
+#include "css/css.h"
+#include "render/font.h"
+#include "utils/utf8.h"
+#include "utils/log.h"
+#include "desktop/options.h"
+#include "desktop/mouse.h"
+#include "desktop/plotters.h"
+
+#include "atari/gui.h"
+#include "atari/font.h"
+#include "atari/plot.h"
+#include "atari/options.h"
+#include "atari/findfile.h"
+#include "atari/gui.h"
+#include "atari/plot.h"
+#include "atari/plot/plotter.h"
+
+extern GEM_FONT_PLOTTER fplotter;
+
+/* TODO: this need a rework..., encoding to atari st doesn|t always work. ( gui_add_to_clipboard...) */
+utf8_convert_ret utf8_to_local_encoding(const char *string,
+ size_t len,
+ char **result)
+{
+ utf8_convert_ret r;
+ r = utf8_to_enc(string, "ATARIST", len, result);
+ if(r != UTF8_CONVERT_OK) {
+ r = utf8_to_enc(string, "UTF-8", len, result);
+ assert( r == UTF8_CONVERT_OK );
+ }
+ return r;
+}
+
+utf8_convert_ret local_encoding_to_utf8(const char *string,
+ size_t len,
+ char **result)
+{
+ return utf8_from_enc(string, "ATARIST", len, result);
+}
+
+
+/* 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 bool atari_font_position_in_string(const plot_font_style_t * fstyle,const char *string,
+ size_t length,int x, size_t *char_offset, int *actual_x )
+{
+ fplotter->pixel_position(fplotter, fstyle, string, length, x, char_offset, actual_x );
+ return( true );
+}
+
+static bool atari_font_split( const plot_font_style_t * fstyle, const char *string,
+ size_t length,int x, size_t *char_offset, int *actual_x )
+{
+ fplotter->str_split( fplotter, fstyle, string, length, x, char_offset, actual_x );
+ return( true );
+}
+
+static bool atari_font_width( const plot_font_style_t *fstyle, const char * str,
+ size_t length, int * width )
+{
+ fplotter->str_width( fplotter, fstyle, str, length, width );
+ return( true );
+}
+
+const struct font_functions nsfont = {
+ atari_font_width,
+ atari_font_position_in_string,
+ atari_font_split
+};
+
+
diff --git a/atari/font.h b/atari/font.h
new file mode 100644
index 000000000..72271803e
--- /dev/null
+++ b/atari/font.h
@@ -0,0 +1,31 @@
+/*
+ * 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_FT_FONT_H
+#define NS_ATARI_FT_FONT_H
+
+#include "utils/utf8.h"
+
+utf8_convert_ret local_encoding_to_utf8(const char *string,
+ size_t len,
+ char **result);
+
+int atari_to_ucs4( unsigned char atarichar);
+
+#endif /* NETSURF_FB_FONT_H */
+
diff --git a/atari/global_evnt.c b/atari/global_evnt.c
new file mode 100644
index 000000000..335fa1d4e
--- /dev/null
+++ b/atari/global_evnt.c
@@ -0,0 +1,760 @@
+/*
+ * 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 <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <windom.h>
+#include <cflib.h>
+
+#include "desktop/gui.h"
+#include "desktop/netsurf.h"
+#include "desktop/browser.h"
+#include "desktop/mouse.h"
+#include "desktop/textinput.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+
+#include "atari/gui.h"
+#include "atari/browser_win.h"
+#include "atari/toolbar.h"
+#include "atari/browser.h"
+#include "atari/hotlist.h"
+#include "atari/misc.h"
+#include "atari/global_evnt.h"
+#include "atari/browser_win.h"
+#include "atari/res/netsurf.rsh"
+
+extern const char * cfg_homepage_url;
+extern struct gui_window *input_window;
+extern OBJECT * h_gem_menu;
+extern int mouse_click_time[3];
+extern int mouse_hold_start[3];
+extern browser_mouse_state bmstate;
+
+/* 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 char * menu_titles[NUM_MENU_TITLES] = {NULL};
+
+
+/* Menu event handlers: */
+static void __CDECL menu_about(WINDOW *win, int item, int title, void *data)
+{
+ LOG(("%s", __FUNCTION__));
+}
+
+static void __CDECL menu_new_win(WINDOW *win, int item, int title, void *data)
+{
+ LOG(("%s", __FUNCTION__));
+ browser_window_create(cfg_homepage_url, 0, 0, true, false);
+}
+
+static void __CDECL menu_open_url(WINDOW *win, int item, int title, void *data)
+{
+ struct gui_window * gw;
+ struct browser_window * bw ;
+
+ gw = input_window;
+ if( gw == NULL ) {
+ bw = browser_window_create("", 0, 0, true, false);
+ gw = bw->window;
+ }
+ /* TODO: reset url? */
+ LOG(("%s", __FUNCTION__));
+}
+
+static void __CDECL menu_open_file(WINDOW *win, int item, int title, void *data)
+{
+ LOG(("%s", __FUNCTION__));
+}
+
+static void __CDECL menu_close_win(WINDOW *win, int item, int title, void *data)
+{
+ LOG(("%s", __FUNCTION__));
+ if( input_window == NULL )
+ return;
+ gui_window_destroy( input_window );
+}
+
+static void __CDECL menu_save_page(WINDOW *win, int item, int title, void *data)
+{
+ LOG(("%s", __FUNCTION__));
+}
+
+static void __CDECL menu_quit(WINDOW *win, int item, int title, void *data)
+{
+ short buff[8];
+ memset( &buff, 0, sizeof(short)*8 );
+ LOG(("%s", __FUNCTION__));
+ global_evnt_apterm( NULL, buff );
+}
+
+static void __CDECL menu_cut(WINDOW *win, int item, int title, void *data)
+{
+ if( input_window != NULL )
+ browser_window_key_press( input_window->browser->bw, KEY_CUT_SELECTION);
+}
+
+static void __CDECL menu_copy(WINDOW *win, int item, int title, void *data)
+{
+ LOG(("%s", __FUNCTION__));
+ if( input_window != NULL )
+ browser_window_key_press( input_window->browser->bw, KEY_COPY_SELECTION);
+}
+
+static void __CDECL menu_paste(WINDOW *win, int item, int title, void *data)
+{
+ LOG(("%s", __FUNCTION__));
+ if( input_window != NULL )
+ browser_window_key_press( input_window->browser->bw, KEY_PASTE);
+}
+
+static void __CDECL menu_find(WINDOW *win, int item, int title, void *data)
+{
+ LOG(("%s", __FUNCTION__));
+}
+
+static void __CDECL menu_choices(WINDOW *win, int item, int title, void *data)
+{
+ LOG(("%s", __FUNCTION__));
+}
+
+static void __CDECL menu_stop(WINDOW *win, int item, int title, void *data)
+{
+ LOG(("%s", __FUNCTION__));
+ if( input_window == NULL )
+ return;
+ tb_stop_click( input_window );
+
+}
+
+static void __CDECL menu_reload(WINDOW *win, int item, int title, void *data)
+{
+ if( input_window == NULL)
+ return;
+ tb_reload_click( input_window );
+ LOG(("%s", __FUNCTION__));
+}
+
+static void __CDECL menu_toolbars(WINDOW *win, int item, int title, void *data)
+{
+ LOG(("%s", __FUNCTION__));
+}
+
+static void __CDECL menu_savewin(WINDOW *win, int item, int title, void *data)
+{
+ LOG(("%s", __FUNCTION__));
+}
+
+static void __CDECL menu_debug_render(WINDOW *win, int item, int title, void *data)
+{
+ LOG(("%s", __FUNCTION__));
+}
+
+static void __CDECL menu_back(WINDOW *win, int item, int title, void *data)
+{
+ LOG(("%s", __FUNCTION__));
+ if( input_window == NULL )
+ return;
+ tb_back_click( input_window );
+}
+
+static void __CDECL menu_forward(WINDOW *win, int item, int title, void *data)
+{
+ LOG(("%s", __FUNCTION__));
+ if( input_window == NULL )
+ return;
+ tb_forward_click( input_window );
+}
+
+static void __CDECL menu_home(WINDOW *win, int item, int title, void *data)
+{
+ LOG(("%s", __FUNCTION__));
+ if( input_window == NULL )
+ return;
+ tb_home_click( input_window );
+}
+
+static void __CDECL menu_lhistory(WINDOW *win, int item, int title, void *data)
+{
+ LOG(("%s", __FUNCTION__));
+}
+
+static void __CDECL menu_ghistory(WINDOW *win, int item, int title, void *data)
+{
+ LOG(("%s", __FUNCTION__));
+}
+
+static void __CDECL menu_add_bookmark(WINDOW *win, int item, int title, void *data)
+{
+ LOG(("%s", __FUNCTION__));
+}
+
+static void __CDECL menu_bookmarks(WINDOW *win, int item, int title, void *data)
+{
+ LOG(("%s", __FUNCTION__));
+ hotlist_open();
+}
+
+static void __CDECL menu_help_content(WINDOW *win, int item, int title, void *data)
+{
+ LOG(("%s", __FUNCTION__));
+}
+
+static struct s_menu_item_evnt menu_evnt_tbl[] =
+{
+ {T_FILE, MAINMENU_M_NEWWIN, "NewWindow", menu_new_win, {0,0,0}, NULL},
+ {T_FILE, MAINMENU_M_OPENURL, "OpenURL", menu_open_url, {0,0,0}, NULL},
+ {T_FILE, MAINMENU_M_OPENFILE, "OpenFile", menu_open_file, {0,0,0}, NULL},
+ {T_FILE, MAINMENU_M_CLOSEWIN, "CloseWindow", menu_close_win, {0,0,0}, NULL},
+ {T_FILE, MAINMENU_M_SAVEPAGE, "Save", menu_save_page, {0,0,0}, NULL},
+ {T_FILE, MAINMENU_M_QUIT, "Quit", menu_quit, {'Q',0,K_CTRL}, NULL},
+ {T_EDIT, MAINMENU_M_CUT, "Cut", menu_cut, {0,0,0}, NULL},
+ {T_EDIT, MAINMENU_M_COPY, "Copy", menu_copy, {0,0,0}, NULL},
+ {T_EDIT, MAINMENU_M_PASTE, "Paste", menu_paste, {0,0,0}, NULL},
+ {T_EDIT, MAINMENU_M_FIND, "FindText", menu_find, {0,0,0}, NULL},
+ {T_VIEW, MAINMENU_M_RELOAD, "Reload", menu_reload, {0,NK_F5,0}, NULL},
+ {T_VIEW, MAINMENU_M_TOOLBARS, "Toolbars", menu_toolbars, {0,0,0}, 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_STOP, "Stop", menu_stop, {0,0,0}, NULL},
+ {T_NAV, MAINMENU_M_BACK, "Back", menu_back, {0,0,0}, NULL},
+ {T_NAV, MAINMENU_M_FORWARD, "Forward", menu_forward, {0,0,0}, NULL},
+ {T_NAV, MAINMENU_M_HOME, "Home", menu_home, {0,0,0}, NULL},
+ {T_UTIL, MAINMENU_M_LHISTORY, "HistLocal", menu_lhistory, {0,0,0}, NULL},
+ {T_UTIL, MAINMENU_M_GHISTORY, "HistGlobal", menu_ghistory, {0,0,0}, NULL},
+ {T_UTIL, MAINMENU_M_ADD_BOOKMARK, "HotlistAdd", menu_add_bookmark, {0,0,0}, NULL},
+ {T_UTIL, MAINMENU_M_BOOKMARKS, "HotlistShow", menu_bookmarks, {0,0,0}, NULL},
+ {T_UTIL, MAINMENU_M_CHOICES, "Choices", menu_choices, {0,0,0}, NULL},
+ {T_HELP, MAINMENU_M_HELP_CONTENT, "Help", menu_help_content, {0,0,0}, NULL},
+ {T_HELP, -1, "", NULL,{0,0,0}, NULL }
+};
+
+void __CDECL global_evnt_apterm( WINDOW * win, short buff[8] )
+{
+ int i = 0;
+ LOG((""));
+ netsurf_quit = true;
+}
+
+void __CDECL global_evnt_keybd( WINDOW * win, short buff[8], void * data)
+{
+ char sascii;
+ long kstate = 0;
+ long kcode = 0;
+ unsigned short nkc = 0;
+ unsigned short nks = 0;
+
+ int i=0;
+ bool done = false;
+ struct s_evnt_data * loc_evnt_data;
+ loc_evnt_data = (struct s_event_data*)data;
+ struct gui_window * gw = input_window;
+ struct gui_window * gw_tmp;
+ if( gw == NULL )
+ return;
+ if( loc_evnt_data->ignore )
+ return;
+ kstate = evnt.mkstate;
+ kcode = evnt.keybd;
+ nkc= gem_to_norm( (short)kstate, (short)kcode );
+ nks = (nkc & 0xFF00);
+ loc_evnt_data->ignore = false;
+ if( kstate & (K_LSHIFT|K_RSHIFT))
+ kstate |= K_LSHIFT|K_RSHIFT;
+ if( window_url_widget_has_focus( gw ) ) {
+ /* make sure we report for the root window and report...: */
+ done = tb_url_input( browser_find_root(gw), nkc );
+ if( done ) return;
+ } else {
+ gw_tmp = window_list;
+ /* search for active browser component: */
+ while( gw_tmp != NULL && done == false ) {
+ if( window_widget_has_focus( (struct gui_window *)input_window,
+ BROWSER,(void*)gw_tmp->browser)) {
+ done = browser_input( gw_tmp, nkc );
+ break;
+ } else {
+ gw_tmp = gw_tmp->next;
+ }
+ }
+ }
+ sascii = keybd2ascii( evnt.keybd, K_LSHIFT);
+ while( menu_evnt_tbl[i].rid != -1 && done == false) {
+ if(menu_evnt_tbl[i].nsid[0] != 0 ) {
+ if( kstate == menu_evnt_tbl[i].accel.mod && menu_evnt_tbl[i].accel.ascii != 0) {
+ if( menu_evnt_tbl[i].accel.ascii == sascii) {
+ menu_evnt_tbl[i].menu_func( NULL, menu_evnt_tbl[i].rid, MAINMENU, buff);
+ 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 &&
+ menu_evnt_tbl[i].menu_func != NULL) {
+ menu_evnt_tbl[i].menu_func( NULL,
+ menu_evnt_tbl[i].rid,
+ MAINMENU, buff
+ );
+ done = true;
+ break;
+ }
+ }
+ }
+ }
+ i++;
+ }
+}
+
+browser_mouse_state global_track_evnt_mbutton( WINDOW * win, long buff[8], void * data )
+{
+ short i;
+ short mbut, mkstat, mx, my;
+ browser_mouse_state retval = 0;
+ graf_mkstate(&mx, &my, &mbut, &mkstat);
+ for( i = 1; i<2; i++) {
+ if( (mbut & i) ) {
+ if( mouse_hold_start[i-1] == 0 ) {
+ mouse_hold_start[i-1] = clock()*1000 / CLOCKS_PER_SEC;
+ LOG(("Drag %d starts", i));
+ if( i == 1 ) {
+ retval |= BROWSER_MOUSE_DRAG_1;
+ }
+ if( i == 2 ) {
+ retval |= BROWSER_MOUSE_DRAG_2;
+ }
+ }
+ } else {
+ /* remember click time, so we can track double clicks: */
+ mouse_click_time[i-1] = clock()*1000 / CLOCKS_PER_SEC; /* clock in ms */
+ /* check if this event was during an drag op: */
+ if( mouse_hold_start[i-1] < 10 ) {
+ if( i == 1)
+ retval |= BROWSER_MOUSE_CLICK_1;
+ if( i == 2 )
+ retval |= BROWSER_MOUSE_CLICK_2;
+ }
+ mouse_hold_start[i-1] = 0;
+ }
+ }
+ return( retval );
+}
+
+
+void global_track_mouse_state( void ){
+ int i = 0;
+ int nx, ny;
+ short mbut, mkstat, mx, my;
+ long hold_time = 0;
+ COMPONENT * cmp;
+ LGRECT cmprect;
+
+ if( !input_window ) {
+ bmstate = 0;
+ return;
+ }
+ graf_mkstate(&mx, &my, &mbut, &mkstat);
+ cmp = mt_CompFind( &app, input_window->root->cmproot, mx, my );
+ if( cmp == NULL ) {
+ bmstate = 0;
+ mouse_hold_start[0] = 0;
+ mouse_hold_start[1] = 0;
+ return;
+ }
+ mt_CompGetLGrect( &app, cmp, WF_WORKXYWH, &cmprect );
+ nx = mx - cmprect.g_x;
+ ny = my - cmprect.g_y;
+
+ if( !(mbut&1) && !(mbut&2) ) {
+ if(bmstate & BROWSER_MOUSE_DRAG_ON )
+ bmstate &= ~( BROWSER_MOUSE_DRAG_ON );
+ }
+
+ for( i = 1; i<3; i++ ) {
+ if( (mbut & i) ) {
+ /* the mouse is still pressed...
+ report further dragging ?
+ BROWSER_MOUSE_PRESS_2 needed ?
+ */
+ if(i==1)
+ bmstate |= BROWSER_MOUSE_DRAG_ON|BROWSER_MOUSE_HOLDING_1;
+ if( i==2 )
+ bmstate |= BROWSER_MOUSE_DRAG_ON|BROWSER_MOUSE_HOLDING_2;
+ LOG(("still dragging %d, time ms: %d", i, (clock()*1000 / CLOCKS_PER_SEC) - mouse_hold_start[i-1] ));
+ browser_window_mouse_track( input_window->browser->bw, bmstate, nx, ny );
+ } else {
+ if( mouse_hold_start[i-1] > 0 ) {
+ mouse_hold_start[i-1] = 0;
+ LOG(("drag release %d", i));
+ /* TODO: not just use the input window browser, find the right one by component! */
+ if( i==1 ) {
+ bmstate &= ~( BROWSER_MOUSE_HOLDING_1 );
+ browser_window_mouse_drag_end( input_window->browser->bw,
+ bmstate, nx, ny);
+ }
+ if( i==2 ) {
+ bmstate &= ~( BROWSER_MOUSE_HOLDING_2 );
+ browser_window_mouse_drag_end( input_window->browser->bw,
+ bmstate, nx, ny);
+ }
+ }
+ }
+ }
+
+ browser_window_mouse_track(input_window->browser->bw, bmstate, nx, ny );
+}
+
+
+void __CDECL global_evnt_m1( WINDOW * win, short buff[8], void * data)
+{
+ struct gui_window * gw = input_window;
+ static bool prev_url = false;
+ static bool prev_sb = false;
+ bool a=false;
+ LGRECT urlbox, bwbox, sbbox;
+ int nx, ny; /* relative mouse position */
+
+ if( gw == NULL)
+ return;
+
+ if( gw->root->toolbar )
+ mt_CompGetLGrect(&app, gw->root->toolbar->url.comp, WF_WORKXYWH, &urlbox);
+ mt_CompGetLGrect(&app, gw->browser->comp, WF_WORKXYWH, &bwbox);
+ mt_CompGetLGrect(&app, gw->root->statusbar->comp, WF_WORKXYWH, &sbbox);
+
+ if( evnt.m1_flag == MO_LEAVE && input_window != NULL ) {
+ if( gw->root->toolbar ) {
+ if( (evnt.mx > urlbox.g_x && evnt.mx < urlbox.g_x + urlbox.g_w ) &&
+ (evnt.my > urlbox.g_y && evnt.my < + urlbox.g_y + urlbox.g_h )) {
+ gem_set_cursor( &gem_cursors.ibeam );
+ prev_url = a = true;
+ }
+ }
+ if( gw->root->statusbar && a == false ) {
+ if( evnt.mx >= sbbox.g_x + (sbbox.g_w-MOVER_WH) && evnt.mx <= sbbox.g_x + sbbox.g_w &&
+ evnt.my >= sbbox.g_y + (sbbox.g_h-MOVER_WH) && evnt.my <= sbbox.g_y + sbbox.g_h ) {
+ /* mouse within mover */
+ prev_sb = a = true;
+ gem_set_cursor( &gem_cursors.sizenwse );
+ }
+ }
+ if( !a ) {
+ if( prev_url || prev_sb ) {
+ gem_set_cursor( &gem_cursors.arrow );
+ prev_url = false;
+ prev_sb = false;
+ }
+ /* report mouse move in the browser window */
+ if( evnt.mx > bwbox.g_x && evnt.mx < bwbox.g_x + bwbox.g_w &&
+ evnt.my > bwbox.g_y && evnt.my < bwbox.g_y + bwbox.g_h ){
+ /* TODO: use global mouse state instead of zero
+ TODO: find COMPONENT and report to its browser, or maybe
+ its better to catch mouse movements with component events?
+ */
+ nx = evnt.mx - bwbox.g_x;
+ ny = evnt.my - bwbox.g_y;
+ /*printf("m1 bw: %p, x: %d, y: %d, state: %d\n" , input_window->browser->bw, nx, ny, bmstate);*/
+ browser_window_mouse_track( input_window->browser->bw, 0, nx + gw->browser->scroll.current.x, ny + gw->browser->scroll.current.y );
+ }
+ }
+ }
+}
+
+/*
+ mode = 0 -> return string ptr
+ (build from accel definition in s_accelerator accel)
+ mode = 1 -> return ptr to (untranslated) NS accel string, if any
+*/
+static char * get_accel(int mode, char * message, struct s_accelerator * accel )
+{
+ static char result[8];
+ int pos = 0;
+ char * r = NULL;
+ char * s = NULL;
+ memset( &result, 0, 8);
+ if( (accel->ascii != 0 || accel->keycode != 0) && mode == 0)
+ goto predefined_accel;
+ s = strrchr(message, (int)' ' ) ;
+ if(!s)
+ goto error;
+ if( strlen( s ) < 2)
+ goto error;
+ if(strlen(s) >= 2){
+ s++;
+ /* if string after space begins with lowercase ascii, its not an accelerator: */
+ if( s[0] >= 0x061 && s[0] <= 0x07A )
+ goto error;
+ if( strncmp(s, "URL", 3) == 0)
+ goto error;
+ if(mode == 1)
+ return( s );
+ /* detect obscure shift accelerator: */
+ if(!strncmp("\xe2\x87\x91", s, 3)){
+ s = s+3;
+ strcpy((char*)&result, "");
+ strncpy((char*)&result[1], s, 14);
+ goto success;
+ }
+ strncpy((char*)&result, s, 15);
+ }
+goto success;
+
+predefined_accel:
+ if( (accel->mod & K_RSHIFT) || (accel->mod & K_RSHIFT) ) {
+ result[pos]='';
+ pos++;
+ }
+ if(accel->mod == K_CTRL ) {
+ result[pos]='^';
+ pos++;
+ }
+ if(accel->ascii != 0L ) {
+ result[pos]= accel->ascii;
+ pos++;
+ }
+ else if(accel->keycode != 0L ) {
+ if( accel->keycode >= NK_F1 && accel->keycode <= NK_F10){
+ result[pos++] = 'F';
+ sprintf( (char*)&result[pos++], "%d", ((accel->keycode - NK_F1)+1) );
+ } else {
+ *((char*)0) = 1;
+ switch( accel->keycode ) {
+ /* TODO: Add further Keycodes & Symbols here, if needed. */
+ default:
+ goto error;
+ }
+ }
+ }
+success:
+ r = (char*)&result;
+error:
+ return r;
+}
+
+/* create accelerator info and keep track of the line length */
+static int parse_accel( char * message, struct s_accelerator * accel)
+{
+ int retval = strlen( message ) ;
+ char * s = get_accel( 0, message, accel );
+ if(!s && (accel->keycode == 0 && accel->ascii == 0 && accel->mod == 0) ) {
+ return retval+4; /* add 3 "imaginary" accel characters + blank */
+ }
+
+ /* the accel is already defined: */
+ if(accel->keycode != 0 ||accel->ascii != 0 || accel->mod != 0) {
+ return( retval+1 );
+ }
+
+ if(s[0] == '' ) { /* arrow up */
+ accel->mod |= (K_LSHIFT|K_RSHIFT);
+ s++;
+ }
+ else if(s[0] == 0x05E ) { /* ^ */
+ accel->mod |= K_CTRL;
+ s++;
+ }
+parsekey:
+ /* expect F1/F10 or something like A, B, C ... : */
+ if(strlen(s) >= 2 && s[0] == 'F' ) {
+ if(s[1] >= 49 && s[1] <= 57) {
+ accel->keycode = NK_F1 + (atoi(&s[1])-1);
+ }
+ }
+ else {
+ accel->ascii = s[0];
+ }
+ return( retval+1 ); /* add 1 blank */
+}
+
+
+void __CDECL global_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;
+ MenuTnormal( NULL, title, 1);
+ 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 == buff[4] ) {
+ menu_evnt_tbl[i].menu_func(win, (int)buff[4], (int)buff[3], NULL );
+ break;
+ }
+ i++;
+ }
+}
+
+
+static void set_menu_title(int rid, const char * nsid)
+{
+ static int count=0;
+ char * msgstr;
+ msgstr = (char*)messages_get(nsid);
+ if(msgstr != NULL) {
+ if(msgstr[0] != 0) {
+ assert(count < NUM_MENU_TITLES);
+ menu_titles[count] = malloc( strlen(msgstr)+3 );
+ strcpy((char*)menu_titles[count], " ");
+ strncat((char*)menu_titles[count], msgstr, strlen(msgstr)+1 );
+ strncat((char*)menu_titles[count], " ", 2 );
+ MenuText(NULL, rid, menu_titles[count] );
+ count++;
+ }
+ }
+}
+
+
+/* Bind global and menu events to event handler functions, create accelerators */
+void bind_global_events( void )
+{
+ int i, len;
+ int maxlen[NUM_MENU_TITLES]={0};
+ char * m, *u, *t;
+ char spare[128];
+ memset( (void*)&evnt_data, 0, sizeof(struct s_evnt_data) );
+ EvntDataAttach( NULL, WM_XKEYBD, global_evnt_keybd, (void*)&evnt_data );
+ EvntAttach( NULL, AP_TERM, global_evnt_apterm );
+ EvntAttach( NULL, MN_SELECTED, global_evnt_menu );
+ EvntDataAttach( NULL, WM_XM1, global_evnt_m1, NULL );
+
+ /* TODO: maybe instant redraw after this is better! */
+ set_menu_title( MAINMENU_T_FILE, "Page");
+ set_menu_title( MAINMENU_T_EDIT, "Edit" );
+ set_menu_title( MAINMENU_T_NAVIGATE, "Navigate");
+ set_menu_title( MAINMENU_T_VIEW, "View");
+ set_menu_title( MAINMENU_T_UTIL, "Utilities");
+ set_menu_title( MAINMENU_T_HELP, "Help");
+
+ /* measure items in titles : */
+ i = 0;
+ while( menu_evnt_tbl[i].rid != -1 ) {
+ if( menu_evnt_tbl[i].nsid[0] != 0 ) {
+ m = (char*)messages_get(menu_evnt_tbl[i].nsid);
+ assert(strlen(m)<40);
+ /* create accelerator: */
+ len = parse_accel(m, &menu_evnt_tbl[i].accel);
+ maxlen[menu_evnt_tbl[i].title]=MAX(len, maxlen[menu_evnt_tbl[i].title] );
+ assert(maxlen[menu_evnt_tbl[i].title]<40);
+ }
+ i++;
+ }
+ for( i=0; i<NUM_MENU_TITLES; i++) {
+ if ( maxlen[i] > 120 )
+ maxlen[i] = 120;
+ }
+ /* set menu texts : */
+ i = 0;
+ while( menu_evnt_tbl[i].rid != -1 ) {
+ if( menu_evnt_tbl[i].nsid[0] != 0 ) {
+ m = (char*)messages_get(menu_evnt_tbl[i].nsid);
+ if(m == NULL) {
+ m = (char*)menu_evnt_tbl[i].nsid;
+ }
+ u = get_accel( 1, m, &menu_evnt_tbl[i].accel); /* get NS accel str */
+ t = get_accel( 0, m, &menu_evnt_tbl[i].accel); /* get NS or custom accel */
+ memset((char*)&spare, ' ', 121);
+ spare[0]=' '; /*''; */
+ spare[1]=' ';
+ if( u != NULL && t != NULL ) {
+ LOG(("Menu Item %s: found NS accelerator, ascii: %c, scancode: %x, mod: %x",
+ m,
+ menu_evnt_tbl[i].accel.ascii,
+ menu_evnt_tbl[i].accel.keycode,
+ menu_evnt_tbl[i].accel.mod
+ ));
+ /* Accelerator is defined in menu string: */
+ memcpy((char*)&spare[2], m, u-m-1);
+ strncpy(&spare[maxlen[menu_evnt_tbl[i].title]-strlen(t)], t, 4);
+ }
+ else if( t != NULL && u == NULL) {
+ LOG(("Menu Item %s: found RSC accelerator, ascii: %c, scancode: %x, mod: %x",
+ m,
+ menu_evnt_tbl[i].accel.ascii,
+ menu_evnt_tbl[i].accel.keycode,
+ menu_evnt_tbl[i].accel.mod
+ ));
+ /* Accelerator is defined in struct: */
+ memcpy( (char*)&spare[2], m, strlen(m) );
+ strncpy(&spare[maxlen[menu_evnt_tbl[i].title]-strlen(t)], t, 4);
+ }
+ else {
+ /* No accel defined: */
+ strcpy((char*)&spare[2], m);
+ }
+ spare[ maxlen[menu_evnt_tbl[i].title]+1 ] = 0;
+ menu_evnt_tbl[i].menustr = malloc(strlen((char*)&spare)+1);
+ if( menu_evnt_tbl[i].menustr ) {
+ strcpy( menu_evnt_tbl[i].menustr , (char*)&spare );
+ }
+ }
+ i++;
+ }
+ i=0;
+ while( menu_evnt_tbl[i].rid != -1 ) {
+ if( menu_evnt_tbl[i].menustr != NULL ) {
+ MenuText( NULL, menu_evnt_tbl[i].rid, menu_evnt_tbl[i].menustr );
+ }
+ i++;
+ }
+ /* TODO: Fix pixel sizes for Titles and Items (for non-8px fonts) */
+}
+
+void unbind_global_events( void )
+{
+ int i;
+ for( i=0; i<NUM_MENU_TITLES; i++){
+ if( menu_titles[i]!= NULL)
+ free( menu_titles[i] );
+ }
+ i=0;
+ while(menu_evnt_tbl[i].rid != -1) {
+ if( menu_evnt_tbl[i].menustr != NULL )
+ free(menu_evnt_tbl[i].menustr);
+ i++;
+ }
+}
+
+void snd_redraw( short x, short y, short w, short h)
+{
+ struct gui_window * gw;
+ gw = window_list;
+ while( gw != NULL && gw->browser->type == 0 ) {
+ ApplWrite( _AESapid, WM_REDRAW, gw->root->handle->handle, x, y, w, h);
+ gw = gw->next;
+ }
+ return;
+}
+
diff --git a/atari/global_evnt.h b/atari/global_evnt.h
new file mode 100644
index 000000000..e9e343696
--- /dev/null
+++ b/atari/global_evnt.h
@@ -0,0 +1,78 @@
+/*
+ * 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_GLOBAL_EVNT_H
+#define NS_ATARI_GLOBAL_EVNT_H
+
+struct s_keybd_evnt_data
+{
+ char ascii;
+} keybd_evnt_data;
+
+struct s_evnt_data
+{
+ bool ignore;
+ union {
+ struct s_keybd_evnt_data keybd;
+ } u;
+};
+
+struct s_evnt_data evnt_data;
+
+struct s_accelerator
+{
+ char ascii; /* either ascii or */
+ long keycode; /* normalised keycode is valid */
+ short mod; /* shift / ctrl etc */
+};
+
+typedef void __CDECL (*menu_evnt_func)(WINDOW * win, int item, int title, void * data);
+struct s_menu_item_evnt {
+ short title; /* to which menu this item belongs */
+ short rid; /* resource ID */
+ const char * nsid; /* Netsurf message ID */
+ menu_evnt_func menu_func; /* click handler */
+ struct s_accelerator accel; /* accelerator info */
+ char * menustr;
+};
+
+/*
+ Global & Menu event handlers
+*/
+
+/* Call this after each call to evnt_multi, to check for states that evnt_multi doesn't: */
+void snd_redraw(short x, short y, short w, short h);
+void snd_win_redraw(WINDOW * win, short x, short y, short w, short h);
+void global_track_mouse_state( void );
+browser_mouse_state global_track_evnt_mbutton( WINDOW * win, long buff[8], void * data );
+void bind_global_events( void );
+void unbind_global_events( void );
+
+/* Global event handlers: */
+
+static void __CDECL global_evnt_apterm( WINDOW * win, short buff[8] );
+static void __CDECL global_evnt_menu( WINDOW * win, short buff[8] );
+static void __CDECL global_evnt_keybd( WINDOW * win, short buff[8], void * data);
+static void __CDECL global_evnt_m1( WINDOW * win, short buff[8], void * data);
+/* Menu event handlers: */
+static void __CDECL menu_about(WINDOW *win, int item, int title, void *data);
+
+
+static char * get_accel(int mode, char * message, struct s_accelerator * accel);
+static int parse_accel( char * message, struct s_accelerator * accel);
+#endif
diff --git a/atari/gui.c b/atari/gui.c
new file mode 100644
index 000000000..55fdfbee5
--- /dev/null
+++ b/atari/gui.c
@@ -0,0 +1,1131 @@
+/*
+ * 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/>.
+ */
+
+ /*
+ This File provides all the mandatory functions prefixed with gui_
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <time.h>
+#include <limits.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdbool.h>
+#include <windom.h>
+#include <cflib.h>
+#include <hubbub/hubbub.h>
+
+#include "content/urldb.h"
+#include "content/fetch.h"
+#include "css/utils.h"
+#include "desktop/gui.h"
+#include "desktop/history_core.h"
+#include "desktop/plotters.h"
+#include "desktop/netsurf.h"
+#include "desktop/401login.h"
+
+#include "desktop/options.h"
+#include "desktop/save_complete.h"
+#include "desktop/selection.h"
+#include "desktop/textinput.h"
+#include "desktop/browser.h"
+#include "desktop/mouse.h"
+#include "render/html.h"
+#include "render/font.h"
+#include "utils/url.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/utils.h"
+
+#include "atari/gui.h"
+#include "atari/options.h"
+#include "atari/misc.h"
+#include "atari/findfile.h"
+#include "atari/schedule.h"
+#include "atari/browser_win.h"
+#include "atari/browser.h"
+#include "atari/statusbar.h"
+#include "atari/toolbar.h"
+#include "atari/verify_ssl.h"
+#include "atari/hotlist.h"
+#include "atari/login.h"
+#include "atari/global_evnt.h"
+#include "atari/font.h"
+#include "atari/res/netsurf.rsh"
+#include "atari/plot.h"
+#include "atari/clipboard.h"
+
+#define TODO() printf("%s Unimplemented!\n", __FUNCTION__)
+
+char *default_stylesheet_url;
+char *adblock_stylesheet_url;
+char *quirks_stylesheet_url;
+char *options_file_location;
+char *tmp_clipboard;
+struct gui_window *input_window = NULL;
+struct gui_window *window_list = NULL;
+void * h_gem_rsrc;
+OBJECT * h_gem_menu;
+OBJECT **rsc_trindex;
+short vdih;
+short rsc_ntree;
+static clock_t last_multi_task;
+int mouse_click_time[3];
+int mouse_hold_start[3];
+browser_mouse_state bmstate;
+bool lck_multi = false;
+
+/* Comandline / Options: */
+int cfg_width;
+int cfg_height;
+
+const char * cfg_homepage_url;
+
+extern GEM_PLOTTER plotter;
+
+void gui_multitask(void)
+{
+ short winloc[4];
+ int flags = MU_MESAG | MU_KEYBD | MU_BUTTON | MU_TIMER;
+ if( ((clock() * 1000 / CLOCKS_PER_SEC) - last_multi_task ) < 50 || lck_multi == true ) {
+ return;
+ }
+ /* todo: instead of time, use dumm window message here,
+ timer takes at least 10ms, WMs take about 1ms!
+ */
+ evnt.timer = 1;
+ if(input_window) {
+ graf_mkstate( &prev_inp_state.mx, &prev_inp_state.my,
+ &prev_inp_state.mbut, &prev_inp_state.mkstat );
+ wind_get(input_window->root->handle->handle, WF_WORKXYWH, &winloc[0],
+ &winloc[1], &winloc[2], &winloc[3] );
+ flags |= MU_M1;
+ if( prev_inp_state.mx >= winloc[0] && prev_inp_state.mx <= winloc[0] + winloc[2] &&
+ prev_inp_state.my >= winloc[1] && prev_inp_state.my <= winloc[1] + winloc[3] ){
+ /* if the cursor is within workarea, capture an movement WITHIN: */
+ evnt.m1_flag = MO_LEAVE;
+ evnt.m1_w = 2;
+ evnt.m1_h = 2;
+ evnt.m1_x = prev_inp_state.mx;
+ evnt.m1_y = prev_inp_state.my;
+ } else {
+ /* otherwise capture mouse move INTO the work area: */
+ evnt.m1_flag = MO_ENTER;
+ evnt.m1_w = winloc[2];
+ evnt.m1_h = winloc[3];
+ evnt.m1_x = winloc[0];
+ evnt.m1_y = winloc[1];
+ }
+ }
+ EvntWindom( flags );
+ if( MOUSE_IS_DRAGGING() )
+ global_track_mouse_state();
+ last_multi_task = clock()*1000 / CLOCKS_PER_SEC;
+}
+void gui_poll(bool active)
+{
+ short winloc[4];
+ int timeout = 50; /* timeout in milliseconds */
+ int flags = MU_MESAG | MU_KEYBD | MU_BUTTON ;
+ timeout = schedule_run();
+ if ( active )
+ timeout = 1;
+
+ if(input_window) {
+ flags |= MU_M1;
+ graf_mkstate( &prev_inp_state.mx, &prev_inp_state.my,
+ &prev_inp_state.mbut, &prev_inp_state.mkstat );
+ wind_get(input_window->root->handle->handle, WF_WORKXYWH, &winloc[0],
+ &winloc[1], &winloc[2], &winloc[3] );
+ if( prev_inp_state.mx >= winloc[0] && prev_inp_state.mx <= winloc[0] + winloc[2] &&
+ prev_inp_state.my >= winloc[1] && prev_inp_state.my <= winloc[1] + winloc[3] ){
+ evnt.m1_flag = MO_LEAVE;
+ evnt.m1_w = 2;
+ evnt.m1_h = 2;
+ evnt.m1_x = prev_inp_state.mx;
+ evnt.m1_y = prev_inp_state.my;
+ } else {
+ evnt.m1_flag = MO_ENTER;
+ evnt.m1_w = winloc[2];
+ evnt.m1_h = winloc[3];
+ evnt.m1_x = winloc[0];
+ evnt.m1_y = winloc[1];
+ }
+ /* if we have some state that can't be recognized by evnt_multi, don't block
+ so tracking can take place after timeout: */
+ if( MOUSE_IS_DRAGGING() )
+ timeout = 1;
+ }
+
+ if( timeout >= 0 ) {
+ flags |= MU_TIMER;
+ evnt.timer = timeout;
+ }
+ lck_multi = true;
+ EvntWindom( flags );
+ lck_multi = false;
+ if( MOUSE_IS_DRAGGING() )
+ global_track_mouse_state();
+ last_multi_task = clock()*1000 / CLOCKS_PER_SEC;
+ struct gui_window * g;
+ for( g = window_list; g; g=g->next ) {
+ if( browser_redraw_required( g ) )
+ browser_redraw( g );
+ }
+}
+
+struct gui_window *
+gui_create_browser_window(struct browser_window *bw,
+ struct browser_window *clone,
+ bool new_tab)
+{
+ struct gui_window *gw=NULL;
+ struct gui_window * gwroot ;
+ short winloc[4];
+ LOG(( "gw: %p, BW: %p, clone %p, tab: %d, type: %d\n" , gw, bw, clone,
+ (int)new_tab, bw->browser_window_type
+ ));
+
+ gw = malloc( sizeof(struct gui_window) );
+ if (gw == NULL)
+ return NULL;
+ memset( gw, 0, sizeof(struct gui_window) );
+
+ switch(bw->browser_window_type) {
+ case BROWSER_WINDOW_NORMAL:
+
+ LOG(("normal browser window: %p\n", gw));
+ window_create(gw, bw, WIDGET_STATUSBAR|WIDGET_TOOLBAR );
+ if( gw->root->handle ) {
+ window_open( gw );
+ /* Recalculate windows browser area now */
+ browser_update_rects( gw );
+ tb_update_buttons( gw );
+ input_window = gw;
+ /* TODO:... this line: placeholder to create a local history widget ... */
+ }
+ break;
+
+ case BROWSER_WINDOW_FRAME:
+ gwroot = bw->parent->window;
+ LOG(("create frame: %p, clone: %p\n", bw, clone));
+ gw->parent = gwroot;
+ gw->root = gwroot->root;
+ gw->browser = browser_create( gw, bw, clone, BT_FRAME, CLT_VERTICAL, 1, 1);
+ /*browser_attach_frame( gwroot, gw );*/
+ break;
+
+ case BROWSER_WINDOW_FRAMESET:
+ LOG(("frameset: %p, clone: %p\n", bw, clone));
+ gwroot = bw->parent->window;
+ gw->parent = gwroot;
+ gw->root = gwroot->root;
+ gw->browser = browser_create( gw, bw, clone, BT_FRAME, CLT_VERTICAL, 1, 1);
+ /*browser_attach_frame( gwroot, gw );*/
+ break;
+
+ case BROWSER_WINDOW_IFRAME:
+ LOG(("iframe: %p, clone: %p\n", bw, clone));
+ /* just dummy code here! */
+ gwroot = bw->parent->window;
+ gw->parent = gwroot;
+ gw->root = bw->parent->window->root;
+ gw->browser = browser_create( gw, bw, NULL, BT_FRAME, CLT_VERTICAL, 1, 1);
+ /*browser_attach_frame( gwroot, gw );*/
+ break;
+
+ default:
+ LOG(("unhandled type!"));
+ }
+
+ /* 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;
+ }
+
+ return( gw );
+
+}
+
+void gui_window_destroy(struct gui_window *w)
+{
+ if (w == NULL)
+ return;
+
+ LOG(("%s\n", __FUNCTION__ ));
+
+ input_window = NULL;
+
+ LGRECT dbg;
+ struct gui_window * root = browser_find_root( w );
+ browser_get_rect( root, BR_CONTENT, &dbg );
+ switch(w->browser->bw->browser_window_type) {
+ case BROWSER_WINDOW_NORMAL:
+ window_destroy( w );
+ break;
+ case BROWSER_WINDOW_FRAME:
+ browser_destroy( w->browser );
+ break;
+
+ case BROWSER_WINDOW_FRAMESET:
+ browser_destroy( w->browser );
+ break;
+
+ case BROWSER_WINDOW_IFRAME:
+ /* just dummy code here: */
+ window_destroy( w );
+ break;
+
+ default:
+ LOG(("Unhandled type!"));
+ assert( 1 == 0 );
+ break;
+ }
+ /* unlink the window: */
+ if(w->prev != NULL ) {
+ w->prev->next = w->next;
+ } else {
+ window_list = w->next;
+ }
+ if( w->next != NULL ) {
+ w->next->prev = w->prev;
+ }
+ if( input_window == w ) {
+ input_window = window_list;
+ }
+ free(w);
+ w = NULL;
+}
+
+void gui_window_get_dimensions(struct gui_window *w, int *width, int *height,
+ bool scaled)
+{
+ if (w == NULL)
+ return;
+ LGRECT rect;
+ browser_get_rect( w, BR_CONTENT, &rect );
+ *width = rect.g_w;
+ *height = rect.g_h;
+}
+
+void gui_window_set_title(struct gui_window *gw, const char *title)
+{
+ if (gw == NULL)
+ return;
+ WindSetStr( gw->root->handle, WF_NAME, (char *)title );
+}
+
+/**
+ * set the status bar message
+ */
+void gui_window_set_status(struct gui_window *w, const char *text)
+{
+ if (w == NULL)
+ return;
+ sb_set_text( w , (char*)text );
+}
+
+void gui_window_redraw(struct gui_window *gw, int x0, int y0, int x1, int y1)
+{
+ if (gw == NULL)
+ return;
+ int w,h;
+ w = x1 - x0;
+ h = y1 - y0;
+ browser_schedule_redraw( gw, x0, y0, x1, y1 );
+}
+
+void gui_window_redraw_window(struct gui_window *gw)
+{
+ CMP_BROWSER b;
+ LGRECT rect;
+ if (gw == NULL)
+ return;
+ b = gw->browser;
+ browser_get_rect( gw, BR_CONTENT, &rect );
+ browser_schedule_redraw( gw, 0, 0, rect.g_w, rect.g_h );
+}
+
+void gui_window_update_box(struct gui_window *gw,
+ const union content_msg_data *data)
+{
+ CMP_BROWSER b;
+ LGRECT cmprect;
+ if (gw == NULL)
+ return;
+ b = gw->browser;
+
+ /* the box values are actually floats */
+ int x0 = data->redraw.x - b->scroll.current.x;
+ int y0 = data->redraw.y - b->scroll.current.y;
+ int x1 = x0 + data->redraw.width;
+ int y1 = y0 + data->redraw.height;
+
+ browser_schedule_redraw( gw, x0, y0, x1, y1 );
+}
+
+bool gui_window_get_scroll(struct gui_window *w, int *sx, int *sy)
+{
+ if (w == NULL)
+ return false;
+ *sx = w->browser->scroll.current.x;
+ *sy = w->browser->scroll.current.y;
+ return( true );
+}
+
+void gui_window_set_scroll(struct gui_window *w, int sx, int sy)
+{
+ if ((w == NULL) ||
+ (w->browser->bw == NULL) ||
+ (w->browser->bw->current_content == NULL))
+ return;
+
+ if( sx != 0 ) {
+ if( sx < 0 ) {
+ browser_scroll(w, WA_LFLINE, abs(sx), true );
+ } else {
+ browser_scroll(w, WA_RTLINE, abs(sx), true );
+ }
+ }
+
+ if( sy != 0 ) {
+ if( sy < 0) {
+ browser_scroll(w, WA_UPLINE, abs(sy), true );
+ } else {
+ browser_scroll(w, WA_DNLINE, abs(sy), true );
+ }
+ }
+ return;
+
+}
+
+void gui_window_scroll_visible(struct gui_window *w, int x0, int y0, int x1, int y1)
+{
+ LOG(("%s:(%p, %d, %d, %d, %d)", __func__, w, x0, y0, x1, y1));
+}
+
+void gui_window_position_frame(struct gui_window *gw, int x0, int y0, int x1, int y1)
+{
+ TODO();
+ struct browser_window * bw = gw->browser->bw;
+ LGRECT pardim;
+ int width = x1 - x0 + 2, height = y1 - y0 + 2;
+ /* get available width/height: */
+ if( gw->parent ) {
+ browser_get_rect( gw->parent, BR_CONTENT, &pardim );
+ LOG(("posframe %s: x0,y0: %d/%d, x1,y1: %d/%d, w: %d, h: %d \n",gw->browser->bw->name, x0,y0, x1,y1, width, height));
+ }
+}
+
+
+/* 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.
+*/
+void gui_window_update_extent(struct gui_window *gw)
+{
+ int oldx, oldy;
+ oldx = gw->browser->scroll.current.x;
+ oldy = gw->browser->scroll.current.y;
+ if( gw->browser->bw->current_content != NULL ) {
+ /*printf("update_extent %p (\"%s\"), c_w: %d, c_h: %d, scale: %f\n",
+ gw->browser->bw,gw->browser->bw->name,
+ content_get_width(gw->browser->bw->current_content),
+ content_get_height(gw->browser->bw->current_content),
+ gw->browser->bw->scale
+ );*/
+ browser_set_content_size( gw,
+ content_get_width(gw->browser->bw->current_content),
+ content_get_height(gw->browser->bw->current_content)
+ );
+ }
+}
+
+
+void gui_clear_selection(struct gui_window *g)
+{
+
+}
+
+
+
+/**
+ * set the pointer shape
+ */
+void gui_window_set_pointer(struct gui_window *w, gui_pointer_shape shape)
+{
+ if (w == NULL)
+ return;
+ switch (shape) {
+ case GUI_POINTER_POINT: /* link */
+ gem_set_cursor(&gem_cursors.hand);
+ break;
+
+ case GUI_POINTER_MENU:
+ gem_set_cursor(&gem_cursors.menu);
+ break;
+
+ case GUI_POINTER_CARET: /* input */
+ gem_set_cursor(&gem_cursors.ibeam);
+ break;
+
+ case GUI_POINTER_CROSS:
+ gem_set_cursor(&gem_cursors.cross);
+ break;
+
+ case GUI_POINTER_MOVE:
+ gem_set_cursor(&gem_cursors.sizeall);
+ break;
+
+ case GUI_POINTER_RIGHT:
+ case GUI_POINTER_LEFT:
+ gem_set_cursor(&gem_cursors.sizewe);
+ break;
+
+ case GUI_POINTER_UP:
+ case GUI_POINTER_DOWN:
+ gem_set_cursor(&gem_cursors.sizens);
+ break;
+
+ case GUI_POINTER_RU:
+ case GUI_POINTER_LD:
+ gem_set_cursor(&gem_cursors.sizenesw);
+ break;
+
+ case GUI_POINTER_RD:
+ case GUI_POINTER_LU:
+ gem_set_cursor(&gem_cursors.sizenwse);
+ break;
+
+ case GUI_POINTER_WAIT:
+ gem_set_cursor(&gem_cursors.wait);
+ break;
+
+ case GUI_POINTER_PROGRESS:
+ gem_set_cursor(&gem_cursors.appstarting);
+ break;
+
+ case GUI_POINTER_NO_DROP:
+ gem_set_cursor(&gem_cursors.nodrop);
+ break;
+
+ case GUI_POINTER_NOT_ALLOWED:
+ gem_set_cursor(&gem_cursors.deny);
+ break;
+
+ case GUI_POINTER_HELP:
+ gem_set_cursor(&gem_cursors.help);
+ break;
+
+ default:
+ gem_set_cursor(&gem_cursors.arrow);
+ break;
+ }
+}
+
+void gui_window_hide_pointer(struct gui_window *w)
+{
+ TODO();
+}
+
+void gui_window_set_url(struct gui_window *w, const char *url)
+{
+ if (w == NULL)
+ return;
+ tb_url_set(w, (char*)url );
+}
+
+static void throbber_advance( void * data )
+{
+ LGRECT work;
+ struct gui_window * gw = (struct gui_window *)data;
+ if( gw->root->toolbar->throbber.running == false )
+ return;
+ mt_CompGetLGrect(&app, gw->root->toolbar->throbber.comp,
+ WF_WORKXYWH, &work);
+ gw->root->toolbar->throbber.index++;
+ if( gw->root->toolbar->throbber.index > gw->root->toolbar->throbber.max_index )
+ gw->root->toolbar->throbber.index = 0;
+ schedule(25, throbber_advance, gw );
+ ApplWrite( _AESapid, WM_REDRAW, gw->root->handle->handle,
+ work.g_x, work.g_y, work.g_w, work.g_h );
+}
+
+void gui_window_start_throbber(struct gui_window *w)
+{
+ LGRECT work;
+ if (w == NULL)
+ return;
+ mt_CompGetLGrect(&app, w->root->toolbar->throbber.comp,
+ WF_WORKXYWH, &work);
+ w->root->toolbar->throbber.running = true;
+ w->root->toolbar->throbber.index = 0;
+ schedule(25, throbber_advance, w );
+ ApplWrite( _AESapid, WM_REDRAW, w->root->handle->handle,
+ work.g_x, work.g_y, work.g_w, work.g_h );
+}
+
+void gui_window_stop_throbber(struct gui_window *w)
+{
+ LGRECT work;
+ if (w == NULL)
+ return;
+ mt_CompGetLGrect(&app, w->root->toolbar->throbber.comp,
+ WF_WORKXYWH, &work);
+ w->root->toolbar->throbber.running = false;
+ ApplWrite( _AESapid, WM_REDRAW, w->root->handle->handle,
+ work.g_x, work.g_y, work.g_w, work.g_h );
+}
+
+/* Place caret in window */
+void gui_window_place_caret(struct gui_window *w, int x, int y, int height)
+{
+ LGRECT work;
+ if (w == NULL)
+ return;
+ if( w->browser->caret.current.g_w > 0 )
+ gui_window_remove_caret( w );
+ w->browser->caret.requested.g_x = x;
+ w->browser->caret.requested.g_y = y;
+ w->browser->caret.requested.g_w = 2;
+ w->browser->caret.requested.g_h = height;
+ w->browser->caret.redraw = true;
+ browser_schedule_redraw( w, x, y, x+2, y + height );
+ return;
+}
+
+
+/**
+ * clear window caret
+ */
+void
+gui_window_remove_caret(struct gui_window *w)
+{
+ if (w == NULL)
+ return;
+ w->browser->caret.requested.g_w = 0;
+ w->browser->caret.redraw = true;
+ browser_schedule_redraw( w,
+ w->browser->caret.current.g_x,
+ w->browser->caret.current.g_y,
+ w->browser->caret.current.g_x + w->browser->caret.current.g_w + 1,
+ w->browser->caret.current.g_y + w->browser->caret.current.g_h + 1
+ );
+}
+
+void
+gui_window_set_icon(struct gui_window *g, hlcache_handle *icon)
+{
+ TODO();
+}
+
+void
+gui_window_set_search_ico(hlcache_handle *ico)
+{
+ TODO();
+}
+
+bool
+save_complete_gui_save(const char *path,
+ const char *filename,
+ size_t len,
+ const char *sourcedata,
+ content_type type)
+{
+ TODO();
+ return false;
+}
+
+int
+save_complete_htmlSaveFileFormat(const char *path,
+ const char *filename,
+ xmlDocPtr cur,
+ const char *encoding,
+ int format)
+{
+ TODO();
+ return 0;
+}
+
+
+void gui_window_new_content(struct gui_window *w)
+{
+ w->browser->scroll.current.x = 0;
+ w->browser->scroll.current.y = 0;
+ /* update scrollers? */
+}
+
+bool gui_window_scroll_start(struct gui_window *w)
+{
+ TODO();
+ return true;
+}
+
+bool gui_window_box_scroll_start(struct gui_window *w,
+ int x0, int y0, int x1, int y1)
+{
+ TODO();
+ return true;
+}
+
+bool gui_window_frame_resize_start(struct gui_window *w)
+{
+ TODO();
+ return true;
+}
+
+void gui_window_save_link(struct gui_window *g, const char *url,
+ const char *title)
+{
+ TODO();
+}
+
+void gui_window_set_scale(struct gui_window *w, float scale)
+{
+ if (w == NULL)
+ return;
+ w->browser->bw->scale = scale;
+ LOG(("%.2f\n", scale));
+ /* TODO schedule redraw */
+}
+
+void gui_drag_save_object(gui_save_type type, hlcache_handle *c,
+ struct gui_window *w)
+{
+ TODO();
+}
+
+void gui_drag_save_selection(struct selection *s, struct gui_window *w)
+{
+ TODO();
+}
+
+void gui_start_selection(struct gui_window *w)
+{
+ gui_empty_clipboard();
+}
+
+void gui_paste_from_clipboard(struct gui_window *w, int x, int y)
+{
+ char * clip = scrap_txt_read( &app );
+ if( clip == NULL )
+ return;
+ int clip_length = strlen( clip );
+ if (clip_length > 0) {
+ char *utf8;
+ utf8_convert_ret ret;
+ /* Clipboard is in local encoding so
+ * convert to UTF8 */
+ ret = local_encoding_to_utf8(clip,
+ clip_length, &utf8);
+ if (ret == UTF8_CONVERT_OK) {
+ browser_window_paste_text(w->browser->bw, utf8,
+ strlen(utf8), true);
+ free(utf8);
+ }
+ free( clip );
+ }
+}
+
+bool gui_empty_clipboard(void)
+{
+ if( tmp_clipboard != NULL ){
+ free( tmp_clipboard );
+ tmp_clipboard = NULL;
+ }
+ return true;
+}
+
+bool gui_add_to_clipboard(const char *text_utf8, size_t length_utf8, bool space)
+{
+ LOG(("(%s): %s (%d)\n", (space)?"space":"", (char*)text_utf8, (int)length_utf8));
+ char * oldptr = tmp_clipboard;
+ size_t oldlen = 0;
+ size_t newlen = 0;
+ char * text = NULL;
+ char * text2 = NULL;
+ bool retval;
+ int length = 0;
+ if( length_utf8 > 0 && text_utf8 != NULL ) {
+ utf8_to_local_encoding(text_utf8,length_utf8,&text);
+ if( text == NULL ) {
+ LOG(("Conversion failed (%s)", text_utf8));
+ goto error;
+ } else {
+ text2 = text;
+ }
+ } else {
+ if( space == false ) {
+ goto success;
+ }
+ text = malloc(length + 2);
+ if( text == NULL ) {
+ goto error;
+ }
+ text2 = text;
+ text[length+1] = 0;
+ memset(text, ' ', length+1);
+ }
+ length = strlen(text);
+ if( tmp_clipboard != NULL ) {
+ oldlen = strlen( tmp_clipboard );
+ }
+ newlen = oldlen + length + 1;
+ if( tmp_clipboard == NULL){
+ tmp_clipboard = malloc(newlen);
+ if( tmp_clipboard == NULL ) {
+ goto error;
+ }
+ strncpy(tmp_clipboard, text, newlen);
+ } else {
+ tmp_clipboard = realloc( tmp_clipboard, newlen);
+ if( tmp_clipboard == NULL ) {
+ goto error;
+ }
+ strncpy(tmp_clipboard, oldptr, newlen);
+ strncat(tmp_clipboard, text, newlen-oldlen);
+ }
+ goto success;
+
+error:
+ retval = false;
+ goto fin;
+
+success:
+ retval = true;
+
+fin:
+ if( text2 != NULL )
+ free( text2 );
+ return(retval);
+
+}
+
+bool gui_commit_clipboard(void)
+{
+ int r = scrap_txt_write(&app, tmp_clipboard);
+ return( (r>0)?true:false );
+}
+
+
+static bool
+gui_selection_traverse_handler(const char *text,
+ size_t length,
+ struct box *box,
+ void *handle,
+ const char *space_text,
+ size_t space_length)
+{
+
+ if (space_text) {
+ if (!gui_add_to_clipboard(space_text, space_length, false)) {
+ return false;
+ }
+ }
+
+ if (!gui_add_to_clipboard(text, length, box->space))
+ return false;
+
+ return true;
+}
+
+bool gui_copy_to_clipboard(struct selection *s)
+{
+ bool ret = false;
+ if( (s->defined) && (s->bw != NULL) && (s->bw->window != NULL) &&
+ (s->bw->window->root != NULL )) {
+ gui_empty_clipboard();
+ if(selection_traverse(s, gui_selection_traverse_handler, NULL)){
+ ret = gui_commit_clipboard();
+ }
+ }
+ gui_empty_clipboard();
+ return ret;
+}
+
+
+void gui_create_form_select_menu(struct browser_window *bw,
+ struct form_control *control)
+{
+ TODO();
+}
+
+/**
+ * Broadcast an URL that we can't handle.
+ */
+void gui_launch_url(const char *url)
+{
+ TODO();
+ LOG(("launch file: %s\n", url));
+}
+
+void gui_401login_open(const char *url, const char *realm,
+ nserror (*cb)(bool proceed, void *pw), void *cbpw)
+{
+ bool bres;
+ char * out = NULL;
+ bres = login_form_do( (char*)url, (char*)realm, &out );
+ if( bres ) {
+ LOG(("url: %s, realm: %s, auth: %s\n", url, realm, out ));
+ urldb_set_auth_details(url, realm, out );
+ }
+ if( out != NULL ){
+ free( out );
+ }
+ if( cb != NULL )
+ cb(bres, cbpw);
+}
+
+void gui_cert_verify(const char *url, const struct ssl_cert_info *certs,
+ unsigned long num,
+ nserror (*cb)(bool proceed, void *pw), void *cbpw)
+{
+ LOG((""));
+
+ bool bres;
+ /*bres = verify_ssl_form_do(url, certs, num);
+ if( bres )
+ urldb_set_cert_permissions(url, true);
+ */
+ int b = form_alert(1, "[2][SSL Verify failed, continue?][Continue|Abort]");
+ bres = (b==1)? true : false;
+ LOG(("Trust: %d", bres ));
+ urldb_set_cert_permissions(url, bres);
+ cb(bres, cbpw);
+}
+
+
+static void *myrealloc(void *ptr, size_t len, void *pw)
+{
+ return realloc(ptr, len);
+}
+
+void gui_quit(void)
+{
+ LOG((""));
+
+ struct gui_window * gw = window_list;
+ struct gui_window * tmp = window_list;
+
+ while( gw ) {
+ tmp = gw->next;
+ if( gw->parent == NULL ) {
+ browser_window_destroy(gw->browser->bw);
+ }
+ gw = tmp;
+ }
+ hotlist_destroy();
+ /* send WM_DESTROY to windows purely managed by windom: */
+ while( wglb.first ) {
+ ApplWrite( _AESapid, WM_DESTROY, wglb.first->handle, 0, 0, 0, 0);
+ EvntWindom( MU_MESAG );
+ }
+
+ RsrcXtype( 0, rsc_trindex, rsc_ntree);
+ unbind_global_events();
+ MenuBar( h_gem_menu , 0 );
+ if( h_gem_rsrc == NULL ) {
+ RsrcXfree(h_gem_rsrc );
+ }
+ LOG(("Shutting down plotter"));
+ atari_plotter_finalise();
+ LOG(("FrameExit"));
+ mt_FrameExit( &app );
+ if( tmp_clipboard != NULL ){
+ free( tmp_clipboard );
+ tmp_clipboard = NULL;
+ }
+ LOG(("done"));
+}
+
+
+
+
+static bool
+process_cmdline(int argc, char** argv)
+{
+ int opt;
+
+ LOG(("argc %d, argv %p", argc, argv));
+
+ if ((option_window_width != 0) && (option_window_height != 0)) {
+ cfg_width = option_window_width;
+ cfg_height = option_window_height;
+ } else {
+ cfg_width = 800;
+ cfg_height = 600;
+ }
+
+ if (option_homepage_url != NULL && option_homepage_url[0] != '\0')
+ cfg_homepage_url = option_homepage_url;
+ else
+ cfg_homepage_url = NETSURF_HOMEPAGE;
+
+
+ while((opt = getopt(argc, argv, "w:h:")) != -1) {
+ switch (opt) {
+ case 'w':
+ cfg_width = atoi(optarg);
+ break;
+
+ case 'h':
+ cfg_height = atoi(optarg);
+ break;
+
+ default:
+ fprintf(stderr,
+ "Usage: %s [w,h,v] url\n",
+ argv[0]);
+ return false;
+ }
+ }
+
+ if (optind < argc) {
+ cfg_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 void gui_init(int argc, char** argv)
+{
+ char buf[PATH_MAX], sbuf[PATH_MAX];
+ int len;
+ OBJECT * cursors;
+
+ atari_find_resource(buf, "netsurf.rsc", "./res/netsurf.rsc");
+ LOG(("Load %s ", (char*)&buf));
+ h_gem_rsrc = RsrcXload( (char*) &buf );
+ if( !h_gem_rsrc )
+ die("Uable to open GEM Resource file!");
+
+ rsc_trindex = RsrcGhdr(h_gem_rsrc)->trindex;
+ rsc_ntree = RsrcGhdr(h_gem_rsrc)->ntree;
+
+ RsrcGaddr( h_gem_rsrc, R_TREE, MAINMENU , &h_gem_menu );
+ RsrcXtype( RSRC_XALL, rsc_trindex, rsc_ntree);
+
+ 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);
+ RsrcGaddr( h_gem_rsrc, R_TREE, CURSOR , &cursors );
+ 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"));
+ option_core_select_menu = true;
+
+ atari_find_resource(buf, "default.css", "./res/default.css");
+ default_stylesheet_url = path_to_url(buf);
+ LOG(("Using '%s' as Default CSS URL", default_stylesheet_url));
+
+ atari_find_resource(buf, "quirks.css", "./res/quirks.css");
+ quirks_stylesheet_url = path_to_url(buf);
+
+ if (process_cmdline(argc,argv) != true)
+ die("unable to process command line.\n");
+
+ nkc_init();
+ atari_plotter_init( option_atari_screen_driver, option_atari_font_driver );
+}
+
+static void gui_init2(int argc, char** argv)
+{
+ struct browser_window *bw;
+ const char *addr = NETSURF_HOMEPAGE;
+ MenuBar( h_gem_menu , 1 );
+ bind_global_events();
+ menu_register( _AESapid, (char*)" NetSurf ");
+}
+
+
+/** 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 options[PATH_MAX];
+ char messages[PATH_MAX];
+
+ setbuf(stderr, NULL);
+
+ ApplInit();
+
+ graf_mouse(BUSY_BEE, NULL);
+
+ atari_find_resource(messages, "messages", "./res/messages");
+ atari_find_resource(options, "Choices", "./Choices");
+ options_file_location = strdup(options);
+
+ netsurf_init(&argc, &argv, options, messages);
+ gui_init(argc, argv);
+ gui_init2(argc, argv);
+ browser_window_create(cfg_homepage_url, 0, 0, true, false);
+ graf_mouse( ARROW , NULL);
+ netsurf_main_loop();
+ netsurf_exit();
+ LOG(("ApplExit"));
+ ApplExit();
+
+ return 0;
+}
+
+
diff --git a/atari/gui.h b/atari/gui.h
new file mode 100644
index 000000000..dad25fa80
--- /dev/null
+++ b/atari/gui.h
@@ -0,0 +1,236 @@
+/*
+ * 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 <windom.h>
+
+#define WM_FORCE_MOVE 1024 + 3
+
+struct point_s {
+ int x;
+ int y;
+};
+
+struct bbox_s {
+ int x0;
+ int y0;
+ int x1;
+ int y1;
+};
+
+typedef struct bbox_s BBOX;
+typedef struct point_s POINT;
+
+#define MFORM_EX_FLAG_USERFORM 0x01
+#define MFORM_EX_FLAG_REDRAW_REQUIRED 0x02
+
+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;
+
+/* maybe its better to have an linked
+ list of redraw areas, so that there
+ is no such an overhead when 2 (or more)
+ SMALL rectangles far away from each other
+ need an redraw!
+ Currently these rects get summarized into
+ one big redraw area!
+*/
+struct s_browser_redrw_info
+{
+ BBOX area; /* this is an box which describes the area to redraw */
+ /* from netsurfs point of view */
+ bool required;
+};
+
+struct s_scroll_info
+{
+ POINT requested;
+ POINT current;
+ bool required;
+};
+
+enum focus_element_type {
+ WIDGET_NONE=0,
+ URL_WIDGET,
+ BROWSER
+};
+
+
+struct s_focus_info
+{
+ enum focus_element_type type;
+ void * element;
+};
+
+
+struct s_gui_input_state {
+ short mbut;
+ short mkstat;
+ short mx;
+ short my;
+} prev_inp_state;
+
+
+#define TB_BUTTON_WIDTH 32
+#define TB_BUTTON_HEIGHT 21 /* includes 1px 3d effect */
+#define TOOLBAR_HEIGHT 25
+#define URLBOX_HEIGHT 21
+#define STATUSBAR_HEIGHT 16
+#define MOVER_WH 16
+#define THROBBER_WIDTH 32
+
+
+/* defines for data attached to components: */
+#define CDT_OBJECT 0x004f424aUL
+#define CDT_OWNER 0x03UL
+#define CDT_ICON 0x04UL
+#define CDT_ICON_TYPE 0x05UL
+
+/*
+ URL Widget Block size: size of memory block to allocated
+ when input takes more memory than currently allocated:
+*/
+#define URL_WIDGET_BSIZE 64
+#define URL_WIDGET_MAX_MEM 60000
+struct s_url_widget
+{
+ short selection_len; /* len & direction of selection */
+ short caret_pos; /* cursor pos */
+ short char_size; /* size of one character (width & hight) */
+ short scrollx; /* current scroll position */
+ bool redraw; /* widget is only redrawn when this flag is set */
+ char * text; /* dynamicall allocated URL string*/
+ unsigned short allocated;
+ unsigned short used; /* memory used by URL (strlen + 1) */
+ COMPONENT * comp;
+};
+
+struct s_throbber_widget
+{
+ COMPONENT * comp;
+ short index;
+ short max_index;
+ bool running;
+};
+
+struct gui_window;
+
+struct s_tb_button
+{
+ short rsc_id;
+ void (*cb_click)(struct gui_window * gw);
+ COMPONENT * comp;
+};
+
+struct s_toolbar
+{
+ COMPONENT * comp;
+ struct gui_window * owner;
+ struct s_url_widget url;
+ struct s_throbber_widget throbber;
+ GRECT btdim; /* size & location of buttons */
+ struct s_tb_button * buttons;
+ int btcnt;
+ /* buttons are defined in toolbar.c */
+};
+
+struct s_statusbar
+{
+ COMPONENT * comp;
+ char text[255];
+};
+
+struct s_caret
+{
+ GRECT requested;
+ GRECT current;
+ bool redraw;
+};
+
+struct s_browser
+{
+ int type;
+ COMPONENT * comp;
+ WINDOW * compwin;
+ struct browser_window * bw;
+ struct s_scroll_info scroll;
+ struct s_browser_redrw_info redraw;
+ struct s_caret caret;
+ bool attached;
+};
+
+typedef struct s_toolbar * CMP_TOOLBAR;
+typedef struct s_statusbar * CMP_STATUSBAR;
+typedef struct s_browser * CMP_BROWSER;
+
+struct s_gui_win_root
+{
+ WINDOW * handle;
+ CMP_TOOLBAR toolbar;
+ CMP_STATUSBAR statusbar;
+ COMPONENT * cmproot;
+ MFORM_EX cursor;
+ struct s_focus_info focus;
+ float scale;
+ bool throbbing;
+ GRECT loc; /* current size of window on screen */
+};
+
+struct gui_window {
+ struct s_gui_win_root * root;
+ CMP_BROWSER browser;
+ struct gui_window * parent;
+ struct gui_window *next, *prev;
+};
+
+
+extern struct gui_window *window_list;
+
+/* scroll a window */
+void gem_window_scroll(struct browser_window * , int x, int y);
+
+#define MOUSE_IS_DRAGGING() (mouse_hold_start[0] || mouse_hold_start[1])
+
+
+#endif
diff --git a/atari/history.c b/atari/history.c
new file mode 100644
index 000000000..b26257475
--- /dev/null
+++ b/atari/history.c
@@ -0,0 +1,30 @@
+/*
+ * 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 "content/urldb.h"
+#include "desktop/browser.h"
+
+void global_history_add_recent(const char *url)
+{
+}
+
+char **global_history_get_recent(int *count)
+{
+ return NULL;
+}
+
diff --git a/atari/history.h b/atari/history.h
new file mode 100644
index 000000000..5899e4cf9
--- /dev/null
+++ b/atari/history.h
@@ -0,0 +1,22 @@
+/*
+ * 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_HISTORY_H
+#define NS_ATARI_HISTORY_H
+
+#endif
diff --git a/atari/hotlist.c b/atari/hotlist.c
new file mode 100644
index 000000000..c0f4a93d3
--- /dev/null
+++ b/atari/hotlist.c
@@ -0,0 +1,165 @@
+/*
+ * 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 <ctype.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include "desktop/browser.h"
+#include "content/content.h"
+#include "content/hlcache.h"
+#include "content/urldb.h"
+#include "desktop/options.h"
+#include "desktop/hotlist.h"
+#include "desktop/tree.h"
+#include "desktop/gui.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/utils.h"
+#include "utils/url.h"
+#include "atari/gui.h"
+#include "atari/misc.h"
+#include "atari/treeview.h"
+#include "atari/hotlist.h"
+#include "atari/findfile.h"
+#include "atari/res/netsurf.rsh"
+
+static struct atari_hotlist {
+ WINDOW * window;
+ NSTREEVIEW tv; /*< The hotlist treeview handle. */
+ bool open;
+} hl;
+
+static const struct {
+ const char *url;
+ const char *msg_key;
+} default_entries[] = {
+ { "http://www.netsurf-browser.org/", "HotlistHomepage" },
+ { "http://www.netsurf-browser.org/downloads/riscos/testbuilds", "HotlistTestBuild" },
+ { "http://www.netsurf-browser.org/documentation", "HotlistDocumentation" },
+ { "http://sourceforge.net/tracker/?atid=464312&group_id=51719",
+ "HotlistBugTracker" },
+ { "http://sourceforge.net/tracker/?atid=464315&group_id=51719",
+ "HotlistFeatureRequest" }
+};
+#define ENTRIES_COUNT (sizeof(default_entries) / sizeof(default_entries[0]))
+
+
+static void evnt_hl_toolbar( WINDOW *win, short buff[8]) {
+ int obj = buff[4]; /* Selected object */
+
+ LOG(("item: %d clicked", obj ));
+
+ switch( obj) {
+ case TOOLBAR_HOTLIST_CREATE_FOLDER:
+ break;
+ case TOOLBAR_HOTLIST_ADD:
+ break;
+ case TOOLBAR_HOTLIST_DELETE:
+ break;
+ }
+
+ /* object state to normal and redraw object */
+/*
+ ObjcChange( TOOLBAR_HOTLIST, hl.window, obj, SELECTED, 1);
+ ObjcChange( TOOLBAR_HOTLIST, hl.window, obj, 0 , 1);
+*/
+}
+
+static void __CDECL evnt_hl_close( WINDOW *win, short buff[8] )
+{
+ hotlist_close();
+}
+
+void hotlist_init(void)
+{
+ char hlfilepath[PATH_MAX];
+
+ atari_find_resource(
+ (char*)&hlfilepath, "hotlist", "./res/Hotlist"
+ );
+
+ if( hl.window == NULL ){
+ int flags = CLOSER | MOVER | SIZER| NAME | FULLER | SMALLER ;
+ OBJECT * tree = get_tree(TOOLBAR_HOTLIST);
+ assert( tree );
+ hl.open = false;
+ hl.window = WindCreate( flags,40, 40, app.w, app.h );
+ if( hl.window == NULL ) {
+ LOG(("Failed to allocate Hotlist"));
+ return;
+ }
+ /* TODO: load hotlist strings from messages */
+ WindSetStr( hl.window, WF_NAME, (char*)"Hotlist" );
+ WindSetPtr( hl.window, WF_TOOLBAR,
+ tree,
+ evnt_hl_toolbar
+ );
+ EvntAttach( hl.window, WM_CLOSED, evnt_hl_close );
+ hl.tv = atari_treeview_create(
+ hotlist_get_tree_flags(),
+ hl.window
+ );
+ if (hl.tv == NULL) {
+ LOG(("Failed to allocate treeview"));
+ return;
+ }
+ hotlist_initialise(
+ atari_treeview_get_tree(hl.tv),
+ /* TODO: use option_hotlist_file or slt*/
+ (char*)&hlfilepath,
+ hlfilepath
+ );
+ } else {
+
+ }
+}
+
+
+void hotlist_open(void)
+{
+ hotlist_init();
+ if( hl.open == false ) {
+ WindOpen( hl.window, -1, -1, app.w/3, app.h/2);
+ hl.open = true;
+ }
+ tree_set_redraw(atari_treeview_get_tree(hl.tv), true);
+}
+
+void hotlist_close(void)
+{
+ WindClose(hl.window);
+ hl.open = false;
+}
+
+void hotlist_destroy(void)
+{
+ if( hl.window != NULL ) {
+ if( hl.open )
+ hotlist_close();
+ WindDelete( hl.window );
+ printf("delete hl tree");
+ atari_treeview_destroy( hl.tv );
+ hl.window = NULL;
+ }
+}
+
+
+
diff --git a/atari/hotlist.h b/atari/hotlist.h
new file mode 100644
index 000000000..78a88e27c
--- /dev/null
+++ b/atari/hotlist.h
@@ -0,0 +1,30 @@
+/*
+ * 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_HOTLIST_H
+#define NS_ATARI_HOTLIST_H
+
+/* The hotlist window, toolbar and treeview data. */
+
+
+void hotlist_init(void);
+void hotlist_open(void);
+void hotlist_close(void);
+void hotlist_destroy(void);
+
+#endif \ No newline at end of file
diff --git a/atari/login.c b/atari/login.c
new file mode 100644
index 000000000..2dc766f56
--- /dev/null
+++ b/atari/login.c
@@ -0,0 +1,110 @@
+/*
+ * 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 "desktop/401login.h"
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <windom.h>
+#include "utils/config.h"
+#include "content/content.h"
+#include "content/hlcache.h"
+#include "content/urldb.h"
+#include "desktop/browser.h"
+#include "desktop/401login.h"
+#include "desktop/gui.h"
+#include "utils/errors.h"
+#include "utils/utils.h"
+#include "utils/messages.h"
+#include "utils/log.h"
+#include "utils/url.h"
+#include "content/urldb.h"
+#include "content/fetch.h"
+#include "atari/login.h"
+#include "atari/res/netsurf.rsh"
+
+
+extern void * h_gem_rsrc;
+
+bool login_form_do( char * url, char * realm, char ** out )
+{
+ OBJECT *tree, *newtree;
+ WINDOW * form;
+ char user[255];
+ char pass[255];
+ bool bres = false;
+ int res = 0;
+ const char * auth;
+ char * host;
+ assert( url_host( url, &host) == URL_FUNC_OK );
+
+ if( realm == NULL ){
+ realm = (char*)"Secure Area";
+ }
+
+ int len = strlen(realm) + strlen(host) + 4;
+ char * title = malloc( len );
+ strncpy(title, realm, len );
+ strncpy(title, ": ", len-strlen(realm) );
+ strncat(title, host, len-strlen(realm)+2 );
+
+ auth = urldb_get_auth_details(url, realm);
+ user[0] = 0;
+ pass[0] = 0;
+ /*
+ TODO: use auth details if available:
+ if( auth == NULL ){
+
+ } else {
+
+ }*/
+
+ RsrcGaddr (h_gem_rsrc , R_TREE, LOGIN, &tree);
+ ObjcChange( OC_OBJC, tree, LOGIN_BT_LOGIN, 0, 0 );
+ ObjcChange( OC_OBJC, tree, LOGIN_BT_ABORT, 0, 0 );
+ ObjcString( tree, LOGIN_TB_USER, (char*)&user );
+ ObjcString( tree, LOGIN_TB_PASSWORD, (char*)&pass );
+ form = FormWindBegin( tree, (char *)title );
+ res = -1;
+ while( res != LOGIN_BT_LOGIN && res != LOGIN_BT_ABORT ){
+ res = FormWindDo( MU_MESAG );
+ switch( res ){
+ case LOGIN_BT_LOGIN:
+ bres = true;
+ break;
+
+ case LOGIN_BT_ABORT:
+ bres = false;
+ break;
+ }
+ }
+
+ if( bres ) {
+ *out = malloc(strlen((char*)&user) + strlen((char*)&pass) + 2 );
+ strcpy(*out, (char*)&user);
+ strcat(*out, ":");
+ strcat(*out, (char*)&pass);
+ } else {
+ *out = NULL;
+ }
+
+ FormWindEnd( );
+ free( title );
+ return( bres );
+}
diff --git a/atari/login.h b/atari/login.h
new file mode 100644
index 000000000..52a4832c9
--- /dev/null
+++ b/atari/login.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_LOGIN_H_INCLUDED
+#define NS_LOGIN_H_INCLUDED
+
+bool login_form_do( char * host, char * realm, char **cbpw );
+
+#endif
diff --git a/atari/misc.c b/atari/misc.c
new file mode 100644
index 000000000..674dd8639
--- /dev/null
+++ b/atari/misc.c
@@ -0,0 +1,184 @@
+/*
+ * 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 <windom.h>
+
+#include "desktop/cookies.h"
+#include "desktop/mouse.h"
+#include "utils/messages.h"
+#include "utils/utils.h"
+#include "utils/url.h"
+#include "utils/log.h"
+#include "content/fetch.h"
+#include "atari/gui.h"
+#include "atari/toolbar.h"
+#include "atari/misc.h"
+
+extern void * h_gem_rsrc;
+
+void 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);
+}
+
+void die(const char *error)
+{
+ printf("%s\n", error);
+ exit(1);
+}
+
+bool cookies_update(const char *domain, const struct cookie_data *data)
+{
+ return true;
+}
+
+/**
+ * Return the filename part of a full path
+ *
+ * \param path full path and filename
+ * \return filename (will be freed with free())
+ */
+
+char *filename_from_path(char *path)
+{
+ char *leafname;
+
+ leafname = strrchr(path, '\\');
+ if (!leafname)
+ leafname = path;
+ else
+ leafname += 1;
+
+ return strdup(leafname);
+}
+
+/**
+ * Add a path component/filename to an existing path
+ *
+ * \param path buffer containing path + free space
+ * \param length length of buffer "path"
+ * \param newpart string containing path component to add to path
+ * \return true on success
+ */
+
+bool path_add_part(char *path, int length, const char *newpart)
+{
+ if(path[strlen(path) - 1] != '/')
+ strncat(path, "/", length);
+
+ strncat(path, newpart, length);
+
+ return true;
+}
+
+#define IS_TOPLEVEL_BROWSER_WIN( gw ) (gw->root->handle == win && gw->parent == NULL )
+struct gui_window * find_root_gui_window( WINDOW * win )
+{
+
+ int i=0;
+ struct gui_window * gw;
+ gw = window_list;
+ while( gw != NULL ) {
+ if( IS_TOPLEVEL_BROWSER_WIN( gw ) ) {
+ return( gw );
+ }
+ else
+ gw = gw->next;
+ i++;
+ assert( i < 1000);
+ }
+ return( NULL );
+}
+
+
+struct gui_window * find_cmp_window( COMPONENT * c )
+{
+ struct gui_window * gw;
+ int i=0;
+ gw = window_list;
+ while( gw != NULL ) {
+ assert( gw->browser != NULL );
+ if( gw->browser->comp == c ) {
+ return( gw );
+ }
+ else
+ gw = gw->next;
+ i++;
+ assert( i < 1000);
+ }
+ return( NULL );
+}
+
+
+/* -------------------------------------------------------------------------- */
+/* GEM Utillity functions: */
+/* -------------------------------------------------------------------------- */
+
+/* Return a string from resource file */
+char *get_rsc_string( int idx) {
+ char *txt;
+ RsrcGaddr( h_gem_rsrc, R_STRING, idx, &txt );
+ return txt;
+}
+
+OBJECT *get_tree( int idx) {
+ OBJECT *tree;
+ RsrcGaddr( h_gem_rsrc, R_TREE, idx, &tree);
+ return tree;
+}
+
+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 ) {
+ MouseSprite( cursor->tree, cursor->number);
+ } else {
+ graf_mouse(cursor->number, NULL );
+ }
+ number = cursor->number;
+ flags = cursor->flags;
+}
+
+void dbg_lgrect( char * str, LGRECT * r )
+{
+ printf("%s: x: %d, y: %d, w: %d, h: %d\n", str,
+ r->g_x, r->g_y, r->g_w, r->g_h );
+}
+
+void dbg_grect( char * str, GRECT * r )
+{
+ printf("%s: x: %d, y: %d, w: %d, h: %d\n", str,
+ r->g_x, r->g_y, r->g_w, r->g_h );
+}
+
+void dbg_pxy( char * str, short * pxy )
+{
+ printf("%s: x: %d, y: %d, w: %d, h: %d\n", str,
+ pxy[0], pxy[1], pxy[2], pxy[3] );
+}
diff --git a/atari/misc.h b/atari/misc.h
new file mode 100644
index 000000000..a2da94095
--- /dev/null
+++ b/atari/misc.h
@@ -0,0 +1,38 @@
+/*
+ * 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];
+
+struct gui_window * find_root_gui_window( WINDOW * win );
+struct gui_window * find_cmp_window( COMPONENT * c );
+OBJECT *get_tree( int idx );
+char *get_rsc_string( int idx );
+void gem_set_cursor( MFORM_EX * cursor );
+void dbg_grect( char * str, GRECT * r );
+#endif \ No newline at end of file
diff --git a/atari/options.h b/atari/options.h
new file mode 100644
index 000000000..3425930fb
--- /dev/null
+++ b/atari/options.h
@@ -0,0 +1,73 @@
+/*
+ * 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_OPTIONS_H_
+#define NS_ATARI_OPTIONS_H_
+
+#include "desktop/options.h"
+extern char * option_atari_screen_driver;
+extern char * option_atari_font_driver;
+extern int option_atari_font_monochrom;
+extern int option_atari_dither;
+extern int option_atari_transparency;
+extern char *option_atari_face_sans_serif; /* default sans face */
+extern char *option_atari_face_sans_serif_bold; /* bold sans face */
+extern char *option_atari_face_sans_serif_italic; /* bold sans face */
+extern char *option_atari_face_sans_serif_italic_bold; /* bold sans face */
+extern char *option_atari_face_monospace; /* monospace face */
+extern char *option_atari_face_monospace_bold; /* monospace face */
+extern char *option_atari_face_serif; /* serif face */
+extern char *option_atari_face_serif_bold; /* bold serif face */
+extern char *option_atari_face_cursive;
+extern char *option_atari_face_fantasy;
+
+#define EXTRA_OPTION_DEFINE \
+char * option_atari_screen_driver = (char*)"vdi";\
+char * option_atari_font_driver = (char*)"vdi";\
+int option_atari_font_monochrom = 0;\
+int option_atari_dither = 1;\
+int option_atari_transparency = 1;\
+char *option_atari_face_sans_serif; \
+char *option_atari_face_sans_serif_bold; \
+char *option_atari_face_sans_serif_italic; \
+char *option_atari_face_sans_serif_italic_bold; \
+char *option_atari_face_monospace; \
+char *option_atari_face_monospace_bold; \
+char *option_atari_face_serif; \
+char *option_atari_face_serif_bold; \
+char *option_atari_face_cursive; \
+char *option_atari_face_fantasy;
+
+#define EXTRA_OPTION_TABLE \
+ { "atari_screen_driver", OPTION_STRING, &option_atari_screen_driver },\
+ { "atari_font_driver", OPTION_STRING, &option_atari_font_driver },\
+ { "atari_font_monochrom", OPTION_INTEGER, &option_atari_font_monochrom },\
+ { "atari_transparency", OPTION_INTEGER, &option_atari_transparency },\
+ { "atari_dither", OPTION_INTEGER, &option_atari_dither },\
+ { "font_face_sans_serif", OPTION_STRING, &option_atari_face_sans_serif },\
+ { "font_face_sans_serif_bold", OPTION_STRING, &option_atari_face_sans_serif_bold },\
+ { "font_face_sans_serif_italic", OPTION_STRING, &option_atari_face_sans_serif_italic },\
+ { "font_face_sans_serif_italic_bold", OPTION_STRING, &option_atari_face_sans_serif_italic_bold },\
+ { "font_face_monospace", OPTION_STRING, &option_atari_face_monospace },\
+ { "font_face_monospace_bold", OPTION_STRING, &option_atari_face_monospace_bold },\
+ { "font_face_serif", OPTION_STRING, &option_atari_face_serif },\
+ { "font_face_serif_bold", OPTION_STRING, &option_atari_face_serif_bold },\
+ { "font_face_cursive", OPTION_STRING, &option_atari_face_cursive },\
+ { "font_face_fantasy", OPTION_STRING, &option_atari_face_fantasy }
+#endif
+
diff --git a/atari/plot.c b/atari/plot.c
new file mode 100644
index 000000000..d7f4b4ba0
--- /dev/null
+++ b/atari/plot.c
@@ -0,0 +1,222 @@
+/*
+ * 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 <stdint.h>
+#include <string.h>
+#include <limits.h>
+#include <math.h>
+#include <stdbool.h>
+#include <windom.h>
+
+#include "image/bitmap.h"
+#include "utils/log.h"
+#include "utils/utf8.h"
+#include "utils/utils.h"
+#include "desktop/gui.h"
+#include "desktop/plotters.h"
+
+#include "atari/bitmap.h"
+#include "atari/gui.h"
+#include "atari/plot.h"
+#include "atari/options.h"
+#include "desktop/options.h"
+#include "atari/plot.h"
+
+GEM_PLOTTER plotter = NULL;
+GEM_FONT_PLOTTER fplotter = NULL;
+
+extern APPvar * appv;
+extern short vdih;
+
+/*
+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 atari_plotter_init( char* drvrname, char * fdrvrname )
+{
+ GRECT loc_pos={0,0,420,420};
+ int err=0;
+ struct s_driver_table_entry * drvinfo;
+ int flags = 0;
+
+ if( option_atari_dither == 1)
+ flags |= PLOT_FLAG_DITHER;
+ if( option_atari_transparency == 1 )
+ flags |= PLOT_FLAG_TRANS;
+
+ vdih = app.graf.handle;
+ if( verbose_log ) {
+ dump_vdi_info( vdih ) ;
+ dump_plot_drivers();
+ dump_font_drivers();
+ }
+
+ drvinfo = get_screen_driver_entry( drvrname );
+
+ LOG(("using plotters: %s, %s", drvrname, fdrvrname));
+ fplotter = new_font_plotter(vdih, fdrvrname, 0, &err );
+ if(err)
+ die(("Unable to load font plotter %s -> %s", fdrvrname, plotter_err_str(err) ));
+
+ plotter = new_plotter( vdih, drvrname, &loc_pos, drvinfo->max_bpp,
+ flags, fplotter, &err );
+ if(err)
+ die(("Unable to load graphics plotter %s -> %s", drvrname, plotter_err_str(err) ));
+
+ return( err );
+}
+
+int atari_plotter_finalise( void )
+{
+ delete_plotter( plotter );
+ delete_font_plotter( fplotter );
+}
+
+bool plot_rectangle( int x0, int y0, int x1, int y1,
+ const plot_style_t *style )
+{
+ plotter->rectangle( plotter, x0, y0, x1, y1, style );
+ return ( true );
+}
+
+static bool plot_line( int x0, int y0, int x1, int y1,
+ const plot_style_t *style )
+{
+ plotter->line( plotter, x0, y0, x1, y1, style );
+ return ( true );
+}
+
+static bool plot_polygon(const int *p, unsigned int n,
+ const plot_style_t *style)
+{
+ plotter->polygon( plotter, p, n, style );
+ return ( true );
+}
+
+bool plot_clip(int x0, int y0, int x1, int y1)
+{
+ plotter->clip( plotter, x0, y0, x1, y1 );
+ return ( true );
+}
+
+bool plot_get_clip(struct s_clipping * out){
+ out->x0 = plotter->clipping.x0;
+ out->y0 = plotter->clipping.y0;
+ out->x1 = plotter->clipping.x1;
+ out->y1 = plotter->clipping.y1;
+ return( true );
+}
+
+static bool plot_text(int x, int y, const char *text, size_t length, const plot_font_style_t *fstyle )
+{
+ plotter->text( plotter, x, y, text, length, fstyle );
+ return ( true );
+}
+
+static bool plot_disc(int x, int y, int radius, const plot_style_t *style)
+{
+ plotter->disc(plotter, x, y, radius, style );
+ return ( true );
+}
+
+static bool plot_arc(int x, int y, int radius, int angle1, int angle2,
+ const plot_style_t *style)
+{
+ plotter->arc( plotter, x, y, radius, angle1, angle2, style );
+ 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);
+
+ if( option_suppress_images != 0 ) {
+ return( true );
+ }
+
+ if( width != bitmap_get_width(bitmap) || height != bitmap_get_height( bitmap) ) {
+ assert( plotter->bitmap_resize(plotter, bitmap, width, height ) == 0);
+ bm = bitmap->resized;
+ } else {
+ bm = bitmap;
+ }
+
+ /* out of memory? */
+ if( bm == NULL )
+ return( true );
+
+ if (!(repeat_x || repeat_y)) {
+ plotter->bitmap( plotter, bm, x, y, bg, flags );
+ } else {
+ int xf,yf;
+ struct s_clipping clip;
+ plotter_get_clip( plotter, &clip );
+ int xoff = x;
+ int yoff = y;
+ /* 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 ) {
+ plotter->bitmap( plotter, 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])
+{
+ plotter->path( plotter, p, n, fill, width, c, transform );
+ return ( true );
+}
+
+
+
+struct plotter_table plot = {
+ .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 = false */
+ .option_knockout = true
+};
diff --git a/atari/plot.h b/atari/plot.h
new file mode 100644
index 000000000..ed86041e5
--- /dev/null
+++ b/atari/plot.h
@@ -0,0 +1,32 @@
+/*
+ * 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
+
+#include "desktop/plotters.h"
+#include "atari/plot/plotter.h"
+
+int atari_plotter_init( char*, char * );
+int atari_plotter_finalise( void );
+
+bool plot_get_clip(struct s_clipping * out);
+bool plot_clip(int x0, int y0, int x1, int y1);
+bool plot_rectangle( int x0, int y0, int x1, int y1,const plot_style_t *style );
+
+#endif
diff --git a/atari/plot/eddi.h b/atari/plot/eddi.h
new file mode 100644
index 000000000..7d6b90d4b
--- /dev/null
+++ b/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/atari/plot/eddi.s b/atari/plot/eddi.s
new file mode 100644
index 000000000..f0ea18a1e
--- /dev/null
+++ b/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/atari/plot/font_freetype.c b/atari/plot/font_freetype.c
new file mode 100644
index 000000000..0a1addfdf
--- /dev/null
+++ b/atari/plot/font_freetype.c
@@ -0,0 +1,512 @@
+/*
+ * 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/>.
+ */
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <math.h>
+#include <assert.h>
+#include <string.h>
+#include <windom.h>
+#include <ft2build.h>
+#include FT_CACHE_H
+
+#include "desktop/plot_style.h"
+#include "image/bitmap.h"
+#include "atari/bitmap.h"
+#include "atari/plot/plotter.h"
+#include "atari/plot/font_freetype.h"
+#include "atari/gui.h"
+#include "atari/font.h"
+#include "atari/options.h"
+#include "atari/findfile.h"
+#include "utils/utf8.h"
+#include "utils/log.h"
+
+#define DEJAVU_PATH "/usr/share/fonts/truetype/ttf-dejavu/"
+
+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 struct bitmap * fontbmp;
+
+static ftc_faceid_t *font_faces[FONT_FACE_COUNT];
+
+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_position( 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;
+
+
+
+/* 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];
+ char resname2[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_CURSIVE:
+ break;
+ case PLOT_FONT_FAMILY_FANTASY:
+ break;
+*/
+ case PLOT_FONT_FAMILY_SERIF:
+ if (fstyle->weight >= 700)
+ selected_face = FONT_FACE_SERIF_BOLD;
+ else
+ selected_face = FONT_FACE_SERIF;
+
+ break;
+
+ case PLOT_FONT_FAMILY_MONOSPACE:
+ selected_face = FONT_FACE_MONOSPACE;
+ break;
+
+ case PLOT_FONT_FAMILY_SANS_SERIF:
+ default:
+ if ((fstyle->flags & FONTF_ITALIC) || (fstyle->flags & FONTF_OBLIQUE)) {
+ if (fstyle->weight >= 700)
+ selected_face = FONT_FACE_SANS_SERIF_ITALIC_BOLD;
+ else
+ selected_face = FONT_FACE_SANS_SERIF_ITALIC;
+ } else {
+ if (fstyle->weight >= 700)
+ 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;
+ srec->x_res = srec->y_res = 72;
+}
+
+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;
+
+ /* freetype library initialise */
+ error = FT_Init_FreeType( &library );
+ if (error) {
+ LOG(("Freetype could not initialised (code %d)\n", error));
+ return false;
+ }
+
+ max_cache_size = 2 * 1024 *1024; /* 2MB should be enough */
+
+ /* 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);
+
+ font_faces[FONT_FACE_SANS_SERIF] = NULL;
+ font_faces[FONT_FACE_SANS_SERIF] = ft_new_face(
+ option_atari_face_sans_serif,
+ "fonts/ss.ttf",
+ DEJAVU_PATH"DejaVuSans.ttf"
+ );
+ 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;
+ }
+
+ font_faces[FONT_FACE_SANS_SERIF_BOLD] =
+ ft_new_face(option_atari_face_sans_serif_bold,
+ "fonts/ssb.ttf",
+ DEJAVU_PATH"DejaVuSans-Bold.ttf");
+
+ font_faces[FONT_FACE_SANS_SERIF_ITALIC] =
+ ft_new_face(option_atari_face_sans_serif_italic,
+ "fonts/ssi.ttf",
+ DEJAVU_PATH"DejaVuSans-Oblique.ttf");
+
+ font_faces[FONT_FACE_SANS_SERIF_ITALIC_BOLD] =
+ ft_new_face(option_atari_face_sans_serif_italic_bold,
+ "fonts/ssib.ttf",
+ DEJAVU_PATH"DejaVuSans-BoldOblique.ttf");
+
+ font_faces[FONT_FACE_MONOSPACE] =
+ ft_new_face(option_atari_face_monospace,
+ "fonts/mono.ttf",
+ DEJAVU_PATH"DejaVuSansMono.ttf");
+
+ font_faces[FONT_FACE_MONOSPACE_BOLD] =
+ ft_new_face(option_atari_face_monospace_bold,
+ "fonts/monob.ttf",
+ DEJAVU_PATH"DejaVuSansMono-Bold.ttf");
+
+ font_faces[FONT_FACE_SERIF] =
+ ft_new_face(option_atari_face_serif,
+ "fonts/s.ttf",
+ DEJAVU_PATH"DejaVuSerif.ttf");
+
+ font_faces[FONT_FACE_SERIF_BOLD] =
+ ft_new_face(option_atari_face_serif_bold,
+ "fonts/sb.ttf",
+ DEJAVU_PATH"DejaVuSerif-Bold.ttf");
+
+ font_faces[FONT_FACE_CURSIVE] =
+ ft_new_face(option_atari_face_cursive,
+ "fonts/cursive.ttf",
+ DEJAVU_PATH"DejaVuSansMono-Oblique.ttf");
+
+ font_faces[FONT_FACE_FANTASY] =
+ ft_new_face(option_atari_face_fantasy,
+ "fonts/fantasy.ttf",
+ DEJAVU_PATH"DejaVuSerifCondensed-Bold.ttf");
+
+ /* set the default render mode */
+ if (option_atari_font_monochrom == true)
+ ft_load_type = FT_LOAD_MONOCHROME;
+ else
+ ft_load_type = 0;
+
+ 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) {
+ /* string has exceeded available width 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_position( 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;
+
+ *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;
+ nxtchr = utf8_next(string, length, nxtchr);
+ }
+ *char_offset = nxtchr;
+ return ( 1 );
+}
+
+static void draw_glyph8(FONT_PLOTTER self, GRECT * loc, uint8_t * pixdata, int pitch, uint32_t colour)
+{
+ GRECT clip;
+ uint32_t * linebuf;
+ uint32_t fontpix;
+ size_t bmpstride;
+ 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;
+
+ clip.g_x = self->plotter->clipping.x0;
+ clip.g_y = self->plotter->clipping.y0;
+ clip.g_w = self->plotter->clipping.x1 - self->plotter->clipping.x0;
+ clip.g_h = self->plotter->clipping.y1 - self->plotter->clipping.y0;
+
+ if( !rc_intersect( &clip, loc ) ){
+ return;
+ }
+
+ assert( loc->g_w > 0 );
+ assert( loc->g_h > 0 );
+ 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;
+ fontbmp = bitmap_realloc( w, h,
+ fontbmp->bpp, w * fontbmp->bpp,
+ BITMAP_GROW, fontbmp );
+ assert( fontbmp );
+ assert( fontbmp->pixdata );
+ bmpstride = bitmap_get_rowstride(fontbmp);
+ for( yloop = 0; yloop < h; yloop++) {
+ linebuf = (uint32_t *)(fontbmp->pixdata + (bmpstride * yloop));
+ for(xloop = 0; xloop < w; xloop++){
+ fontpix = (uint32_t)(pixdata[(( yoff + yloop ) * pitch) + xloop + xoff]);
+ linebuf[xloop] = (uint32_t)(colour | fontpix);
+ }
+ }
+ self->plotter->bitmap( self->plotter, fontbmp, loc->g_x, loc->g_y, 0, 0);
+}
+
+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 ;
+ /* in -> BGR */
+ /* out -> ARGB */
+ c = ABGR_TO_RGB(c);
+
+ clip.g_x = self->plotter->clipping.x0;
+ clip.g_y = self->plotter->clipping.y0;
+ clip.g_w = self->plotter->clipping.x1 - self->plotter->clipping.x0;
+ clip.g_h = self->plotter->clipping.y1 - self->plotter->clipping.y0;
+ 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 (bglyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) {
+ assert( 1 == 0 );
+ } else {
+ if( loc.g_w > 0) {
+ draw_glyph8( self,
+ &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_position = pixel_position;
+ self->text = text;
+ LOG(("%s: %s\n", (char*)__FILE__, __FUNCTION__));
+ if( !init ) {
+ ft_font_init();
+ fontbmp = bitmap_create(48, 48, 0);
+ fontbmp->opaque = false;
+ init = true;
+ }
+
+ return( 1 );
+}
+
+static int dtor( FONT_PLOTTER self )
+{
+ ft_font_finalise();
+ if( fontbmp == NULL )
+ bitmap_destroy( fontbmp );
+ return( 1 );
+} \ No newline at end of file
diff --git a/atari/plot/font_freetype.h b/atari/plot/font_freetype.h
new file mode 100644
index 000000000..bca6d9956
--- /dev/null
+++ b/atari/plot/font_freetype.h
@@ -0,0 +1,51 @@
+/*
+ * 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 \ No newline at end of file
diff --git a/atari/plot/font_vdi.c b/atari/plot/font_vdi.c
new file mode 100644
index 000000000..04a94734e
--- /dev/null
+++ b/atari/plot/font_vdi.c
@@ -0,0 +1,216 @@
+/*
+ * 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 <stdbool.h>
+#include <stdio.h>
+#include <math.h>
+#include <assert.h>
+#include <string.h>
+#include <windom.h>
+
+#include "desktop/plot_style.h"
+#include "atari/bitmap.h"
+#include "atari/plot/plotter.h"
+#include "atari/plot/font_vdi.h"
+#include "utils/utf8.h"
+#include "utils/log.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_position( 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;
+int ctor_font_plotter_vdi( FONT_PLOTTER self )
+{
+ self->dtor = dtor;
+ self->str_width = str_width;
+ self->str_split = str_split;
+ self->pixel_position = pixel_position;
+ 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;
+ lstr = (char*)str;
+ utf8_to_enc(str, "ATARIST", length, &lstr );
+ assert( lstr != NULL );
+ int slen = strlen(lstr);
+
+ 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);
+ *width = slen * cellw;
+ free( (void*)lstr );
+ lstr = NULL;
+ 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;
+ int i;
+ lstr = (char*)string;
+ int slen = 0;
+ int last_space_x = 0;
+ int last_space_idx = 0;
+
+ utf8_to_enc(string, "ATARIST", length, &lstr );
+ assert( lstr != NULL );
+
+ slen = strlen(lstr);
+ 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;
+ int cpos=0;
+ 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 );
+ lstr = NULL;
+ return( 0 );
+}
+
+static int pixel_position( 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;
+
+ lstr = (char*)string;
+ int i=0;
+ int curpx=0;
+ utf8_to_enc(string, "ATRIST", length, &lstr );
+ assert( lstr != NULL );
+ int slen = strlen(lstr);
+ 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 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;
+ lstr = (char*)text;
+ utf8_to_enc(text, "ATARIST", length, &lstr );
+ assert( lstr != NULL );
+ int slen = strlen(lstr);
+ size_t mylen = MIN(511, slen );
+ char textcpy[mylen+1];
+
+ textcpy[mylen] = 0;
+ strncpy((char*)&textcpy, lstr, mylen+1 );
+ if( fstyle != NULL){
+ 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
+ pass it as arg, to reduce netsurf dependency */
+ pxsize = ceil( (fstyle->size/FONT_SIZE_SCALE) * 90 / 72 );
+ }
+ vst_effects( self->vdi_handle, fx );
+ vst_alignment(vdih, 0, 4, &cw, &ch );
+ vst_height( self->vdi_handle, pxsize ,&cw, &ch, &cellw, &cellh);
+ vswr_mode( self->vdi_handle, MD_TRANS );
+ vst_color( self->vdi_handle, RGB_TO_VDI(fstyle->foreground) );
+ x += CURFB(self->plotter).x;
+ y += CURFB(self->plotter).y;
+ v_ftext( self->vdi_handle, x, y, (char*)&textcpy );
+ free( lstr );
+ return( 0 );
+}
+
diff --git a/atari/plot/font_vdi.h b/atari/plot/font_vdi.h
new file mode 100644
index 000000000..e9f1894b4
--- /dev/null
+++ b/atari/plot/font_vdi.h
@@ -0,0 +1,23 @@
+/*
+ * 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_PLOTTER_VDI
+#define FONT_PLOTTER_VDI
+
+int ctor_font_plotter_vdi( FONT_PLOTTER self );
+
+#endif \ No newline at end of file
diff --git a/atari/plot/plotter.c b/atari/plot/plotter.c
new file mode 100644
index 000000000..d21b46540
--- /dev/null
+++ b/atari/plot/plotter.c
@@ -0,0 +1,723 @@
+/*
+ * 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 <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <windom.h>
+#include <assert.h>
+#include <mint/osbind.h>
+#include <mint/cookie.h>
+#include <Hermes/Hermes.h>
+
+#include "desktop/plot_style.h"
+#include "atari/bitmap.h"
+#include "image/bitmap.h"
+#include "atari/plot/eddi.h"
+#include "atari/plot/plotter.h"
+#include "atari/plot/plotter_vdi.h"
+#include "atari/plot/font_vdi.h"
+#include "atari/plot/font_freetype.h"
+#include "utils/log.h"
+
+
+unsigned char rgb_web_pal[216][3] = {
+ {0x00,0x00,0x00}, {0x33,0x00,0x00}, {0x66,0x00,0x00}, {0x99,0x00,0x00}, {0xcc,0x00,0x00}, {0xff,0x00,0x00},
+ {0x00,0x33,0x00}, {0x33,0x33,0x00}, {0x66,0x33,0x00}, {0x99,0x33,0x00}, {0xcc,0x33,0x00}, {0xff,0x33,0x00},
+ {0x00,0x66,0x00}, {0x33,0x66,0x00}, {0x66,0x66,0x00}, {0x99,0x66,0x00}, {0xcc,0x66,0x00}, {0xff,0x66,0x00},
+ {0x00,0x99,0x00}, {0x33,0x99,0x00}, {0x66,0x99,0x00}, {0x99,0x99,0x00}, {0xcc,0x99,0x00}, {0xff,0x99,0x00},
+ {0x00,0xcc,0x00}, {0x33,0xcc,0x00}, {0x66,0xcc,0x00}, {0x99,0xcc,0x00}, {0xcc,0xcc,0x00}, {0xff,0xcc,0x00},
+ {0x00,0xff,0x00}, {0x33,0xff,0x00}, {0x66,0xff,0x00}, {0x99,0xff,0x00}, {0xcc,0xff,0x00}, {0xff,0xff,0x00},
+ {0x00,0x00,0x33}, {0x33,0x00,0x33}, {0x66,0x00,0x33}, {0x99,0x00,0x33}, {0xcc,0x00,0x33}, {0xff,0x00,0x33},
+ {0x00,0x33,0x33}, {0x33,0x33,0x33}, {0x66,0x33,0x33}, {0x99,0x33,0x33}, {0xcc,0x33,0x33}, {0xff,0x33,0x33},
+ {0x00,0x66,0x33}, {0x33,0x66,0x33}, {0x66,0x66,0x33}, {0x99,0x66,0x33}, {0xcc,0x66,0x33}, {0xff,0x66,0x33},
+ {0x00,0x99,0x33}, {0x33,0x99,0x33}, {0x66,0x99,0x33}, {0x99,0x99,0x33}, {0xcc,0x99,0x33}, {0xff,0x99,0x33},
+ {0x00,0xcc,0x33}, {0x33,0xcc,0x33}, {0x66,0xcc,0x33}, {0x99,0xcc,0x33}, {0xcc,0xcc,0x33}, {0xff,0xcc,0x33},
+ {0x00,0xff,0x33}, {0x33,0xff,0x33}, {0x66,0xff,0x33}, {0x99,0xff,0x33}, {0xcc,0xff,0x33}, {0xff,0xff,0x33},
+ {0x00,0x00,0x66}, {0x33,0x00,0x66}, {0x66,0x00,0x66}, {0x99,0x00,0x66}, {0xcc,0x00,0x66}, {0xff,0x00,0x66},
+ {0x00,0x33,0x66}, {0x33,0x33,0x66}, {0x66,0x33,0x66}, {0x99,0x33,0x66}, {0xcc,0x33,0x66}, {0xff,0x33,0x66},
+ {0x00,0x66,0x66}, {0x33,0x66,0x66}, {0x66,0x66,0x66}, {0x99,0x66,0x66}, {0xcc,0x66,0x66}, {0xff,0x66,0x66},
+ {0x00,0x99,0x66}, {0x33,0x99,0x66}, {0x66,0x99,0x66}, {0x99,0x99,0x66}, {0xcc,0x99,0x66}, {0xff,0x99,0x66},
+ {0x00,0xcc,0x66}, {0x33,0xcc,0x66}, {0x66,0xcc,0x66}, {0x99,0xcc,0x66}, {0xcc,0xcc,0x66}, {0xff,0xcc,0x66},
+ {0x00,0xff,0x66}, {0x33,0xff,0x66}, {0x66,0xff,0x66}, {0x99,0xff,0x66}, {0xcc,0xff,0x66}, {0xff,0xff,0x66},
+ {0x00,0x00,0x99}, {0x33,0x00,0x99}, {0x66,0x00,0x99}, {0x99,0x00,0x99}, {0xcc,0x00,0x99}, {0xff,0x00,0x99},
+ {0x00,0x33,0x99}, {0x33,0x33,0x99}, {0x66,0x33,0x99}, {0x99,0x33,0x99}, {0xcc,0x33,0x99}, {0xff,0x33,0x99},
+ {0x00,0x66,0x99}, {0x33,0x66,0x99}, {0x66,0x66,0x99}, {0x99,0x66,0x99}, {0xcc,0x66,0x99}, {0xff,0x66,0x99},
+ {0x00,0x99,0x99}, {0x33,0x99,0x99}, {0x66,0x99,0x99}, {0x99,0x99,0x99}, {0xcc,0x99,0x99}, {0xff,0x99,0x99},
+ {0x00,0xcc,0x99}, {0x33,0xcc,0x99}, {0x66,0xcc,0x99}, {0x99,0xcc,0x99}, {0xcc,0xcc,0x99}, {0xff,0xcc,0x99},
+ {0x00,0xff,0x99}, {0x33,0xff,0x99}, {0x66,0xff,0x99}, {0x99,0xff,0x99}, {0xcc,0xff,0x99}, {0xff,0xff,0x99},
+ {0x00,0x00,0xcc}, {0x33,0x00,0xcc}, {0x66,0x00,0xcc}, {0x99,0x00,0xcc}, {0xcc,0x00,0xcc}, {0xff,0x00,0xcc},
+ {0x00,0x33,0xcc}, {0x33,0x33,0xcc}, {0x66,0x33,0xcc}, {0x99,0x33,0xcc}, {0xcc,0x33,0xcc}, {0xff,0x33,0xcc},
+ {0x00,0x66,0xcc}, {0x33,0x66,0xcc}, {0x66,0x66,0xcc}, {0x99,0x66,0xcc}, {0xcc,0x66,0xcc}, {0xff,0x66,0xcc},
+ {0x00,0x99,0xcc}, {0x33,0x99,0xcc}, {0x66,0x99,0xcc}, {0x99,0x99,0xcc}, {0xcc,0x99,0xcc}, {0xff,0x99,0xcc},
+ {0x00,0xcc,0xcc}, {0x33,0xcc,0xcc}, {0x66,0xcc,0xcc}, {0x99,0xcc,0xcc}, {0xcc,0xcc,0xcc}, {0xff,0xcc,0xcc},
+ {0x00,0xff,0xcc}, {0x33,0xff,0xcc}, {0x66,0xff,0xcc}, {0x99,0xff,0xcc}, {0xcc,0xff,0xcc}, {0xff,0xff,0xcc},
+ {0x00,0x00,0xff}, {0x33,0x00,0xff}, {0x66,0x00,0xff}, {0x99,0x00,0xff}, {0xcc,0x00,0xff}, {0xff,0x00,0xff},
+ {0x00,0x33,0xff}, {0x33,0x33,0xff}, {0x66,0x33,0xff}, {0x99,0x33,0xff}, {0xcc,0x33,0xff}, {0xff,0x33,0xff},
+ {0x00,0x66,0xff}, {0x33,0x66,0xff}, {0x66,0x66,0xff}, {0x99,0x66,0xff}, {0xcc,0x66,0xff}, {0xff,0x66,0xff},
+ {0x00,0x99,0xff}, {0x33,0x99,0xff}, {0x66,0x99,0xff}, {0x99,0x99,0xff}, {0xcc,0x99,0xff}, {0xff,0x99,0xff},
+ {0x00,0xcc,0xff}, {0x33,0xcc,0xff}, {0x66,0xcc,0xff}, {0x99,0xcc,0xff}, {0xcc,0xcc,0xff}, {0xff,0xcc,0xff},
+ {0x00,0xff,0xff}, {0x33,0xff,0xff}, {0x66,0xff,0xff}, {0x99,0xff,0xff}, {0xcc,0xff,0xff}, {0xff,0xff,0xff}
+};
+
+
+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}
+};
+
+static short prev_vdi_clip[4];
+struct s_vdi_sysinfo vdi_sysinfo;
+
+struct s_driver_table_entry screen_driver_table[] =
+{
+ {(char*)"vdi", ctor_plotter_vdi, 0, 32},
+ {(char*)"screen.ldg", ctor_plotter_vdi, PLOT_FLAG_OFFSCREEN, 32 },
+ {(char*)"vdi_offscreen", ctor_plotter_vdi, PLOT_FLAG_OFFSCREEN, 32},
+ {(char*)NULL, NULL, 0, 0 }
+};
+
+const struct s_font_driver_table_entry font_driver_table[] =
+{
+ {(char*)"vdi", ctor_font_plotter_vdi, 0},
+ {(char*)"freetype", ctor_font_plotter_freetype, 0},
+ {(char*)NULL, NULL, 0}
+};
+
+struct s_vdi_sysinfo * read_vdi_sysinfo( short vdih, struct s_vdi_sysinfo * info ) {
+
+ unsigned long cookie_EdDI=0;
+ short out[300];
+ memset( info, 0, sizeof(struct s_vdi_sysinfo) );
+
+ info->vdi_handle = vdih;
+ if ( Getcookie(C_EdDI, &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=0;
+ 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:
+ {
+
+ int i;
+ unsigned short *tmp_p;
+/* it's possible to store the vdi painters:
+ tmp_p = (unsigned short *)&work_out[16];
+
+ for (i=0;i<256;i++) {
+ vdi_index[*tmp_p++] = i;
+ }
+*/
+ }
+ 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;
+ }
+ }
+}
+
+
+/*
+ lookup an plotter ID by name
+*/
+static int drvrname_idx( char * name )
+{
+ int i;
+ for( i = 0; ; i++) {
+ if( screen_driver_table[i].name == NULL ) {
+ return( -1 );
+ }
+ else {
+ if( strcmp(name, screen_driver_table[i].name) == 0 ) {
+ return( i );
+ }
+ }
+ }
+}
+
+/*
+ lookup of font plotter ID by name
+*/
+static int font_drvrname_idx( char * name )
+{
+ int i;
+ for( i = 0; ; i++) {
+ if( font_driver_table[i].name == NULL ) {
+ return( -1 );
+ }
+ else {
+ if( strcmp(name, font_driver_table[i].name) == 0 ) {
+ return( i );
+ }
+ }
+ }
+}
+
+/*
+ Get an plotter info entry, the entry contains an pointer to ctor
+*/
+struct s_driver_table_entry * get_screen_driver_entry( char * name )
+{
+ int idx = drvrname_idx( name );
+ if( idx < 0 )
+ return( 0 );
+ else
+ return( &screen_driver_table[idx] );
+}
+
+/*
+ Get an font plotter info entry, the entry contains an pointer to ctor.
+*/
+struct s_font_driver_table_entry * get_font_driver_entry( char * name )
+{
+ int idx = font_drvrname_idx( name );
+ if( idx < 0 )
+ return( 0 );
+ else
+ return( (struct s_font_driver_table_entry *)&font_driver_table[idx] );
+}
+
+
+/*
+ Create an new text plotter object
+*/
+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 = (FONT_PLOTTER)malloc( sizeof(struct s_font_plotter) );
+ if( fplotter == NULL ) {
+ *error = 0-ERR_NO_MEM;
+ return( NULL );
+ }
+ fplotter->vdi_handle = vdihandle;
+ fplotter->name = name;
+ fplotter->flags |= flags;
+ for( i = 0; ; i++) {
+ if( font_driver_table[i].name == NULL ) {
+ res = 0-ERR_PLOTTER_NOT_AVAILABLE;
+ break;
+ } else {
+ if( strcmp(name, font_driver_table[i].name) == 0 ) {
+ if( font_driver_table[i].ctor ) {
+ res = font_driver_table[i].ctor( fplotter );
+ *error = 0;
+ } else {
+ res = 0-ERR_PLOTTER_NOT_AVAILABLE;
+ *error = res;
+ return (NULL);
+ }
+ break;
+ }
+ }
+ }
+ if( res < 0 ) {
+ free( fplotter );
+ *error = res;
+ return( NULL );
+ }
+ fplotter->plotter = NULL;
+ return( fplotter );
+}
+
+static bool init=false;
+static int inst=0;
+
+/*
+ Create an new plotter object
+*/
+GEM_PLOTTER new_plotter(int vdihandle, char * name, GRECT * loc_size,
+ int virt_bpp, unsigned long flags, FONT_PLOTTER fplotter, int * error )
+{
+ int res = 0-ERR_PLOTTER_NOT_AVAILABLE;
+ int i;
+ assert( fplotter != NULL );
+
+ GEM_PLOTTER gemplotter = (GEM_PLOTTER)malloc( sizeof(struct s_gem_plotter) );
+ if( !gemplotter ) {
+ *error = 0-ERR_NO_MEM;
+ return( NULL );
+ }
+ memset( gemplotter, 0, sizeof(struct s_gem_plotter));
+
+ gemplotter->name = name;
+ gemplotter->vdi_handle = vdihandle;
+ gemplotter->flags |= flags;
+ gemplotter->font_plotter = fplotter;
+ gemplotter->bpp_virt = virt_bpp;
+ gemplotter->cfbi = 0;
+ memset(&gemplotter->fbuf, 0, sizeof(struct s_frame_buf) * MAX_FRAMEBUFS );
+ gemplotter->fbuf[0].x = loc_size->g_x;
+ gemplotter->fbuf[0].y = loc_size->g_y;
+ gemplotter->fbuf[0].w = loc_size->g_w;
+ gemplotter->fbuf[0].h = loc_size->g_h;
+
+ /* request vdi info once, so every plotter is able to access the info */
+ if( !init ) {
+ /* vdi_sysinfo */
+ read_vdi_sysinfo( vdihandle, &vdi_sysinfo );
+ init = true;
+ }
+ for( i = 0; ; i++) {
+ if( screen_driver_table[i].name == NULL ) {
+ res = 0-ERR_PLOTTER_NOT_AVAILABLE;
+ break;
+ }
+ else {
+ if( strcmp(name, screen_driver_table[i].name) == 0 ) {
+ if( screen_driver_table[i].ctor ) {
+ gemplotter->flags |= screen_driver_table[i].flags;
+ res = screen_driver_table[i].ctor( gemplotter );
+ *error = 0;
+ } else {
+ res = 0-ERR_PLOTTER_NOT_AVAILABLE;
+ *error = res;
+ return (NULL);
+ }
+ break;
+ }
+ }
+ }
+ if( res < 0 ) {
+ free( gemplotter );
+ *error = res;
+ return( NULL );
+ }
+ inst++;
+ gemplotter->font_plotter->plotter = gemplotter;
+ return( gemplotter );
+}
+
+/*
+ Free an plotter
+*/
+int delete_plotter( GEM_PLOTTER p )
+{
+ if( p ) {
+ p->dtor( p );
+ free( p );
+ p = NULL;
+ inst--;
+ if( inst == 0 ){
+
+ }
+ }
+ else
+ return( -1 );
+ return( 0 );
+}
+
+/*
+ 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 );
+}
+
+/*
+ x - x coord
+ y - y coord
+ stride - stride in bytes
+ bpp - bits per pixel
+*/
+int calc_chunked_buffer_size(int x, int y, int stride, int bpp)
+{
+ return( (x * (bpp >> 3)) * y );
+}
+
+/*
+ x - x coord
+ y - y coord
+ stride - stride in bytes
+ bpp - bits per pixel
+*/
+int get_pixel_offset( int x, int y, int stride, int bpp )
+{
+ LOG(("byte_pp: %d, pure: %d, result: %d\n",(bpp >> 3),(y * stride + x), (y * stride + x) * (bpp >> 3)));
+ return( ( (y * stride) + x) * (bpp >> 3) );
+}
+
+/*
+ 1. calculate visible area of framebuffer in coords relative to framebuffer position
+
+ result:
+ this function should calc offsets into x,y coords of the framebuffer which
+ can be drawn. If the framebuffer coords do not fall within the screen region,
+ all values of visible region are set to zero.
+*/
+void update_visible_rect( GEM_PLOTTER p )
+{
+ GRECT screen;
+ GRECT common;
+ GRECT frame;
+
+ 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 = CURFB(p).x;
+ common.g_y = frame.g_y = CURFB(p).y;
+ common.g_w = frame.g_w = CURFB(p).w;
+ common.g_h = frame.g_h = CURFB(p).h;
+
+ if( rc_intersect( &screen, &common ) ) {
+ CURFB(p).vis_w = common.g_w;
+ CURFB(p).vis_h = common.g_h;
+ if( CURFB(p).x < screen.g_x )
+ CURFB(p).vis_x = frame.g_w - common.g_w;
+ else
+ CURFB(p).vis_x = 0;
+ if( CURFB(p).y <screen.g_y )
+ CURFB(p).vis_y = frame.g_h - common.g_h;
+ else
+ CURFB(p).vis_y = 0;
+ } else {
+ CURFB(p).vis_w = CURFB(p).vis_h = 0;
+ CURFB(p).vis_x = CURFB(p).vis_y = 0;
+ }
+}
+
+/*
+ Returns the visible parts of the box (relative coords within framebuffer),
+ relative to screen coords (normally starting at 0,0 )
+*/
+bool fbrect_to_screen( GEM_PLOTTER self, 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 = CURFB(self).x;
+ vis.g_y = CURFB(self).y;
+ vis.g_w = CURFB(self).w;
+ vis.g_h = CURFB(self).h;
+
+ if ( !rc_intersect( &screen, &vis ) ) {
+ return( false );
+ }
+ vis.g_x = CURFB(self).w - vis.g_w;
+ vis.g_y = CURFB(self).h - vis.g_h;
+
+ /* clip box to visible region: */
+ if( !rc_intersect(&vis, &box) ) {
+ return( false );
+ }
+ out.g_x = box.g_x + CURFB(self).x;
+ out.g_y = box.g_y + CURFB(self).y;
+ out.g_w = box.g_w;
+ out.g_h = box.g_h;
+ *ret = out;
+ return ( true );
+}
+
+const char* plotter_err_str(int i) { return(plot_error_codes[abs(i)]); }
+
+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: %d\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: %d\n", temp.screensize);
+ printf(" unsigned long mask_r: 0x0%08x\n", temp.mask_r);
+ printf(" unsigned long mask_g: 0x0%08x\n", temp.mask_g);
+ printf(" unsigned long mask_b: 0x0%08x\n", temp.mask_b);
+ printf(" unsigned long mask_a: 0x0%08x\n", temp.mask_a);
+ printf(" short maxintin: %d\n", temp.maxintin);
+ printf(" short maxpolycoords: %d\n", temp.maxpolycoords);
+ printf(" unsigned long EdDiVersion: 0x0%03x\n", temp.EdDiVersion);
+ printf(" unsigned short rasterscale: 0x%2x\n", temp.rasterscale);
+ printf("};\n");
+}
+
+void dump_plot_drivers(void)
+{
+ int i = 0;
+ while( screen_driver_table[i].name != NULL ) {
+ printf("%s -> max_bpp: %d, flags: %d\n",
+ screen_driver_table[i].name,
+ screen_driver_table[i].max_bpp,
+ screen_driver_table[i].flags
+ );
+ i++;
+ }
+}
+
+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++;
+ }
+}
+
+/*
+ Convert an RGB color to an VDI Color
+*/
+void rgb_to_vdi1000( unsigned char * in, unsigned short * out )
+{
+
+ double r = ((double)in[0]/255); /* prozentsatz red */
+ double g = ((double)in[1]/255); /* prozentsatz green */
+ double b = ((double)in[2]/255); /* prozentsatz blue */
+ out[0] = 1000 * r + 0.5;
+ out[1] = 1000 * g + 0.5;
+ out[2] = 1000 * b + 0.5;
+ return;
+}
+
+
+
+static short web_std_colors[6] = {0, 51, 102, 153, 204, 255};
+
+/*
+ Convert an RGB color into an index into the 216 colors web pallette
+*/
+short rgb_to_666_index(unsigned char r, unsigned char g, unsigned char b)
+{
+ short ret = 0;
+ short i;
+ unsigned char rgb[3] = {r,g,b};
+ unsigned char tval[3];
+ /* 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] );
+}
+
+/* Shared (static in object oriented slang) plotter functions: */
+int plotter_get_clip( GEM_PLOTTER self, struct s_clipping * out )
+{
+ out->x0 = self->clipping.x0;
+ out->y0 = self->clipping.y0;
+ out->x1 = self->clipping.x1;
+ out->y1 = self->clipping.y1;
+ return( 1 );
+}
+
+int plotter_std_clip(GEM_PLOTTER self,int x0, int y0, int x1, int y1)
+{
+ self->clipping.x0 = x0;
+ self->clipping.y0 = y0;
+ self->clipping.x1 = x1;
+ self->clipping.y1 = y1;
+ return ( 1 );
+}
+
+/* this converts framebuffer clipping to vdi clipping and sets it */
+void plotter_vdi_clip( GEM_PLOTTER self, bool set)
+{
+ return;
+ if( set == true ) {
+ struct s_clipping * c = &self->clipping;
+ short vdiflags[58];
+ short newclip[4];
+ vq_extnd( self->vdi_handle, 1, (short*)&vdiflags);
+ prev_vdi_clip[0] = vdiflags[45];
+ prev_vdi_clip[1] = vdiflags[46];
+ prev_vdi_clip[2] = vdiflags[47];
+ prev_vdi_clip[3] = vdiflags[48];
+ newclip[0] = CURFB(self).x + MAX(c->x0, 0);
+ newclip[1] = CURFB(self).y + MAX(c->y0, 0);
+ newclip[2] = CURFB(self).x + MIN(CURFB(self).vis_w, c->x1 - c->x0)-1;
+ newclip[3] = CURFB(self).y + MIN(CURFB(self).vis_h, c->y1 - c->y0)-1;
+ vs_clip( self->vdi_handle, 1, (short*)&newclip );
+ } else {
+ short set = 1;
+ vs_clip( self->vdi_handle, set, (short *)&prev_vdi_clip );
+ }
+}
+
diff --git a/atari/plot/plotter.h b/atari/plot/plotter.h
new file mode 100644
index 000000000..973b70058
--- /dev/null
+++ b/atari/plot/plotter.h
@@ -0,0 +1,293 @@
+/*
+ * 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 _GEM_PLOTTER_API_H_
+#define _GEM_PLOTTER_API_H_
+#include <windom.h>
+
+
+
+#ifndef ceilf
+#define ceilf(x) (float)ceil((double)x)
+#endif
+
+#ifdef TEST_PLOTTER
+#define verbose_log 1
+#define LOG(x) do { if (verbose_log) (printf(__FILE__ " %s %i: ", __PRETTY_FUNCTION__, __LINE__), printf x, fputc('\n', stdout)); } while (0)
+#endif
+
+#define MAX_FRAMEBUFS 0x010
+#define C2P (1<<0) /* C2P convert buffer 1 to buffer 2 */
+/* TODO: implement offscreen buffer switch */
+/* Plotter Flags: */
+#define PLOT_FLAG_OFFSCREEN 0x01
+#define PLOT_FLAG_LOCKED 0x02
+#define PLOT_FLAG_DITHER 0x04
+#define PLOT_FLAG_TRANS 0x08
+
+/* Error codes: */
+#define ERR_BUFFERSIZE_EXCEEDS_SCREEN 1
+#define ERR_NO_MEM 2
+#define ERR_PLOTTER_NOT_AVAILABLE 3
+
+static const char * plot_error_codes[] =
+{
+ "None",
+ "ERR_BUFFERSIZE_EXCEEDS_SCREEN",
+ "ERR_NO_MEM",
+ "ERR_PLOTTER_NOT_AVAILABLE"
+};
+
+/* Grapics & Font Plotter Objects: */
+typedef struct s_font_plotter * FONT_PLOTTER;
+typedef struct s_gem_plotter * GEM_PLOTTER;
+typedef struct s_font_plotter * GEM_FONT_PLOTTER; /* for public use ... */
+struct s_font_plotter
+{
+ char * name;
+ int flags;
+ int vdi_handle;
+ void * priv_data;
+ GEM_PLOTTER plotter;
+
+ bool (*str_width)(FONT_PLOTTER self, const plot_font_style_t *fstyle,
+ const char * str, size_t length, int * width);
+ bool (*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);
+ bool (*pixel_position)(FONT_PLOTTER self, const plot_font_style_t *fstyle,
+ const char *string, size_t length,
+ int x, size_t *char_offset, int *actual_x);
+ void (*text)(FONT_PLOTTER self, int x, int y, const char *text, size_t length, const plot_font_style_t *fstyle);
+ void (*dtor)(FONT_PLOTTER self );
+};
+
+
+struct s_clipping {
+ short x0;
+ short y0;
+ short x1;
+ short y1;
+};
+
+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; /* color masks */
+ unsigned long mask_g;
+ unsigned long mask_b;
+ unsigned long mask_a;
+ 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 s_frame_buf
+{
+ short x;
+ short y;
+ short w;
+ short h;
+ short vis_x; /* visible rectangle of the screen buffer */
+ short vis_y; /* coords are relative to framebuffer location */
+ short vis_w;
+ short vis_h;
+ int size;
+ bool swapped;
+ void * mem;
+};
+
+
+struct s_gem_plotter
+{
+ char * name; /* name that identifies the Plotter */
+ unsigned long flags;
+ int vdi_handle;
+ struct s_vdi_sysinfo * scr;
+ void * priv_data;
+ int bpp_virt; /* bit depth of framebuffer */
+ struct s_clipping clipping;
+ struct s_frame_buf fbuf[MAX_FRAMEBUFS];
+ int cfbi; /* current framebuffer index */
+
+ FONT_PLOTTER font_plotter;
+ int (*dtor)(GEM_PLOTTER self);
+ int (*resize)(GEM_PLOTTER self, int w, int h);
+ int (*move)(GEM_PLOTTER self, short x, short y );
+ void * (*lock)(GEM_PLOTTER self);
+ void * (*create_framebuffer)(GEM_PLOTTER self);
+ void * (*switch_to_framebuffer)(GEM_PLOTTER self);
+ int (*unlock)(GEM_PLOTTER self);
+ int (*update_region)(GEM_PLOTTER self, GRECT region);
+ int (*update_screen_region)( GEM_PLOTTER self, GRECT region );
+ int (*update_screen)(GEM_PLOTTER self);
+ int (*put_pixel)(GEM_PLOTTER self, int x, int y, int color );
+ int (*copy_rect)(GEM_PLOTTER self, GRECT src, GRECT dst );
+ int (*clip)(GEM_PLOTTER self, int x0, int y0, int x1, int y1);
+ int (*arc)(GEM_PLOTTER self, int x, int y, int radius, int angle1, int angle2, const plot_style_t * pstyle);
+ int (*disc)(GEM_PLOTTER self, int x, int y, int radius, const plot_style_t * pstyle);
+ int (*line)(GEM_PLOTTER self, int x0, int y0, int x1, int y1, const plot_style_t * pstyle);
+ int (*rectangle)(GEM_PLOTTER self, int x0, int y0, int x1, int y1, const plot_style_t * pstyle);
+ int (*polygon)(GEM_PLOTTER self, const int *p, unsigned int n, const plot_style_t * pstyle);
+ int (*path)(GEM_PLOTTER self, const float *p, unsigned int n, int fill, float width, int c, const float transform[6]);
+ int (*bitmap_resize) ( GEM_PLOTTER self, struct bitmap * bm, int nw, int nh );
+ int (*bitmap)(GEM_PLOTTER self, struct bitmap * bmp, int x, int y,
+ unsigned long bg, unsigned long flags );
+ int (*text)(GEM_PLOTTER self, int x, int y, const char *text, size_t length, const plot_font_style_t *fstyle);
+};
+
+
+struct s_driver_table_entry
+{
+ char * name;
+ int (*ctor)( GEM_PLOTTER self );
+ int flags;
+ int max_bpp;
+};
+
+struct s_font_driver_table_entry
+{
+ char * name;
+ int (*ctor)( FONT_PLOTTER self );
+ int flags;
+};
+
+typedef struct s_driver_table_entry * PLOTTER_INFO;
+typedef struct s_font_driver_table_entry * FONT_PLOTTER_INFO;
+
+/* get index to driver in driver list by name */
+static int drvrname_idx( char * name );
+
+/* get s_driver_table_entry from driver table */
+struct s_driver_table_entry * get_screen_driver_entry(char * name);
+
+/* get s_font_driver_table_entry from driver table */
+struct s_font_driver_table_entry * get_font_driver_entry(char * name);
+
+/* fill screen / sys info */
+struct s_vdi_sysinfo * read_vdi_sysinfo(short vdih, struct s_vdi_sysinfo * info );
+
+/*
+ Create an new plotter object
+ Error Values:
+ -1 no mem
+ -2 error configuring plotter
+ -3 Plotter not available
+*/
+GEM_PLOTTER new_plotter(int vdihandle, char * name,
+ GRECT *, int virt_bpp, unsigned long flags, FONT_PLOTTER font_renderer,
+ int * error);
+
+/*
+ Create an new font plotter object
+ Error Values:
+ -1 no mem
+ -2 error configuring font plotter
+ -3 Font Plotter not available
+*/
+FONT_PLOTTER new_font_plotter(int vdihandle, char * name, unsigned long flags, int * error );
+
+/* free the plotter resources */
+int delete_plotter( GEM_PLOTTER p );
+int delete_font_plotter( FONT_PLOTTER p );
+
+
+/* calculate size of intermediate buffer */
+int calc_chunked_buffer_size(int x, int y, int stride, int bpp);
+
+/* calculates the pixel offset from x,y pos */
+int get_pixel_offset( int x, int y, int stride, int bpp );
+
+/* Recalculate visible parts of the framebuffer */
+void update_visible_rect( GEM_PLOTTER p );
+
+/* resolve possible visible parts of the framebuffer in screen coords */
+bool fbrect_to_screen( GEM_PLOTTER self, GRECT box, GRECT * ret );
+
+/* translate an error number */
+const char* plotter_err_str(int i) ;
+
+void dump_font_drivers(void);
+void dump_plot_drivers(void);
+void dump_vdi_info(short);
+
+/* convert an rgb color to vdi1000 color */
+void rgb_to_vdi1000( unsigned char * in, unsigned short * 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);
+
+/* shared / static methods ... */
+int plotter_get_clip( GEM_PLOTTER self, struct s_clipping * out );
+int plotter_std_clip(GEM_PLOTTER self,int x0, int y0, int x1, int y1);
+void plotter_vdi_clip( GEM_PLOTTER self, bool set);
+
+#define PLOTTER_IS_LOCKED(plotter) ( plotter->private_flags & PLOTTER_FLAG_LOCKED )
+#define FILL_PLOTTER_VTAB( p ) \
+ p->dtor = dtor;\
+ p->resize= resize;\
+ p->move = move;\
+ p->lock = lock;\
+ p->unlock = unlock;\
+ p->update_region = update_region;\
+ p->update_screen_region = update_screen_region;\
+ p->update_screen = update_screen;\
+ p->put_pixel = put_pixel;\
+ p->copy_rect = copy_rect; \
+ p->clip = clip;\
+ p->arc = arc;\
+ p->disc = disc;\
+ p->line = line;\
+ p->rectangle = rectangle;\
+ p->polygon = polygon;\
+ p->path = path;\
+ p->bitmap = bitmap;\
+ p->text = text;\
+
+
+#define FILL_FONT_PLOTTER_VTAB( p ) \
+ p->dtor = dtor;\
+ p->str_width = str_width;\
+ p->str_split = str_split;\
+ p->pixel_position = pixel_position;\
+ p->text = text;\
+
+#define CURFB( p ) \
+ p->fbuf[p->cfbi]
+
+#define FIRSTFB( p ) \
+ p->fbuf[0]
+
+#define OFFSET_WEB_PAL 16
+#define OFFSET_FONT_PAL 232
+#define RGB_TO_VDI(c) rgb_to_666_index( (c&0xFF),(c&0xFF00)>>8,(c&0xFF0000)>>16)+OFFSET_WEB_PAL
+#define ABGR_TO_RGB(c) ( ((c&0xFF)<<16) | (c&0xFF00) | ((c&0xFF0000)>>16) ) << 8
+
+#endif
diff --git a/atari/plot/plotter_vdi.c b/atari/plot/plotter_vdi.c
new file mode 100644
index 000000000..e825d92d3
--- /dev/null
+++ b/atari/plot/plotter_vdi.c
@@ -0,0 +1,998 @@
+/*
+ * 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 <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <assert.h>
+#include <windom.h>
+#include <Hermes/Hermes.h>
+
+#include "desktop/plot_style.h"
+#include "image/bitmap.h"
+#include "atari/bitmap.h"
+#include "atari/plot/eddi.h"
+#include "atari/plot/plotter.h"
+#include "atari/plot/plotter_vdi.h"
+#include "atari/plot/font_vdi.h"
+#include "atari/bitmap.h"
+#include "utils/log.h"
+
+/* assign vdi line style to dst ( netsurf type ) */
+#define NSLT2VDI(dst, src) \
+ switch( src->stroke_type ) {\
+ case PLOT_OP_TYPE_DOT: \
+ dst = 3; \
+ break;\
+ case PLOT_OP_TYPE_DASH:\
+ dst = 4; \
+ break;\
+ case PLOT_OP_TYPE_SOLID:\
+ case PLOT_OP_TYPE_NONE:\
+ default:\
+ dst = 1;\
+ break;\
+ }\
+
+static int dtor( GEM_PLOTTER self );
+static int resize( GEM_PLOTTER self, int w, int h );
+static int move( GEM_PLOTTER self, short x, short y );
+static void * lock( GEM_PLOTTER self );
+static int unlock( GEM_PLOTTER self );
+static int update_region( GEM_PLOTTER self, GRECT region );
+static int update_screen_region( GEM_PLOTTER self, GRECT region );
+static int update_screen( GEM_PLOTTER self );
+static int put_pixel(GEM_PLOTTER self, int x, int y, int color );
+static int copy_rect( GEM_PLOTTER self, GRECT src, GRECT dst );
+static int arc(GEM_PLOTTER self,int x, int y, int radius, int angle1, int angle2, const plot_style_t * pstyle);
+static int disc(GEM_PLOTTER self,int x, int y, int radius, const plot_style_t * pstyle);
+static int line(GEM_PLOTTER self,int x0, int y0, int x1, int y1, const plot_style_t * pstyle);
+static int rectangle(GEM_PLOTTER self,int x0, int y0, int x1, int y1, const plot_style_t * pstyle);
+static int polygon(GEM_PLOTTER self,const int *p, unsigned int n, const plot_style_t * pstyle);
+static int path(GEM_PLOTTER self,const float *p, unsigned int n, int fill, float width, int c, const float transform[6]);
+static int bitmap_resize( GEM_PLOTTER self, struct bitmap * img, int nw, int nh );
+static int bitmap( GEM_PLOTTER self, struct bitmap * bmp, int x, int y,
+ unsigned long bg, unsigned long flags );
+static int text(GEM_PLOTTER self, int x, int y, const char *text,size_t length, const plot_font_style_t *fstyle);
+
+static unsigned short sys_pal[256][3]; /*RGB*/
+static unsigned short pal[256][3]; /*RGB*/
+
+extern unsigned char rgb_web_pal[126][3];
+extern unsigned short vdi_web_pal[126][3];
+extern struct s_vdi_sysinfo vdi_sysinfo;
+
+static HermesHandle hermes_pal_h; /* hermes palette handle */
+static HermesHandle hermes_cnv_h; /* hermes converter instance handle */
+static HermesHandle hermes_res_h;
+int32 * hermes_pal_p;
+
+int ctor_plotter_vdi(GEM_PLOTTER self )
+{
+ int retval = 0;
+ int i;
+ self->dtor = dtor;
+ self->resize= resize;
+ self->move = move;
+ self->lock = lock;
+ self->unlock = unlock;
+ self->update_region = update_region;
+ self->update_screen_region = update_screen_region;
+ self->update_screen = update_screen;
+ self->put_pixel = put_pixel;
+ self->copy_rect = copy_rect;
+ self->clip = plotter_std_clip;
+ self->arc = arc;
+ self->disc = disc;
+ self->line = line;
+ self->rectangle = rectangle;
+ self->polygon = polygon;
+ self->path = path;
+ self->bitmap = bitmap;
+ self->bitmap_resize = bitmap_resize;
+ self->text = text;
+ LOG(("Screen: x: %d, y: %d\n", vdi_sysinfo.scr_w, vdi_sysinfo.scr_h));
+
+ self->priv_data = malloc( sizeof(struct s_vdi_priv_data) );
+ if( self->priv_data == NULL )
+ return( 0-ERR_NO_MEM );
+ memset( self->priv_data, 0, sizeof(struct s_vdi_priv_data) );
+ DUMMY_PRIV(self)->bufops = 0;
+ DUMMY_PRIV(self)->size_buf_packed = 0;
+ DUMMY_PRIV(self)->size_buf_planar = 0;
+ DUMMY_PRIV(self)->buf_packed = NULL;
+ DUMMY_PRIV(self)->buf_planar = NULL;
+ if( vdi_sysinfo.vdiformat == VDI_FORMAT_PACK ) {
+ self->bpp_virt = vdi_sysinfo.scr_bpp;
+ } else {
+ DUMMY_PRIV(self)->bufops = C2P;
+ self->bpp_virt = 8;
+ }
+ if( FIRSTFB(self).w > vdi_sysinfo.scr_w || FIRSTFB(self).h > vdi_sysinfo.scr_h )
+ return( 0-ERR_BUFFERSIZE_EXCEEDS_SCREEN );
+
+ FIRSTFB(self).size = calc_chunked_buffer_size( FIRSTFB(self).w, FIRSTFB(self).h, FIRSTFB(self).w, self->bpp_virt );
+ /* offscreen: FIRSTFB(self).mem = malloc( FIRSTFB(self).size ); */
+ FIRSTFB(self).mem = NULL;
+ update_visible_rect( self );
+ self->clip( self, 0, 0, FIRSTFB(self).w, FIRSTFB(self).h );
+ /* store system palette & setup the new (web) palette: */
+ i = 0;
+ for( i=0; i<=255; i++ ) {
+ vq_color(self->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 ( i < OFFSET_FONT_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];
+ }
+ if( i >= OFFSET_FONT_PAL ) {
+ /* here we could define some additional colors... */
+ /* rgb_to_vdi1000( &rgb_font_pal[i-OFFSET_FONT_PAL], &pal[i] ); */
+ }
+ vs_color( self->vdi_handle, i, &pal[i][0] );
+ }
+ }
+
+ unsigned char * col;
+ assert( Hermes_Init() );
+ hermes_pal_h = Hermes_PaletteInstance();
+ hermes_pal_p = Hermes_PaletteGet(hermes_pal_h);
+ assert(hermes_pal_p);
+
+ for( i = 0; i<OFFSET_FONT_PAL; i++) {
+ col = (unsigned char *)(hermes_pal_p+i);
+ if( i < OFFSET_WEB_PAL ) {
+ col[0] = sys_pal[i][0];
+ col[1] = sys_pal[i][1];
+ col[2] = sys_pal[i][2];
+ }
+ if( i >= OFFSET_WEB_PAL ) {
+ col[0] = rgb_web_pal[i-OFFSET_WEB_PAL][0];
+ col[1] = rgb_web_pal[i-OFFSET_WEB_PAL][1];
+ col[2] = rgb_web_pal[i-OFFSET_WEB_PAL][2];
+ }
+ /* font colors missing */
+ col[3] = 0;
+ }
+ Hermes_PaletteInvalidateCache(hermes_pal_h);
+
+ unsigned long flags = ( self->flags & PLOT_FLAG_DITHER ) ? HERMES_CONVERT_DITHER : 0;
+ hermes_cnv_h = Hermes_ConverterInstance( flags );
+ assert( hermes_cnv_h );
+ hermes_res_h = Hermes_ConverterInstance( flags );
+ assert( hermes_res_h );
+
+ /* set up the src & dst format: */
+ /* netsurf uses RGBA ... */
+ DUMMY_PRIV(self)->nsfmt.a = 0xFFUL;
+ DUMMY_PRIV(self)->nsfmt.b = 0x0FF00UL;
+ DUMMY_PRIV(self)->nsfmt.g = 0x0FF0000UL;
+ DUMMY_PRIV(self)->nsfmt.r = 0x0FF000000UL;
+ DUMMY_PRIV(self)->nsfmt.bits = 32;
+ DUMMY_PRIV(self)->nsfmt.indexed = false;
+ DUMMY_PRIV(self)->nsfmt.has_colorkey = false;
+
+ DUMMY_PRIV(self)->vfmt.r = vdi_sysinfo.mask_r;
+ DUMMY_PRIV(self)->vfmt.g = vdi_sysinfo.mask_g;
+ DUMMY_PRIV(self)->vfmt.b = vdi_sysinfo.mask_b;
+ DUMMY_PRIV(self)->vfmt.a = vdi_sysinfo.mask_a;
+ DUMMY_PRIV(self)->vfmt.bits = self->bpp_virt;
+ DUMMY_PRIV(self)->vfmt.indexed = false;
+ DUMMY_PRIV(self)->vfmt.has_colorkey = false;
+
+ return( 1 );
+}
+
+static int dtor( GEM_PLOTTER self )
+{
+ int i=0;
+ LOG(("%s: %s\n", (char*)__FILE__, __FUNCTION__));
+ for( i=0; i<MAX_FRAMEBUFS; i++) {
+ if( self->fbuf[i].mem != NULL )
+ free( self->fbuf[i].mem );
+ }
+
+ /* restore system palette */
+ for( i=0; i<=255; i++ ) {
+ vs_color( self->vdi_handle, i, &sys_pal[i][0] );
+ }
+
+ /* close Hermes stuff: */
+ Hermes_ConverterReturn( hermes_cnv_h );
+ Hermes_PaletteReturn( hermes_pal_h );
+ Hermes_Done();
+
+ if( self->priv_data != NULL ){
+ if( DUMMY_PRIV(self)->buf_packed )
+ free( DUMMY_PRIV(self)->buf_packed );
+ if( DUMMY_PRIV(self)->buf_planar )
+ free( DUMMY_PRIV(self)->buf_planar );
+ free( self->priv_data );
+ }
+ return( 1 );
+}
+
+static int resize( GEM_PLOTTER self, int w, int h )
+{
+ if( w == CURFB(self).w && h == CURFB(self).h )
+ return( 1 );
+ int newsize = calc_chunked_buffer_size( w, h, w, self->bpp_virt );
+ LOG(("%s: %s, oldsize: %d\n", (char*)__FILE__, __FUNCTION__, CURFB(self).size ));
+ /* todo: needed when using offscreen buffers...
+ if( newsize > self->screen_buffer_size ) {
+ self->screen_buffer_size = newsize;
+ self->screen_buffer =realloc( self->screen_buffer , self->screen_buffer_size );
+ }
+ */
+ CURFB(self).w = w;
+ CURFB(self).h = h;
+ update_visible_rect( self );
+ LOG(("%s: %s, newsize: %d\n", (char*)__FILE__, (char*)__FUNCTION__, CURFB(self).size ));
+ return( 1 );
+}
+static int move( GEM_PLOTTER self,short x, short y )
+{
+ bool upd;
+ if(x == CURFB(self).x && y == CURFB(self).y ){
+ return 1;
+ }
+ LOG(("%s: x: %d, y: %d\n",(char*)__FUNCTION__, x, y));
+ CURFB(self).x = x;
+ CURFB(self).y = y;
+ update_visible_rect( self );
+
+ /*
+ for offscreen plotters:
+ copy current contents to new pos?
+ we could also copy content of our own screen buffer,
+ but only when it's unlocked
+ ...nono, the user must do this manually. Because window move will already be handled by the OS
+ */
+ /*update_screen( self );*/
+ return( 1 );
+}
+
+
+static void * lock( GEM_PLOTTER self )
+{
+ LOG(("%s: %s\n", (char*)__FILE__, __FUNCTION__));
+ self->flags |= PLOT_FLAG_LOCKED;
+ wind_update(BEG_UPDATE);
+ wind_update(BEG_MCTRL);
+ return( NULL );
+}
+
+static int unlock( GEM_PLOTTER self )
+{
+ LOG(("%s: %s\n", (char*)__FILE__, __FUNCTION__));
+ self->flags &= ~PLOT_FLAG_LOCKED;
+ wind_update(END_MCTRL);
+ wind_update(END_UPDATE);
+ return( 1 );
+}
+
+/*
+ region specifies an rectangle within the framebuffer
+ calculation of screen coords is done automatically.
+*/
+static int update_region( GEM_PLOTTER self, GRECT region )
+{
+ int src_offs;
+ GRECT screen_area, tmp, visible;
+ short pxy[10];
+ visible.g_x = CURFB(self).vis_x;
+ visible.g_y = CURFB(self).vis_y;
+ visible.g_w = CURFB(self).vis_w;
+ visible.g_h = CURFB(self).vis_h;
+
+/*
+ LOG(("%s: %s %d\n", (char*)__FILE__, __FUNCTION__, __LINE__));
+ LOG(("region: x:%d, y:%d, w:%d, h:%d\n", region.g_x, region.g_y, region.g_w, region.g_h ));
+ LOG(("visible: x:%d, y:%d, w:%d, h:%d\n", visible.g_x, visible.g_y, visible.g_w, visible.g_h ));
+*/
+ /* sanitize region: */
+ tmp = region;
+ if( !rc_intersect(&visible, &tmp) )
+ return( 0 );
+/*
+ region is partially out of bottom or left:
+ if( region.g_x < self->visible.g_x )
+ {
+ region.g_w = self->visible.g_x - region.g_x;
+ region.g_x = self->visible.g_x;
+ }
+ if( region.g_y < self->visible.g_y )
+ {
+ region.g_h = self->visible.g_y - region.g_y;
+ region.g_y = self->visible.g_y;
+ }
+ region is partially out of top or right:
+ if( region.g_x + region.g_w > self->visible.g_x + self->visible.g_w )
+ {
+ region.g_w = self->visible.g_w - region.g_x;
+ }
+ if( region.g_y + region.g_h > self->visible.g_y + self->visible.g_h )
+ {
+ region.g_h = self->visible.g_h - region.g_y;
+ }
+ now region contains coords of framebuffer that needs redraw.
+*/
+ if( fbrect_to_screen( self, tmp, &screen_area) ) {
+ pxy[0] = screen_area.g_x;
+ pxy[1] = screen_area.g_y;
+ pxy[2] = screen_area.g_x + screen_area.g_w;
+ pxy[3] = screen_area.g_y;
+ pxy[4] = screen_area.g_x + screen_area.g_w;
+ pxy[5] = screen_area.g_y + screen_area.g_h;
+ pxy[6] = screen_area.g_x;
+ pxy[7] = screen_area.g_y + screen_area.g_h;
+ pxy[8] = screen_area.g_x;
+ pxy[9] = screen_area.g_y;
+ }
+ return( 1 );
+}
+
+/*
+ region specifies an rectangle within the screen,
+ calculation of framebuffer coords is done automatically.
+*/
+static int update_screen_region( GEM_PLOTTER self, GRECT region )
+{
+ LOG(("%s: %s\n", (char*)__FILE__, __FUNCTION__));
+
+ return( 1 );
+}
+
+/* Updates all visible parts of the framebuffer */
+static int update_screen( GEM_PLOTTER self )
+{
+ GRECT target, src;
+ int src_offset;
+ int i,x;
+ LOG(("%s: %s\n", (char*)__FILE__, __FUNCTION__));
+ if( !(PLOT_FLAG_OFFSCREEN & self->flags) )
+ return( 0 );
+ target.g_x = src.g_x = 0;
+ target.g_y = src.g_y = 0;
+ target.g_w = src.g_w = CURFB(self).w;
+ target.g_h = src.g_h = CURFB(self).h;
+ if( !fbrect_to_screen( self, target, &target ) )
+ return( -1 );
+ src_offset = get_pixel_offset( CURFB(self).vis_x, CURFB(self).vis_y, CURFB(self).w, self->bpp_virt );
+ LOG(("area: x:%d ,y:%d ,w:%d ,h:%d, from: %p (offset: %d) \n",
+ target.g_x, target.g_y,
+ target.g_w, target.g_h,
+ ((char*)CURFB(self).mem)+src_offset, src_offset
+ ));
+
+ return( 1 );
+}
+static int put_pixel(GEM_PLOTTER self, int x, int y, int color )
+{
+ LOG(("%s: %s\n", (char*)__FILE__, __FUNCTION__));
+ return( 1 );
+}
+
+static int copy_rect( GEM_PLOTTER self, GRECT src, GRECT dst )
+{
+ MFDB devmf;
+ MFDB scrmf;
+ short pxy[8];
+ GRECT vis;
+
+ /* clip to visible rect, only needed for onscreen renderer: */
+ vis.g_x = CURFB(self).vis_x;
+ vis.g_y = CURFB(self).vis_y;
+ vis.g_w = CURFB(self).vis_w;
+ vis.g_h = CURFB(self).vis_h;
+
+ if( !rc_intersect(&vis, &src) )
+ return 1;
+ if( !rc_intersect(&vis, &dst) )
+ return 1;
+
+ src.g_x = CURFB(self).x + src.g_x;
+ src.g_y = CURFB(self).y + src.g_y;
+ dst.g_x = CURFB(self).x + dst.g_x;
+ dst.g_y = CURFB(self).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;
+ self->lock( self );
+ vro_cpyfm( self->vdi_handle, S_ONLY, (short*)&pxy, &devmf, &scrmf);
+ self->unlock( self );
+
+ return( 1 );
+}
+
+static int arc(GEM_PLOTTER self,int x, int y, int radius, int angle1, int angle2, const plot_style_t * pstyle)
+{
+ plotter_vdi_clip( self, 1);
+ vswr_mode( self->vdi_handle, MD_REPLACE );
+ if( pstyle->fill_type == PLOT_OP_TYPE_NONE )
+ return 1;
+ if( pstyle->fill_type != PLOT_OP_TYPE_SOLID) {
+ vsl_color( self->vdi_handle, RGB_TO_VDI(pstyle->stroke_colour) );
+ vsf_perimeter( self->vdi_handle, 1);
+ vsf_interior( self->vdi_handle, 1 );
+ v_arc( self->vdi_handle, CURFB(self).x + x, CURFB(self).y + y, radius, angle1*10, angle2*10 );
+ } else {
+ vsl_color( self->vdi_handle, RGB_TO_VDI(pstyle->fill_colour) );
+ vsl_width( self->vdi_handle, 1 );
+ vsf_perimeter( self->vdi_handle, 1);
+ v_arc( self->vdi_handle, CURFB(self).x + x, CURFB(self).y + y, radius, angle1*10, angle2*10 );
+ }
+ plotter_vdi_clip( self, 0);
+ return ( 1 );
+}
+
+static int disc(GEM_PLOTTER self,int x, int y, int radius, const plot_style_t * pstyle)
+{
+ plotter_vdi_clip( self, 1);
+ if( pstyle->fill_type != PLOT_OP_TYPE_SOLID) {
+ vsf_color( self->vdi_handle, RGB_TO_VDI(pstyle->stroke_colour) );
+ vsf_perimeter( self->vdi_handle, 1);
+ vsf_interior( self->vdi_handle, 0 );
+ v_circle( self->vdi_handle, CURFB(self).x + x, CURFB(self).y + y, radius );
+ } else {
+ vsf_color( self->vdi_handle, RGB_TO_VDI(pstyle->fill_colour) );
+ vsf_perimeter( self->vdi_handle, 0);
+ vsf_interior( self->vdi_handle, FIS_SOLID );
+ v_circle( self->vdi_handle, CURFB(self).x + x, CURFB(self).y + y, radius );
+ }
+ plotter_vdi_clip( self, 0);
+ return ( 1 );
+}
+
+static int line(GEM_PLOTTER self,int x0, int y0, int x1, int y1, const plot_style_t * pstyle)
+{
+ short pxy[4];
+ short lt;
+ int sw = pstyle->stroke_width;
+ pxy[0] = CURFB(self).x + x0;
+ pxy[1] = CURFB(self).y + y0;
+ pxy[2] = CURFB(self).x + x1;
+ pxy[3] = CURFB(self).y + y1;
+ /* plotter_vdi_clip( self, 1); */
+ if( sw == 0)
+ sw = 1;
+ NSLT2VDI(lt, pstyle)
+ vsl_type( self->vdi_handle, lt );
+ vsl_width( self->vdi_handle, (short)sw );
+ vsl_color( self->vdi_handle, RGB_TO_VDI(pstyle->stroke_colour) );
+ v_pline(self->vdi_handle, 2, (short *)&pxy );
+ /* plotter_vdi_clip( self, 0); */
+ return ( 1 );
+}
+
+static int rectangle(GEM_PLOTTER self,int x0, int y0, int x1, int y1, const plot_style_t * pstyle)
+{
+ short pxy[10];
+
+ GRECT r, rclip, sclip;
+
+ /* plotter_vdi_clip( self, 1); */
+
+ rclip.g_x = self->clipping.x0;
+ rclip.g_y = self->clipping.y0;
+ rclip.g_w = self->clipping.x1 - self->clipping.x0;
+ rclip.g_h = self->clipping.y1 - self->clipping.y0;
+
+ sclip.g_x = rclip.g_x;
+ sclip.g_y = rclip.g_y;
+ sclip.g_w = CURFB(self).vis_w;
+ sclip.g_h = CURFB(self).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( 1 );
+ }
+ vsf_color( self->vdi_handle, RGB_TO_VDI(pstyle->fill_colour) );
+ vsf_perimeter( self->vdi_handle, 0);
+ vsf_interior( self->vdi_handle, FIS_SOLID );
+
+ pxy[0] = CURFB(self).x + r.g_x;
+ pxy[1] = CURFB(self).y + r.g_y;
+ pxy[2] = CURFB(self).x + r.g_x + r.g_w -1;
+ pxy[3] = CURFB(self).y + r.g_y + r.g_h -1;
+
+ vsf_style( self->vdi_handle, 1);
+ v_bar( self->vdi_handle, (short*)&pxy );
+
+ /* plotter_vdi_clip( self, 0); */
+ return ( 1 );
+}
+
+static int polygon(GEM_PLOTTER self,const int *p, unsigned int n, const plot_style_t * pstyle)
+{
+ short pxy[n+2];
+ unsigned int i=0;
+ short d[4];
+ if( vdi_sysinfo.maxpolycoords > 0 )
+ assert( n < vdi_sysinfo.maxpolycoords );
+/*
+ Does this double check make sense?
+ else
+ assert( n < vdi_sysinfo.maxintin );
+*/
+ /* test this: */
+ /* plotter_vdi_clip( self, 1); */
+ vsf_interior( self->vdi_handle, FIS_SOLID );
+ vsf_style( self->vdi_handle, 1);
+ for( i = 0; i<n*2; i=i+2 ) {
+ pxy[i] = (short)CURFB(self).x+p[i];
+ pxy[i+1] = (short)CURFB(self).y+p[i+1];
+ }
+ if( pstyle->fill_type == PLOT_OP_TYPE_SOLID){
+ vsf_color( self->vdi_handle, BLACK);
+ v_fillarea(self->vdi_handle, n, (short*)&pxy);
+
+ } else {
+ pxy[n*2]=pxy[0];
+ pxy[n*2+1]=pxy[1];
+ vsl_color( self->vdi_handle, BLACK );
+ v_pline(self->vdi_handle, n+1, (short *)&pxy );
+ }
+ /* plotter_vdi_clip( self, 0); */
+ return ( 1 );
+}
+
+static int path(GEM_PLOTTER self,const float *p, unsigned int n, int fill, float width,
+ int c, const float transform[6])
+{
+ LOG(("%s: %s\n", (char*)__FILE__, __FUNCTION__));
+ return ( 1 );
+}
+
+
+static inline uint32_t ablend(uint32_t pixel, uint32_t scrpixel)
+{
+ int opacity = pixel & 0xFF;
+ int transp = 0x100 - opacity;
+ uint32_t rb, g;
+
+ rb = ((pixel & 0xFF00FF00UL) * opacity +
+ (scrpixel & 0xFF00FF00UL) * transp) >> 8;
+ g = ((pixel & 0x00FF0000UL) * opacity +
+ (scrpixel & 0x00FF0000UL) * transp) >> 8;
+
+ return (rb & 0xFF00FF00) | (g & 0x00FF0000);
+}
+
+static int bitmap_resize( GEM_PLOTTER self, struct bitmap * img, int nw, int nh )
+{
+ HermesFormat fmt;
+ short bpp = bitmap_get_bpp( img );
+ int stride = bitmap_get_rowstride( img );
+ int err;
+
+ if( img->resized != NULL ) {
+ if( img->resized->width != nw || img->resized->height != nh ) {
+ bitmap_destroy( img->resized );
+ img->resized = NULL;
+ } else {
+ return( 0 );
+ }
+ }
+
+ /* allocate the mem for resized bitmap */
+ img->resized = bitmap_create_ex( nw, nh, bpp, nw*bpp, 0, NULL );
+ if( img->resized == NULL ) {
+ assert( img->resized );
+ return ( -ERR_NO_MEM );
+ }
+
+ /* allocate an converter, only for resizing */
+ err = Hermes_ConverterRequest( hermes_res_h,
+ &DUMMY_PRIV(self)->nsfmt,
+ &DUMMY_PRIV(self)->nsfmt
+ );
+ if( err == 0 ) {
+ return( -ERR_PLOTTER_NOT_AVAILABLE );
+ }
+
+ err = Hermes_ConverterCopy( hermes_res_h,
+ img->pixdata,
+ 0, /* x src coord of top left in pixel coords */
+ 0, /* y src coord of top left in pixel coords */
+ bitmap_get_width( img ), 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,
+ bitmap_get_rowstride( img->resized ) /* stride as bytes */
+ );
+ if( err == 0 ) {
+ bitmap_destroy( img->resized );
+ img->resized = NULL;
+ return( -2 );
+ }
+
+ return( 0 );
+}
+
+/*
+ fuellt ein mfdb, wenn bpp==null wird angenommen das ein MFDB fr
+ den Bildschirm initialisiert werden soll, der Speicher fuer das Bild
+ wird daher nicht alloziert ( fd_addr == 0 )
+*/
+static int init_mfdb(int bpp, int w, int h, MFDB * out )
+{
+ int pxsize = bpp >> 3;
+ int dststride;
+ dststride = MFDB_STRIDE( w );
+ if( bpp > 0 ) {
+ out->fd_addr = malloc( dststride * pxsize * h );
+ out->fd_stand = 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( 1 );
+}
+
+/*
+* 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
+*/
+static struct bitmap * snapshot_create(GEM_PLOTTER self, int x, int y, int w, int h)
+{
+ MFDB scr;
+ short pxy[8];
+ int err;
+
+ /* make sure the screen format is pixel packed... */
+ /* no method to convert planar screen to pixel packed ... right now */
+ assert( vdi_sysinfo.vdiformat == VDI_FORMAT_PACK );
+
+ {
+ int pxsize = vdi_sysinfo.scr_bpp >> 3;
+ int scr_stride = MFDB_STRIDE( w );
+ int scr_size = scr_stride * pxsize * h;
+ if( DUMMY_PRIV(self)->size_buf_scr == 0 ){
+ /* init screen mfdb */
+ DUMMY_PRIV(self)->buf_scr.fd_addr = malloc( scr_size );
+ DUMMY_PRIV(self)->size_buf_scr = scr_size;
+ } else {
+ if( scr_size > DUMMY_PRIV(self)->size_buf_scr ) {
+ DUMMY_PRIV(self)->buf_scr.fd_addr = realloc(
+ DUMMY_PRIV(self)->buf_scr.fd_addr, scr_size
+ );
+ DUMMY_PRIV(self)->size_buf_scr = scr_size;
+ }
+ }
+ if( DUMMY_PRIV(self)->buf_scr.fd_addr == NULL ) {
+ DUMMY_PRIV(self)->size_buf_scr = 0;
+ return( NULL );
+ }
+ DUMMY_PRIV(self)->buf_scr.fd_nplanes = vdi_sysinfo.scr_bpp;
+ DUMMY_PRIV(self)->buf_scr.fd_w = scr_stride;
+ DUMMY_PRIV(self)->buf_scr.fd_h = h;
+ DUMMY_PRIV(self)->buf_scr.fd_wdwidth = scr_stride >> 4;
+ assert( DUMMY_PRIV(self)->buf_scr.fd_addr != NULL );
+ }
+
+ init_mfdb( 0, w, h, &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] = pxy[2];
+ pxy[7] = pxy[3];
+ vro_cpyfm( self->vdi_handle, S_ONLY, (short*)&pxy,
+ &scr, &DUMMY_PRIV(self)->buf_scr
+ );
+
+ /* convert screen buffer to ns format: */
+ if( DUMMY_PRIV(self)->buf_scr_compat == NULL ) {
+ DUMMY_PRIV(self)->buf_scr_compat = bitmap_create(w, h, 0);
+ } else {
+ DUMMY_PRIV(self)->buf_scr_compat = bitmap_realloc( w, h,
+ DUMMY_PRIV(self)->buf_scr_compat->bpp,
+ w * DUMMY_PRIV(self)->buf_scr_compat->bpp,
+ BITMAP_GROW,
+ DUMMY_PRIV(self)->buf_scr_compat );
+ }
+ err = Hermes_ConverterRequest( hermes_cnv_h,
+ &DUMMY_PRIV(self)->vfmt,
+ &DUMMY_PRIV(self)->nsfmt
+ );
+ assert( err != 0 );
+ err = Hermes_ConverterCopy( hermes_cnv_h,
+ DUMMY_PRIV(self)->buf_scr.fd_addr,
+ 0, /* x src coord of top left in pixel coords */
+ 0, /* y src coord of top left in pixel coords */
+ w, h,
+ DUMMY_PRIV(self)->buf_scr.fd_w * vdi_sysinfo.pixelsize, /* stride as bytes */
+ DUMMY_PRIV(self)->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,
+ bitmap_get_rowstride(DUMMY_PRIV(self)->buf_scr_compat) /* stride as bytes */
+ );
+ assert( err != 0 );
+ return( (struct bitmap * )DUMMY_PRIV(self)->buf_scr_compat );
+}
+
+static void snapshot_suspend(GEM_PLOTTER self )
+{
+ if( DUMMY_PRIV(self)->size_buf_scr > CONV_KEEP_LIMIT ) {
+ DUMMY_PRIV(self)->buf_scr.fd_addr = realloc(
+ DUMMY_PRIV(self)->buf_scr.fd_addr, CONV_KEEP_LIMIT
+ );
+ if( DUMMY_PRIV(self)->buf_scr.fd_addr != NULL ) {
+ DUMMY_PRIV(self)->size_buf_scr = CONV_KEEP_LIMIT;
+ } else {
+ DUMMY_PRIV(self)->size_buf_scr = 0;
+ }
+ }
+
+ if( bitmap_buffer_size( DUMMY_PRIV(self)->buf_scr_compat ) > CONV_KEEP_LIMIT ) {
+ int w = 0;
+ int h = 1;
+ w = (CONV_KEEP_LIMIT / DUMMY_PRIV(self)->buf_scr_compat->bpp);
+ assert( CONV_KEEP_LIMIT == w*DUMMY_PRIV(self)->buf_scr_compat->bpp );
+ DUMMY_PRIV(self)->buf_scr_compat = bitmap_realloc( w, h,
+ DUMMY_PRIV(self)->buf_scr_compat->bpp,
+ CONV_KEEP_LIMIT, BITMAP_SHRINK, DUMMY_PRIV(self)->buf_scr_compat
+ );
+
+ }
+}
+
+static void snapshot_destroy( GEM_PLOTTER self )
+{
+ if( DUMMY_PRIV(self)->buf_scr.fd_addr ) {
+ free( DUMMY_PRIV(self)->buf_scr.fd_addr );
+ DUMMY_PRIV(self)->buf_scr.fd_addr = NULL;
+ }
+
+ if( DUMMY_PRIV(self)->buf_scr_compat ) {
+ bitmap_destroy( DUMMY_PRIV(self)->buf_scr_compat );
+ DUMMY_PRIV(self)->buf_scr_compat = NULL;
+ }
+}
+
+/* convert bitmap to framebuffer format */
+static int convert_bitmap( GEM_PLOTTER self,
+ struct bitmap * img,
+ int x,
+ int y,
+ GRECT * clip,
+ uint32_t bg,
+ MFDB *out )
+{
+ short vpxsize = self->bpp_virt >> 3; /* / 8 */
+ int dststride; /* stride of dest. image */
+ int dstsize; /* size of dest. in byte */
+ int err;
+ int bw;
+ struct bitmap * scrbuf = NULL;
+ struct bitmap * bm;
+
+ assert( clip->g_h > 0 );
+ assert( clip->g_w > 0 );
+
+ bm = img;
+ bw = bitmap_get_width( img );
+
+ /* rem. if eddi xy is installed, we could directly access the screen! */
+ /* apply transparency to the image: */
+ if( (img->opaque == false)
+ && ((self->flags & PLOT_FLAG_TRANS) != 0)
+ && (vdi_sysinfo.vdiformat == VDI_FORMAT_PACK ) ) {
+ uint32_t * imgpixel;
+ uint32_t * screenpixel;
+ int img_x, img_y; /* points into old bitmap */
+ int screen_x, screen_y; /* pointers into new bitmap */
+ /* copy the screen to an temp buffer: */
+ scrbuf = snapshot_create(self, x, y, clip->g_w, clip->g_h );
+ if( scrbuf != NULL ) {
+ /* copy blended pixels the new buffer (which contains screen content): */
+ int img_stride = bitmap_get_rowstride(bm);
+ int screen_stride = bitmap_get_rowstride(scrbuf);
+ for( img_y = clip->g_y, screen_y = 0; screen_y < clip->g_h; screen_y++, img_y++) {
+ imgpixel = (uint32_t *)(bm->pixdata + (img_stride * img_y));
+ screenpixel = (uint32_t *)(scrbuf->pixdata + (screen_stride * screen_y));
+ for( img_x = clip->g_x, screen_x = 0; screen_x < clip->g_w; screen_x++, img_x++ ) {
+ if( (imgpixel[img_x] & 0xFF) != 0xFF ) {
+ if( (imgpixel[img_x] & 0x0FF) != 0 ) {
+ screenpixel[screen_x] = ablend( imgpixel[img_x], screenpixel[screen_x]);
+ }
+ } else {
+ screenpixel[screen_x] = imgpixel[img_x];
+ }
+ }
+ }
+ clip->g_x = 0;
+ clip->g_y = 0;
+ bm = scrbuf;
+ }
+ }
+
+ /* (re)allocate buffer for framebuffer image: */
+ dststride = MFDB_STRIDE( clip->g_w );
+ dstsize = dststride * vpxsize * clip->g_h;
+ if( dstsize > DUMMY_PRIV(self)->size_buf_packed) {
+ int blocks = (dstsize / (CONV_BLOCK_SIZE-1))+1;
+ if( DUMMY_PRIV(self)->buf_packed == NULL )
+ DUMMY_PRIV(self)->buf_packed =(void*)malloc( blocks * CONV_BLOCK_SIZE );
+ else
+ DUMMY_PRIV(self)->buf_packed =(void*)realloc(
+ DUMMY_PRIV(self)->buf_packed,
+ blocks * CONV_BLOCK_SIZE
+ );
+ assert( DUMMY_PRIV(self)->buf_packed );
+ if( DUMMY_PRIV(self)->buf_packed == NULL ) {
+ if( scrbuf != NULL )
+ bitmap_destroy( scrbuf );
+ return( 0-ERR_NO_MEM );
+ }
+ DUMMY_PRIV(self)->size_buf_packed = blocks * CONV_BLOCK_SIZE;
+ }
+ out->fd_addr = DUMMY_PRIV(self)->buf_packed;
+ out->fd_w = dststride;
+ out->fd_h = clip->g_h;
+ out->fd_wdwidth = dststride >> 4;
+ out->fd_stand = 0;
+ out->fd_nplanes = (short)self->bpp_virt;
+ out->fd_r1 = out->fd_r2 = out->fd_r3 = 0;
+
+ err = Hermes_ConverterRequest(
+ hermes_cnv_h,
+ &DUMMY_PRIV(self)->nsfmt,
+ &DUMMY_PRIV(self)->vfmt
+ );
+ assert( err != 0 );
+ /* convert image to virtual format: */
+ err = Hermes_ConverterCopy( hermes_cnv_h,
+ bm->pixdata,
+ clip->g_x, /* x src coord of top left in pixel coords */
+ clip->g_y, /* y src coord of top left in pixel coords */
+ clip->g_w, clip->g_h,
+ bm->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 */
+ clip->g_w, clip->g_h,
+ dststride * vpxsize /* stride as bytes */
+ );
+ assert( err != 0 );
+
+ return( 0 );
+
+}
+
+static void convert_bitmap_done( GEM_PLOTTER self )
+{
+ if( DUMMY_PRIV(self)->size_buf_packed > CONV_KEEP_LIMIT ) {
+ /* free the mem if it was an large allocation ... */
+ DUMMY_PRIV(self)->buf_packed = realloc( DUMMY_PRIV(self)->buf_packed, CONV_KEEP_LIMIT );
+ DUMMY_PRIV(self)->size_buf_packed = CONV_KEEP_LIMIT;
+ }
+ snapshot_suspend( self );
+}
+
+
+static int bitmap( GEM_PLOTTER self, struct bitmap * bmp, int x, int y,
+ unsigned long bg, unsigned long flags )
+{
+ MFDB src_mf;
+ MFDB scrmf;
+ short pxy[8];
+ GRECT off, clip, loc, vis;
+
+ 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.g_x = self->clipping.x0;
+ clip.g_y = self->clipping.y0;
+ clip.g_w = self->clipping.x1 - self->clipping.x0;
+ clip.g_h = self->clipping.y1 - self->clipping.y0;
+
+ if( !rc_intersect( &clip, &off) ) {
+ return( true );
+ }
+
+ vis.g_x = CURFB(self).vis_x;
+ vis.g_y = CURFB(self).vis_y;
+ vis.g_w = CURFB(self).vis_w;
+ vis.g_h = CURFB(self).vis_h;
+ if( !rc_intersect( &vis, &off) ) {
+ return( true );
+ }
+
+ loc = off;
+ off.g_x = MAX(0, off.g_x - x);
+ off.g_y = MAX(0, off.g_y - y);
+ loc.g_x = MAX(0, loc.g_x);
+ loc.g_y = MAX(0, loc.g_y);
+
+ pxy[0] = 0;
+ pxy[1] = 0;
+ pxy[2] = off.g_w-1;
+ pxy[3] = off.g_h-1;
+ pxy[4] = CURFB(self).x + loc.g_x;
+ pxy[5] = CURFB(self).y + loc.g_y;
+ pxy[6] = CURFB(self).x + loc.g_x + off.g_w-1;
+ pxy[7] = CURFB(self).y + loc.g_y + off.g_h-1;
+ if( convert_bitmap( self, bmp, pxy[4], pxy[5], &off, bg, &src_mf) != 0 ) {
+ return( true );
+ }
+ vro_cpyfm( self->vdi_handle, S_ONLY, (short*)&pxy, &src_mf, &scrmf);
+ convert_bitmap_done( self );
+ return( true );
+}
+
+static int text(GEM_PLOTTER self, int x, int y, const char *text, size_t length, const plot_font_style_t *fstyle)
+{
+ self->font_plotter->text( self->font_plotter,
+ x,
+ y,
+ text, length,
+ fstyle
+ );
+ return ( 1 );
+}
diff --git a/atari/plot/plotter_vdi.h b/atari/plot/plotter_vdi.h
new file mode 100644
index 000000000..8c0a95c9c
--- /dev/null
+++ b/atari/plot/plotter_vdi.h
@@ -0,0 +1,48 @@
+/*
+ * 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 GEM_PLOTTER_DUMMY_H_INCLUDED
+#define GEM_PLOTTER_DUMMY_H_INCLUDED
+#include "plotter.h"
+#include <Hermes/Hermes.h>
+
+struct s_vdi_priv_data {
+ short bufops;
+ void * buf_packed; /* temp buffer for bitmap conversion */
+ int size_buf_packed;
+ void * buf_planar; /* temp buffer for bitmap conversion */
+ int size_buf_planar;
+ MFDB buf_scr; /* buffer for native screen capture */
+ int size_buf_scr;
+ struct bitmap * buf_scr_compat;
+ HermesFormat vfmt; /* framebuffer format */
+ /* no screen format here, hermes may not suitable for it */
+ HermesFormat nsfmt; /* netsurf bitmap format */
+};
+
+#define CONV_KEEP_LIMIT 512000 /* how much memory should be kept allocated for temp. conversion bitmaps? */
+#define CONV_BLOCK_SIZE 32000 /* how much memory to allocate if some is needed */
+#define DUMMY_PRIV(self) ((struct s_vdi_priv_data*)self->priv_data)
+
+/* Each driver must export 1 method to create the plotter object: */
+int ctor_plotter_vdi( GEM_PLOTTER p );
+
+static struct bitmap * snapshot_create(GEM_PLOTTER self, int x, int y, int w, int h);
+static void snapshot_suspend(GEM_PLOTTER self );
+static void snapshot_destroy( GEM_PLOTTER self );
+
+#endif
diff --git a/atari/res/netsurf.rsh b/atari/res/netsurf.rsh
new file mode 100644
index 000000000..43429a205
--- /dev/null
+++ b/atari/res/netsurf.rsh
@@ -0,0 +1,97 @@
+ /* Resource C-Header-File v1.97 fr ResourceMaster ab v2.06 by ARDISOFT */
+
+#define MAINMENU 0 /* menu */
+#define MAINMENU_T_FILE 4 /* TITLE in tree MAINMENU */
+#define MAINMENU_T_EDIT 5 /* TITLE in tree MAINMENU */
+#define MAINMENU_T_VIEW 6 /* TITLE in tree MAINMENU */
+#define MAINMENU_T_NAVIGATE 7 /* TITLE in tree MAINMENU */
+#define MAINMENU_T_UTIL 8 /* TITLE in tree MAINMENU */
+#define MAINMENU_T_HELP 9 /* TITLE in tree MAINMENU */
+#define MAINMENU_M_ABOUT 12 /* STRING in tree MAINMENU */
+#define MAINMENU_M_NEWWIN 21 /* STRING in tree MAINMENU */
+#define MAINMENU_M_OPENURL 22 /* STRING in tree MAINMENU */
+#define MAINMENU_M_OPENFILE 23 /* STRING in tree MAINMENU */
+#define MAINMENU_M_CLOSEWIN 24 /* STRING in tree MAINMENU */
+#define MAINMENU_SEP0 25 /* STRING in tree MAINMENU */
+#define MAINMENU_M_SAVEPAGE 26 /* STRING in tree MAINMENU */
+#define MAINMENU_SEP1 27 /* STRING in tree MAINMENU */
+#define MAINMENU_M_QUIT 28 /* STRING in tree MAINMENU */
+#define MAINMENU_M_CUT 30 /* STRING in tree MAINMENU */
+#define MAINMENU_M_COPY 31 /* STRING in tree MAINMENU */
+#define MAINMENU_M_PASTE 32 /* STRING in tree MAINMENU */
+#define MAINMENU_SEP3 33 /* STRING in tree MAINMENU */
+#define MAINMENU_M_FIND 34 /* STRING in tree MAINMENU */
+#define MAINMENU_M_STOP 36 /* STRING in tree MAINMENU */
+#define MAINMENU_M_RELOAD 37 /* STRING in tree MAINMENU */
+#define MAINMENU_M_SCALE 39 /* STRING in tree MAINMENU */
+#define MAINMENU_M_TOOLBARS 41 /* STRING in tree MAINMENU */
+#define MAINMENU_M_SAVEWIN 43 /* STRING in tree MAINMENU */
+#define MAINMENU_M_DEBUG_RENDER 44 /* STRING in tree MAINMENU */
+#define MAINMENU_M_BACK 46 /* STRING in tree MAINMENU */
+#define MAINMENU_M_FORWARD 47 /* STRING in tree MAINMENU */
+#define MAINMENU_M_HOME 48 /* STRING in tree MAINMENU */
+#define MAINMENU_M_LHISTORY 50 /* STRING in tree MAINMENU */
+#define MAINMENU_M_GHISTORY 51 /* STRING in tree MAINMENU */
+#define MAINMENU_M_ADD_BOOKMARK 53 /* STRING in tree MAINMENU */
+#define MAINMENU_M_BOOKMARKS 54 /* STRING in tree MAINMENU */
+#define MAINMENU_M_CHOICES 56 /* STRING in tree MAINMENU */
+#define MAINMENU_M_HELP_CONTENT 58 /* STRING in tree MAINMENU */
+
+#define TOOLBAR 1 /* form/dial */
+#define TOOLBAR_BT_BACK 2 /* CICON in tree TOOLBAR */
+#define TOOLBAR_BT_HOME 3 /* CICON in tree TOOLBAR */
+#define TOOLBAR_BT_FORWARD 4 /* CICON in tree TOOLBAR */
+#define TOOLBAR_BT_RELOAD 5 /* CICON in tree TOOLBAR */
+#define TOOLBAR_BT_STOP 6 /* CICON in tree TOOLBAR */
+
+#define ICONIFY 2 /* form/dial */
+#define ICONIFY_GLOBE 1 /* CICON in tree ICONIFY */
+
+#define FAVICON 3 /* form/dial */
+
+#define CURSOR 4 /* 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 5 /* 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 VERIFY 6 /* form/dial */
+#define VERIFY_LBL_HOST 3 /* TEXT in tree VERIFY */
+#define VERIFY_BT_ACCEPT 4 /* BUTTON in tree VERIFY */
+#define VERIFY_BT_REJECT 5 /* BUTTON in tree VERIFY */
+#define VERIFY_BT_NEXT_CERT 7 /* BUTTON in tree VERIFY */
+#define VERIFY_BOX_DETAILS 8 /* BOX in tree VERIFY */
+#define VERIFY_BOX_H 9 /* BOX in tree VERIFY */
+#define VERIFY_BT_SCROLL_R 10 /* BOXCHAR in tree VERIFY */
+#define VERIFY_BT_SCROLL_L 11 /* BOXCHAR in tree VERIFY */
+#define VERIFY_BOX_MOVER_H 12 /* BOX in tree VERIFY */
+#define VERIFY_BT_SCROLL_U 13 /* BOXCHAR in tree VERIFY */
+#define VERIFY_BT_SCROLL_D 14 /* BOXCHAR in tree VERIFY */
+#define VERIFY_BOX_V 15 /* BOX in tree VERIFY */
+#define VERIFY_MOVER_V 16 /* BOX in tree VERIFY */
+
+#define THROBBER 7 /* form/dial */
+
+#define SLIDER 8 /* form/dial */
+#define SLIDER_BT_SCROLL_L 1 /* BOXCHAR in tree SLIDER */
+#define SLIDER_BOX_H 2 /* BOX in tree SLIDER */
+#define SLIDER_BOX_MOVER_H 3 /* BOX in tree SLIDER */
+#define SLIDER_BT_SCROLL_R 4 /* BOXCHAR in tree SLIDER */
+#define SLIDER_BT_SCROLL_U 5 /* BOXCHAR in tree SLIDER */
+#define SLIDER_BOX_V 6 /* BOX in tree SLIDER */
+#define SLIDER_MOVER_V 8 /* BOX in tree SLIDER */
+#define SLIDER_BT_SCROLL_D 7 /* BOXCHAR in tree SLIDER */
+
+#define TOOLBAR_HOTLIST 9 /* form/dial */
+#define TOOLBAR_HOTLIST_CREATE_FOLDER 1 /* BUTTON in tree TOOLBAR_HOTLIST */
+#define TOOLBAR_HOTLIST_ADD 2 /* BUTTON in tree TOOLBAR_HOTLIST */
+#define TOOLBAR_HOTLIST_DELETE 3 /* BUTTON in tree TOOLBAR_HOTLIST */
diff --git a/atari/res/netsurf.rsm b/atari/res/netsurf.rsm
new file mode 100644
index 000000000..754b3f987
--- /dev/null
+++ b/atari/res/netsurf.rsm
@@ -0,0 +1,94 @@
+ResourceMaster v3.65
+#C 10@0@0@0@
+#N 99@32@AZAaza___ _@AZAaza090___ _@@_@
+#FoC-Header@rsm2out@C-Header@rsh@@@[C-Header@0@
+#R 0@0@1@1@1@1@
+#M 20010100@17741@7728@533@
+#T 0@1@MAINMENU@@59@@
+#O 4@32@T_FILE@@
+#O 5@32@T_EDIT@@
+#O 6@32@T_VIEW@@
+#O 7@32@T_NAVIGATE@@
+#O 8@32@T_UTIL@@
+#O 9@32@T_HELP@@
+#O 12@28@M_ABOUT@@
+#O 21@28@M_NEWWIN@@
+#O 22@28@M_OPENURL@@
+#O 23@28@M_OPENFILE@@
+#O 24@28@M_CLOSEWIN@@
+#O 25@28@SEP0@@
+#O 26@28@M_SAVEPAGE@@
+#O 27@28@SEP1@@
+#O 28@28@M_QUIT@@
+#O 30@28@M_CUT@@
+#O 31@28@M_COPY@@
+#O 32@28@M_PASTE@@
+#O 33@28@SEP3@@
+#O 34@28@M_FIND@@
+#O 36@28@M_STOP@@
+#O 37@28@M_RELOAD@@
+#O 39@28@M_SCALE@@
+#O 41@28@M_TOOLBARS@@
+#O 43@28@M_SAVEWIN@@
+#O 44@28@M_DEBUG_RENDER@@
+#O 46@28@M_BACK@@
+#O 47@28@M_FORWARD@@
+#O 48@28@M_HOME@@
+#O 50@28@M_LHISTORY@@
+#O 51@28@M_GHISTORY@@
+#O 53@28@M_ADD_BOOKMARK@@
+#O 54@28@M_BOOKMARKS@@
+#O 56@28@M_CHOICES@@
+#O 58@28@M_HELP_CONTENT@@
+#T 1@2@TOOLBAR@@7@@
+#O 2@33@BT_BACK@@
+#O 3@33@BT_HOME@@
+#O 4@33@BT_FORWARD@@
+#O 5@33@BT_RELOAD@@
+#O 6@33@BT_STOP@@
+#T 2@2@ICONIFY@@3@@
+#O 1@33@GLOBE@@
+#T 3@2@FAVICON@@2@@
+#T 4@2@CURSOR@@8@@
+#O 1@31@HELP@@
+#O 2@31@NODROP@@
+#O 3@31@APPSTART@@
+#O 4@31@DENY@@
+#O 5@31@SIZEWE@@
+#O 6@31@SIZENS@@
+#O 7@31@MENU@@
+#T 5@2@LOGIN@@7@@
+#O 2@29@TB_USER@@
+#O 4@29@TB_PASSWORD@@
+#O 5@26@BT_LOGIN@@
+#O 6@26@BT_ABORT@@
+#T 6@2@VERIFY@@17@@
+#O 0@20@@VERT SLIDER SIND HIDDEN!@
+#O 3@21@LBL_HOST@@
+#O 4@26@BT_ACCEPT@@
+#O 5@26@BT_REJECT@@
+#O 7@26@BT_NEXT_CERT@@
+#O 8@20@BOX_DETAILS@@
+#O 9@20@BOX_H@@
+#O 10@27@BT_SCROLL_R@@
+#O 11@27@BT_SCROLL_L@@
+#O 12@20@BOX_MOVER_H@@
+#O 13@27@BT_SCROLL_U@@
+#O 14@27@BT_SCROLL_D@@
+#O 15@20@BOX_V@@
+#O 16@20@MOVER_V@@
+#T 7@2@THROBBER@@9@@
+#T 8@2@SLIDER@@9@@
+#O 1@27@BT_SCROLL_L@@
+#O 2@20@BOX_H@@
+#O 3@20@BOX_MOVER_H@@
+#O 4@27@BT_SCROLL_R@@
+#O 5@27@BT_SCROLL_U@@
+#O 6@20@BOX_V@@
+#O 8@20@MOVER_V@@
+#O 7@27@BT_SCROLL_D@@
+#T 9@2@TOOLBAR_HOTLIST@@4@@
+#O 1@26@CREATE_FOLDER@@
+#O 2@26@ADD@@
+#O 3@26@DELETE@@
+#c 1564@
diff --git a/atari/schedule.c b/atari/schedule.c
new file mode 100644
index 000000000..e72e1bcbe
--- /dev/null
+++ b/atari/schedule.c
@@ -0,0 +1,223 @@
+/*
+ * Copyright 2008 Vincent Sanders <vince@simtec.co.uk>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/time.h>
+#include <time.h>
+
+#include "desktop/browser.h"
+#include "atari/schedule.h"
+
+#include "utils/log.h"
+
+/* linked list of scheduled callbacks */
+static struct nscallback *schedule_list = NULL;
+
+/**
+ * scheduled callback.
+ */
+struct nscallback
+{
+ struct nscallback *next;
+ struct timeval tv;
+ void (*callback)(void *p);
+ void *p;
+};
+
+
+/**
+ * Schedule a callback.
+ *
+ * \param tival interval before the callback should be made / cs
+ * \param callback callback function
+ * \param p user parameter, passed to callback function
+ *
+ * The callback function will be called as soon as possible after t cs have
+ * passed.
+ */
+
+void schedule(int cs_ival, void (*callback)(void *p), void *p)
+{
+ struct nscallback *nscb;
+ struct timeval tv;
+
+ tv.tv_sec = cs_ival / 100; /* cs to seconds */
+ tv.tv_usec = (cs_ival % 100) * 10000; /* remainder to microseconds */
+
+ nscb = calloc(1, sizeof(struct nscallback));
+
+ LOG(("adding callback %p for %p(%p) at %d cs", nscb, callback, p, cs_ival));
+
+ gettimeofday(&nscb->tv, NULL);
+ timeradd(&nscb->tv, &tv, &nscb->tv);
+
+ nscb->callback = callback;
+ nscb->p = p;
+
+ /* add to list front */
+ nscb->next = schedule_list;
+ schedule_list = nscb;
+}
+
+/**
+ * Unschedule a callback.
+ *
+ * \param callback callback function
+ * \param p user parameter, passed to callback function
+ *
+ * All scheduled callbacks matching both callback and p are removed.
+ */
+
+void schedule_remove(void (*callback)(void *p), void *p)
+{
+ struct nscallback *cur_nscb;
+ struct nscallback *prev_nscb;
+ struct nscallback *unlnk_nscb;
+
+ if (schedule_list == NULL)
+ return;
+
+ LOG(("removing %p, %p", callback, p));
+
+ cur_nscb = schedule_list;
+ prev_nscb = NULL;
+
+ while (cur_nscb != NULL) {
+ if ((cur_nscb->callback == callback) &&
+ (cur_nscb->p == p)) {
+ /* item to remove */
+
+ LOG(("callback entry %p removing %p(%p)",
+ cur_nscb, cur_nscb->callback, cur_nscb->p));
+
+ /* remove callback */
+ unlnk_nscb = cur_nscb;
+ cur_nscb = unlnk_nscb->next;
+
+ if (prev_nscb == NULL) {
+ schedule_list = cur_nscb;
+ } else {
+ prev_nscb->next = cur_nscb;
+ }
+ free (unlnk_nscb);
+ } else {
+ /* move to next element */
+ prev_nscb = cur_nscb;
+ cur_nscb = prev_nscb->next;
+ }
+ }
+}
+
+/**
+ * Process events up to current time.
+ */
+
+int
+schedule_run(void)
+{
+ struct timeval tv;
+ struct timeval nexttime;
+ struct timeval rettime;
+ struct nscallback *cur_nscb;
+ struct nscallback *prev_nscb;
+ struct nscallback *unlnk_nscb;
+
+ if (schedule_list == NULL)
+ return -1;
+
+ /* reset enumeration to the start of the list */
+ cur_nscb = schedule_list;
+ prev_nscb = NULL;
+ nexttime = cur_nscb->tv;
+
+ gettimeofday(&tv, NULL);
+
+ while (cur_nscb != NULL) {
+ if (timercmp(&tv, &cur_nscb->tv, >)) {
+ /* scheduled time */
+
+ /* remove callback */
+ unlnk_nscb = cur_nscb;
+
+ if (prev_nscb == NULL) {
+ schedule_list = unlnk_nscb->next;
+ } else {
+ prev_nscb->next = unlnk_nscb->next;
+ }
+
+ LOG(("callback entry %p running %p(%p)",
+ unlnk_nscb, unlnk_nscb->callback, unlnk_nscb->p));
+ /* call callback */
+ unlnk_nscb->callback(unlnk_nscb->p);
+
+ free(unlnk_nscb);
+
+ /* need to deal with callback modifying the list. */
+ if (schedule_list == NULL) {
+ LOG(("schedule_list == NULL"));
+ return -1; /* no more callbacks scheduled */
+ }
+
+ /* reset enumeration to the start of the list */
+ cur_nscb = schedule_list;
+ prev_nscb = NULL;
+ nexttime = cur_nscb->tv;
+ } else {
+ /* if the time to the event is sooner than the
+ * currently recorded soonest event record it
+ */
+ if (timercmp(&nexttime, &cur_nscb->tv, >)) {
+ nexttime = cur_nscb->tv;
+ }
+ /* move to next element */
+ prev_nscb = cur_nscb;
+ cur_nscb = prev_nscb->next;
+ }
+ }
+
+ /* make rettime relative to now */
+ timersub(&nexttime, &tv, &rettime);
+
+ LOG(("returning time to next event as %ldms",(rettime.tv_sec * 1000) + (rettime.tv_usec / 1000)));
+ /*return next event time in milliseconds (24days max wait) */
+ return (rettime.tv_sec * 1000) + (rettime.tv_usec / 1000);
+}
+
+void list_schedule(void)
+{
+ struct timeval tv;
+ struct nscallback *cur_nscb;
+
+ gettimeofday(&tv, NULL);
+
+ LOG(("schedule list at %ld:%ld", tv.tv_sec, tv.tv_usec));
+
+ cur_nscb = schedule_list;
+
+ while (cur_nscb != NULL) {
+ LOG(("Schedule %p at %ld:%ld",
+ cur_nscb, cur_nscb->tv.tv_sec, cur_nscb->tv.tv_usec));
+ cur_nscb = cur_nscb->next;
+ }
+}
+
+
+/*
+ * Local Variables:
+ * c-basic-offset:8
+ * End:
+ */
diff --git a/atari/schedule.h b/atari/schedule.h
new file mode 100644
index 000000000..0ca3f910a
--- /dev/null
+++ b/atari/schedule.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2008 Vincent Sanders <vince@simtec.co.uk>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NS_SCHEDULE_H
+#define NS_SCHEDULE_H
+
+void list_schedule(void);
+int schedule_run(void);
+
+#endif
diff --git a/atari/scripts/mkpkg.sh b/atari/scripts/mkpkg.sh
new file mode 100644
index 000000000..b056bcded
--- /dev/null
+++ b/atari/scripts/mkpkg.sh
@@ -0,0 +1,223 @@
+#!/bin/bash
+
+# this is an small build script to create an package for nsgem
+# invoke: mkpkg.sh [-s,-d,-8,-fonts]
+#
+# Parameters:
+#
+# -8
+# Description: The package will be build for 8.3 filesystems
+# This also defines the -fonts parameter
+#
+# -fonts
+# Description: The package will include the DejaVu fonts package
+# ( 8.3 compatible names )
+#
+# -fpath
+# Description: Set path to dejavu Fonts
+#
+# -s (srcpath)
+# Description: use it like: -s "path to netsurf root" to configure from which
+# directory the package files are taken.
+# The Path must have trailing slash!
+#
+# -d (dstpath)
+# Description: use it like: -d "path to dir where the package will be placed"
+# to configure the output path of this script.
+# The path mus have trailing slash!
+#
+
+# config variable, set default values
+src="/f/netsurf/netsurf/"
+dst=$src"atari/pkg/"
+shortfs=0
+inc_short_fonts=0
+font_src="/usr/share/fonts/truetype/ttf-dejavu/"
+framebuffer=0
+
+while [ "$1" != "" ] # When there are arguments...
+do # Process the next one
+ case $1 # Look at $1
+ in
+ -8)
+ shortfs="1"
+ shift
+ ;;
+
+ -fonts)
+ inc_short_fonts="1"
+ shift
+ ;;
+
+ -fpath)
+ shift
+ font_src=$1
+ shift
+ ;;
+
+ -d)
+ shift
+ dst=$1
+ shift
+ ;;
+
+ -s)
+ shift
+ src=$1
+ shift
+ ;;
+
+ *) echo "Option [$1] not one of [-8,-fonts,-d,-s,-fpath]";
+ exit;;
+
+ esac
+done
+
+echo "Building from: "$src
+echo "Building in: "$dst
+echo "Building for short fs: "$shortfs
+
+if [ "$shortfs" = "1" ]
+then
+ inc_short_fonts=1
+fi
+
+if [ -d "$font_src" ]
+then
+ echo "Found fonts in $font_src"
+else
+ echo "Error: TTF Fonts not found ($font_src)!"
+ exit 0
+fi
+
+set -o verbose
+rm $dst -r
+mkdir $dst
+cp $src"ns.prg" $dst
+chmod +x $dst"ns.prg"
+strip $dst"ns.prg"
+
+cp $src"atari/res/" $dst -rL
+cp $src"\!NetSurf/Resources/AdBlock,f79" $dst"res/adblock.css" -rL
+cp $src"\!NetSurf/Resources/CSS,f79" $dst"res/default.css" -rL
+cp $src"\!NetSurf/Resources/CSS,f79" $dst"res/quirks.css" -rL
+cp $src"\!NetSurf/Resources/SearchEngines" $dst"res/search" -rL
+cp $src"\!NetSurf/Resources/ca-bundle" $dst"res/cabundle" -rL
+cp $src"\!NetSurf/Resources/en/Messages" $dst"res/messages" -rL
+
+#remove uneeded files:
+rm $dst"res/netsurf.rsm"
+rm $dst"res/netsurf.rsh"
+
+
+if [ "$inc_short_fonts" = "1" ]
+then
+ mkdir $dst"res/fonts"
+ cp $font_src"DejaVuSans.ttf" $dst"res/fonts/ss.ttf"
+ cp $font_src"DejaVuSans-Bold.ttf" $dst"res/fonts/ssb.ttf"
+ cp $font_src"DejaVuSans-Oblique.ttf" $dst"res/fonts/ssi.ttf"
+ cp $font_src"DejaVuSans-BoldOblique.ttf" $dst"res/fonts/ssib.ttf"
+ cp $font_src"DejaVuSansMono.ttf" $dst"res/fonts/mono.ttf"
+ cp $font_src"DejaVuSansMono-Bold.ttf" $dst"res/fonts/monob.ttf"
+ cp $font_src"DejaVuSansMono-Oblique.ttf" $dst"res/fonts/cursive.ttf"
+ cp $font_src"DejaVuSerif.ttf" $dst"res/fonts/s.ttf"
+ cp $font_src"DejaVuSerifCondensed-Bold.ttf" $dst"res/fonts/fantasy.ttf"
+fi
+
+#rename long filenames for short mode:
+if [ "$shortfs" = "1" ]
+then
+ mv $dst"res/SearchEngines" $dst"res/Search"
+ mv $dst"res/ca-bundle" $dst"res/ca"
+fi
+
+#create an simple startup script:
+if [ "$framebuffer" = "1" ]
+then
+echo "NETSURFRES=./res/
+export NETSURFRES
+./nsfb.prg -v file:///f/" > $dst"ns.sh"
+chmod +x $dst"ns.sh"
+fi
+
+echo "
+atari_screen_driver:vdi
+atari_font_driver:freetype
+homepage_url:file:///./
+http_proxy:0
+http_proxy_host:
+http_proxy_port:8123
+http_proxy_auth:0
+http_proxy_auth_user:
+http_proxy_auth_pass:
+suppress_curl_debug:1
+font_size:120
+font_min_size:80
+#font_sans:Sans
+#font_serif:Serif
+#font_mono:Monospace
+#font_cursive:Serif
+#font_fantasy:Serif
+accept_language:
+accept_charset:
+memory_cache_size:204800
+disc_cache_age:28
+block_advertisements:0
+minimum_gif_delay:0
+send_referer:1
+animate_images:1
+expire_url:28
+#font_default:1
+ca_bundle:./res/cabundle
+ca_path:./res/certs
+cookie_file:./res/Cookies
+cookie_jar:./res/Cookies
+search_url_bar:0
+search_provider:0
+url_suggestion:1
+window_x:0
+window_y:0
+window_width:0
+window_height:0
+window_screen_width:0
+window_screen_height:0
+scale:100
+incremental_reflow:1
+min_reflow_period:25
+tree_icons_dir:./res/icons
+core_select_menu:1
+max_fetchers:16
+max_fetchers_per_host:2
+max_cached_fetch_handles:6
+target_blank:1
+margin_top:10
+margin_bottom:10
+margin_left:10
+margin_right:10
+export_scale:70
+suppress_images:0
+remove_backgrounds:0
+enable_loosening:1
+enable_PDF_compression:1
+enable_PDF_password:0
+render_resample:0
+downloads_clear:0
+request_overwrite:1
+downloads_directory:./
+url_file:./res/URLs
+button_type:2
+disable_popups:0
+disable_plugins:0
+history_age:0
+hover_urls:0
+focus_new:0
+new_blank:0
+hotlist_path:./res/Hotlist
+current_theme:0
+" > $dst"Choices"
+
+cd $dst
+tar cvf - ./* | gzip -c > ns.tar.gz
+
+echo
+exit 0
diff --git a/atari/slider.c b/atari/slider.c
new file mode 100644
index 000000000..37eead414
--- /dev/null
+++ b/atari/slider.c
@@ -0,0 +1,131 @@
+/*
+ * 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 "atari/slider.h"
+
+long inline slider_pages( long content_dim, long workarea_dim )
+{
+ long ret;
+ ret = (long)ceil( (float)content_dim / (float)workarea_dim );
+ if( ret <= 0 )
+ ret = 1;
+ return( ret );
+}
+
+float inline slider_pages_dec( long content_dim, long workarea_dim )
+{
+ float ret;
+ ret = (float)content_dim / (float)workarea_dim );
+ if( ret <= 0 )
+ ret = 1;
+ return( ret );
+}
+
+
+int slider_gem_size( long content_dim, long workarea_dim )
+{
+ int ret;
+ int pages = slider_pages(content_dim, workarea_dim);
+ if( pages <= 0 )
+ return 1;
+ ret = 1000 / pages;
+ if( ret <= 0 )
+ ret = 1;
+ return( ret );
+}
+
+
+int slider_pos_to_gem_pos( long content_dim, long workarea_dim, long slider_pos )
+{
+ int ret;
+ int spos = slider_max_pos( content_dim, workarea_dim );
+ if( spos < 1 )
+ return( 0 );
+ float x = (float)1000 / spos;
+ if(content_dim >= 1000)
+ ret = (int)( x * slider_pos );
+ else
+ ret = (int)ceilf( (float)x * slider_pos );
+ return( max(0, ret) );
+}
+
+
+long slider_gem_pos_to_pos( long content_dim, long workarea_dim, int slider_pos )
+{
+ long ret;
+ int nmax = slider_max_pos( content_dim, workarea_dim );
+ float x = (float)1000 / nmax;
+ if(content_dim >= 1000)
+ ret = (int) ( (float) slider_pos * x);
+ else
+ ret = (int) ceilf( (float)slider_pos * x );
+ return( max(0, ret) );
+}
+
+
+long inline slider_gem_size_to_res( long workarea_dim, int gem_size )
+{
+ /* subtract [<-] and [->] buttons (16*2) from workarea: */
+ int factor = 1000 / (workarea_dim - 16*2);
+ return( max(1, gem_size / factor) );
+}
+
+
+long slider_gem_pos_to_res( long content_dim, long workarea_dim, int gem_pos )
+{
+ /* subtract size of boxchar: */
+ int room = workarea_dim - 16 * 2 - slider_gem_size_to_res(workarea_dim, slider_gem_sz );
+
+ /*
+ 1. Berechnen welchem Prozentsatz die GEM Position entspricht:
+ 1000 = Grundwert
+ gem_pos = Prozentwert
+ Prozentsatz = ?
+ Rechnung: Prozentwert * 100 / 1000
+ Gekürzt: Prozentwert / 10
+ p_calc = der Prozentsatz / 100 -> fuer vereinfachte nutzung
+ */
+ /* float p_gem = (float)gem_pos / 10; */
+ float p_calc = (float)gem_pos / 1000;
+
+ /*
+ 2. Berechnen welchem Pixel der Prozentsatz entspricht
+ room = Grundwert
+ p_gem = Prozentsatz
+ Prozentwert = ?
+ Rechnung = G * p / 100
+ Anmerkung: es wird p_calc verwendet, da praktischer...
+ */
+ int pixel = (float)((float)room * p_calc)+0.5;
+
+ return( pixel );
+}
+
+
+/*
+
+Not implemented
+
+long slider_pos_to_res( long content_dim, long workarea_dim, int pos )
+{
+ long max_pos = slider_max_pos( content_dim, workarea_dim );
+ return( -1 );
+}
+ */
+
+
diff --git a/atari/slider.h b/atari/slider.h
new file mode 100644
index 000000000..54aff43c8
--- /dev/null
+++ b/atari/slider.h
@@ -0,0 +1,57 @@
+/*
+ * 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_SLIDER_H_INCLUDED
+#define NS_SLIDER_H_INCLUDED
+
+/* -------------------------------------------------------------------------- */
+/* Slider Interface: */
+/* -------------------------------------------------------------------------- */
+
+#define BR_SCROLLBAR_SZ 16
+
+/* Calculate how many pixel an specific page of the content contains */
+#define SLIDER_PIXELS_ON_PAGE( long content_dim, long workarea_dim, long page )\
+ min( workarea_dim, content_dim - page * workarea_dim)
+
+/* Returns max internal slider pos, counting from zero */
+#define SLIDER_MAX_POS(content_dim, workarea_dim) max( 0, content_dim - workarea_dim)
+
+/* Calculate the number of content-"pages" for window size */
+long inline slider_pages( long content_dim, long workarea_dim );
+float inline slider_pages_dec( long content_dim, long workarea_dim )
+
+/* Convert content size into gem slider size ( 0 - 1000 ) */
+int inline slider_gem_size( long content_dim, long workarea_dim );
+
+/* convert internal slider position to gem slider position */
+int slider_pos_to_gem_pos( long content_dim, long workarea_dim, long slider_pos );
+
+/* convert gem slider pos to "internal" pos system */
+long slider_gem_pos_to_pos( long content_dim, long workarea_dim, int slider_pos );
+
+/* Calculate the gem slider mover size into pixel size */
+long slider_gem_size_to_res( long workarea_dim, int gem_size );
+
+/* Convert the gem Slider pos to an pixel value */
+long slider_gem_pos_to_res( long content_dim, long workarea_dim, int gem_pos );
+
+
+
+
+#endif
diff --git a/atari/statusbar.c b/atari/statusbar.c
new file mode 100644
index 000000000..d0f3e8e12
--- /dev/null
+++ b/atari/statusbar.c
@@ -0,0 +1,178 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <windom.h>
+#include <assert.h>
+#include <math.h>
+
+#include "utils/log.h"
+#include "desktop/gui.h"
+#include "desktop/history_core.h"
+#include "desktop/netsurf.h"
+#include "desktop/browser.h"
+#include "desktop/mouse.h"
+#include "desktop/plotters.h"
+
+#include "atari/gui.h"
+#include "atari/statusbar.h"
+#include "atari/browser_win.h"
+#include "atari/misc.h"
+#include "atari/global_evnt.h"
+#include "atari/res/netsurf.rsh"
+#include "atari/plot/plotter.h"
+
+extern short vdih;
+
+static
+void __CDECL evnt_sb_redraw( COMPONENT *c, long buff[8] )
+{
+ struct gui_window * gw = (struct gui_window *)mt_CompDataSearch(&app, c, CDT_OWNER);
+ CMP_STATUSBAR sb = gw->root->statusbar;
+ LGRECT work, lclip;
+ short pxy[8], d, pxyclip[4];
+
+ mt_CompGetLGrect(&app, sb->comp, WF_WORKXYWH, &work);
+ lclip = work;
+ if ( !rc_lintersect( (LGRECT*)&buff[4], &lclip ) ) return;
+
+ vsf_interior( vdih, FIS_SOLID );
+ vsl_color( vdih, BLACK );
+ vsl_type( vdih, 1);
+ vsl_width( vdih, 1 );
+ vst_color(vdih, BLACK);
+ vst_height( vdih, 10, &pxy[0], &pxy[1], &pxy[2], &pxy[3] );
+ vst_arbpt( vdih, 9, &pxy[0], &pxy[1], &pxy[2], &pxy[3] );
+ vst_alignment(vdih, 0, 5, &d, &d );
+ vst_effects( vdih, 0 );
+
+ pxyclip[0] = lclip.g_x;
+ pxyclip[1] = lclip.g_y;
+ pxyclip[2] = lclip.g_x + lclip.g_w;
+ pxyclip[3] = lclip.g_y + lclip.g_h;
+ vs_clip(vdih, 1, (short*)&pxyclip );
+ vswr_mode( vdih, MD_REPLACE );
+
+ if( lclip.g_y <= work.g_y ) {
+ pxy[0] = work.g_x;
+ pxy[1] = work.g_y;
+ pxy[2] = MIN( work.g_x + work.g_w, lclip.g_x + lclip.g_w );
+ pxy[3] = work.g_y;
+ v_pline( vdih, 2, (short*)&pxy );
+ }
+
+ vsf_color( vdih, LWHITE);
+ pxy[0] = work.g_x;
+ pxy[1] = work.g_y+1;
+ pxy[2] = work.g_x + work.g_w;
+ pxy[3] = work.g_y + work.g_h-1;
+ v_bar( vdih, pxy );
+
+ vswr_mode( vdih, MD_TRANS );
+ v_gtext( vdih, work.g_x + 2, work.g_y + 5, (char*)&sb->text );
+
+ vswr_mode( vdih, MD_REPLACE );
+
+ pxy[0] = work.g_x + work.g_w - MOVER_WH;
+ pxy[1] = work.g_y + 1;
+ pxy[2] = work.g_x + work.g_w;
+ pxy[3] = work.g_y + work.g_h-1;
+ v_bar( vdih, pxy );
+
+ pxy[0] = work.g_x + work.g_w - MOVER_WH;
+ pxy[1] = work.g_y + work.g_h;
+ pxy[2] = work.g_x + work.g_w - MOVER_WH;
+ pxy[3] = work.g_y + work.g_h - MOVER_WH;
+ v_pline( vdih, 2, (short*)&pxy );
+
+ vs_clip(vdih, 0, (short*)&pxyclip );
+
+}
+
+static void __CDECL evnt_sb_click( COMPONENT *c, long buff[8] )
+{
+ short sbuff[8], mx, my;
+ LGRECT work;
+ mt_CompGetLGrect(&app, c, WF_WORKXYWH, &work);
+ if( evnt.mx >= work.g_x + (work.g_w - MOVER_WH) && evnt.mx <= work.g_x + work.g_w &&
+ evnt.my >= work.g_y + (work.g_h - MOVER_WH) && evnt.my <= work.g_y + work.g_h ) {
+ /* click into the mover region */
+ struct gui_window * g;
+ for( g = window_list; g; g=g->next ) {
+ if( g->root->statusbar->comp == c ) {
+ sbuff[0] = WM_SIZED;
+ sbuff[1] = (short)buff[0];
+ sbuff[2] = 0;
+ sbuff[3] = g->root->handle->handle;
+ sbuff[4] = g->root->loc.g_x;
+ sbuff[5] = g->root->loc.g_y;
+ sbuff[6] = g->root->loc.g_w;
+ sbuff[7] = g->root->loc.g_h;
+ evnt_window_resize( g->root->handle, sbuff );
+ }
+ }
+ }
+}
+
+CMP_STATUSBAR sb_create( struct gui_window * gw )
+{
+ CMP_STATUSBAR s = malloc( sizeof(struct s_statusbar) );
+ s->comp = (COMPONENT*)mt_CompCreate(&app, CLT_HORIZONTAL, STATUSBAR_HEIGHT, 0);
+ s->comp->rect.g_h = STATUSBAR_HEIGHT;
+ s->comp->bounds.max_height = STATUSBAR_HEIGHT;
+ mt_CompDataAttach( &app, s->comp, CDT_OWNER, gw );
+ mt_CompEvntAttach( &app, s->comp, WM_REDRAW, evnt_sb_redraw );
+ mt_CompEvntAttach( &app, s->comp, WM_XBUTTON, evnt_sb_click );
+ strncpy( (char*)&s->text, "  ", 254 );
+ return( s );
+}
+
+void sb_destroy( CMP_STATUSBAR s )
+{
+ LOG(("%s\n", __FUNCTION__ ));
+ if( s ) {
+ if( s->comp ){
+ mt_CompDelete( &app, s->comp );
+ }
+ free( s );
+ }
+}
+
+void sb_set_text( struct gui_window * gw , char * text )
+{
+
+ if( gw->root == NULL )
+ return;
+ CMP_STATUSBAR sb = gw->root->statusbar;
+ LGRECT work;
+
+ if( sb == NULL || gw->browser->attached == false )
+ return;
+
+ strncpy( (char*)&sb->text, text, 254 );
+ mt_CompGetLGrect(&app, sb->comp, WF_WORKXYWH, &work);
+ ApplWrite( _AESapid, WM_REDRAW, gw->root->handle->handle,
+ work.g_x, work.g_y, work.g_w, work.g_h );
+}
diff --git a/atari/statusbar.h b/atari/statusbar.h
new file mode 100644
index 000000000..2c8df3dae
--- /dev/null
+++ b/atari/statusbar.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_STATUSBAR
+#define NS_ATARI_STATUSBAR
+
+CMP_STATUSBAR sb_create( struct gui_window * gw );
+void sb_destroy( CMP_STATUSBAR s );
+void sb_set_text( struct gui_window * gw, char * text );
+#endif
diff --git a/atari/thumbnail.c b/atari/thumbnail.c
new file mode 100644
index 000000000..d267271bf
--- /dev/null
+++ b/atari/thumbnail.c
@@ -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/>.
+ */
+
+#include "desktop/browser.h"
+
+bool thumbnail_create(struct hlcache_handle *content, struct bitmap *bitmap,
+ const char *url)
+{
+ return false;
+}
diff --git a/atari/toolbar.c b/atari/toolbar.c
new file mode 100644
index 000000000..5231f7da7
--- /dev/null
+++ b/atari/toolbar.c
@@ -0,0 +1,772 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <windom.h>
+#include <cflib.h>
+#include <assert.h>
+#include <math.h>
+
+#include "utils/log.h"
+#include "desktop/gui.h"
+#include "desktop/history_core.h"
+#include "desktop/netsurf.h"
+#include "desktop/browser.h"
+#include "desktop/mouse.h"
+#include "desktop/plotters.h"
+#include "atari/clipboard.h"
+#include "atari/gui.h"
+#include "atari/toolbar.h"
+#include "atari/browser_win.h"
+#include "atari/clipboard.h"
+#include "atari/misc.h"
+#include "atari/global_evnt.h"
+#include "atari/res/netsurf.rsh"
+#include "atari/plot/plotter.h"
+
+extern char * cfg_homepage_url;
+extern short vdih;
+extern void * h_gem_rsrc;
+
+/* prototypes & order for button widgets: */
+static struct s_tb_button tb_buttons[] =
+{
+ { TOOLBAR_BT_BACK, tb_back_click, NULL },
+ { TOOLBAR_BT_HOME, tb_home_click, NULL },
+ { TOOLBAR_BT_FORWARD, tb_forward_click, NULL },
+ { TOOLBAR_BT_RELOAD, tb_reload_click, NULL },
+ { TOOLBAR_BT_STOP, tb_stop_click, NULL },
+ { 0, NULL, NULL }
+};
+
+static OBJECT * throbber_form = NULL;
+
+
+static void __CDECL button_redraw( COMPONENT *c, long buff[8])
+{
+ OBJECT *tree = (OBJECT*)mt_CompDataSearch( &app, c, CDT_OBJECT );
+ struct gui_window * gw = mt_CompDataSearch( &app, c, CDT_OWNER );
+ LGRECT work,clip;
+ short pxy[4];
+
+ mt_CompGetLGrect(&app, c, WF_WORKXYWH, &work);
+ clip = work;
+ if ( !rc_lintersect( (LGRECT*)&buff[4], &clip ) ) return;
+
+ pxy[0] = clip.g_x;
+ pxy[1] = clip.g_y;
+ pxy[2] = clip.g_w + clip.g_x;
+ pxy[3] = clip.g_h + clip.g_y;
+
+ vs_clip( vdih, 1, (short*)&pxy );
+
+ tree->ob_x = work.g_x+1;
+ tree->ob_y = work.g_y+2;
+ tree->ob_width = work.g_w;
+ tree->ob_height = work.g_h;
+ vsf_interior( vdih , 1 );
+ vsf_color( vdih, LWHITE );
+ pxy[0] = (short)buff[4];
+ pxy[1] = (short)buff[5];
+ pxy[2] = (short)buff[4] + buff[6];
+ pxy[3] = MIN( (short)buff[5] + buff[7], work.g_y + work.g_h - 2);
+ vswr_mode( vdih, MD_REPLACE);
+ v_bar( vdih, (short*)&pxy );
+ mt_objc_draw( tree, 0, 8, clip.g_x, clip.g_y, clip.g_w, clip.g_h, app.aes_global );
+ if( gw->root->toolbar->buttons[0].comp == c && work.g_x == buff[4] ){
+ vsl_color( vdih, LWHITE );
+ pxy[0] = (short)buff[4];
+ pxy[1] = (short)buff[5];
+ pxy[2] = (short)buff[4];
+ pxy[3] = (short)buff[5] + buff[7];
+ v_pline( vdih, 2, (short*) pxy );
+ }
+ vs_clip( vdih, 0, (short*)&clip );
+}
+
+static void __CDECL button_enable( COMPONENT *c, long buff[8])
+{
+ ((OBJECT*)mt_CompDataSearch(&app, c, CDT_OBJECT))->ob_state &= ~OS_DISABLED;
+}
+
+static void __CDECL button_disable( COMPONENT *c, long buff[8])
+{
+ ((OBJECT*)mt_CompDataSearch(&app, c, CDT_OBJECT))->ob_state |= OS_DISABLED;
+}
+
+static void __CDECL button_click( COMPONENT *c, long buff[8])
+{
+ int i = 0;
+ struct gui_window * gw = (struct gui_window *)mt_CompDataSearch(&app, c, CDT_OWNER);
+ assert( gw );
+ while( i < gw->root->toolbar->btcnt ) {
+ if(c == gw->root->toolbar->buttons[i].comp ) {
+ gw->root->toolbar->buttons[i].cb_click( gw );
+ break;
+ }
+ i++;
+ }
+}
+
+static struct s_tb_button * find_button( struct gui_window * gw, int rsc_id )
+{
+ int i = 0;
+ while( i < gw->root->toolbar->btcnt ) {
+ if( gw->root->toolbar->buttons[i].rsc_id == rsc_id ) {
+ return( &gw->root->toolbar->buttons[i] );
+ }
+ i++;
+ }
+}
+
+
+static COMPONENT *button_create( OBJECT *o, short type, long size, short flex )
+{
+ COMPONENT *c = mt_CompCreate( &app, type, size, flex );
+ OBJECT *oc = mt_ObjcNDup( &app, o, NULL, 1);
+ oc->ob_next = oc->ob_head = oc->ob_tail = -1;
+ mt_CompDataAttach( &app, c, CDT_OBJECT, oc );
+ mt_CompEvntAttach( &app, c, WM_REDRAW, button_redraw );
+ mt_CompEvntAttach( &app, c, WM_XBUTTON, button_click );
+ mt_CompEvntAttach( &app, c, CM_GETFOCUS, button_enable );
+ mt_CompEvntAttach( &app, c, CM_LOSEFOCUS, button_disable );
+ return c;
+}
+
+
+static
+void __CDECL evnt_throbber_redraw( COMPONENT *c, long buff[8])
+{
+ LGRECT work, clip;
+ int idx;
+ short pxy[4];
+ struct gui_window * gw = (struct gui_window *)mt_CompDataSearch(&app, c, CDT_OWNER);
+ idx = gw->root->toolbar->throbber.index+1;
+ mt_CompGetLGrect(&app, c, WF_WORKXYWH, &work);
+ clip = work;
+ if ( !rc_lintersect( (LGRECT*)&buff[4], &clip ) ) return;
+
+ vsf_interior( vdih , 1 );
+ vsf_color( vdih, LWHITE );
+ pxy[0] = (short)buff[4];
+ pxy[1] = (short)buff[5];
+ pxy[2] = (short)buff[4] + buff[6]-1;
+ pxy[3] = (short)buff[5] + buff[7]-2;
+ v_bar( vdih, (short*)&pxy );
+
+ if( throbber_form != NULL ) {
+ throbber_form[idx].ob_x = work.g_x+1;
+ throbber_form[idx].ob_y = work.g_y+4;
+ mt_objc_draw( throbber_form, idx, 8, clip.g_x, clip.g_y, clip.g_w, clip.g_h, app.aes_global );
+ }
+}
+
+static
+void __CDECL evnt_url_redraw( COMPONENT *c, long buff[8] )
+{
+ LGRECT work, clip;
+ short pxy[10];
+ short i,d;
+ short mchars, width, cs;
+ struct gui_window * gw = (struct gui_window *)mt_CompDataSearch(&app, c, CDT_OWNER);
+ assert( gw != NULL );
+ assert( gw->browser != NULL );
+ assert( gw->root != NULL );
+ assert( gw->browser->bw != NULL );
+ short start = gw->root->toolbar->url.scrollx;
+
+ mt_CompGetLGrect(&app, c, WF_WORKXYWH, &work);
+ clip = work;
+ if ( !rc_lintersect( (LGRECT*)&buff[4], &clip ) ) return;
+
+ pxy[0] = clip.g_x;
+ pxy[1] = clip.g_y;
+ pxy[2] = clip.g_w + clip.g_x;
+ pxy[3] = clip.g_h + clip.g_y;
+ vs_clip( vdih, 1, (short*)&pxy );
+
+ width = work.g_w-6; /* subtract 6px -> 3px padding around text on each side */
+ cs = gw->root->toolbar->url.char_size;
+ mchars = (width / cs);
+ char textcpy[mchars+3];
+ memset(&textcpy, 0, mchars + 3 );
+
+ vswr_mode( vdih, MD_REPLACE);
+ vsf_perimeter( vdih, 0 );
+ vsf_interior( vdih , 1 );
+ vsf_color( vdih, LWHITE );
+ vst_arbpt( vdih, 10, &pxy[0], &pxy[1], &pxy[2], &pxy[3] );
+ vst_alignment(vdih, 0, 5, &d, &d );
+ vst_effects( vdih, 0 );
+
+ /* gray the whole component: */
+
+ pxy[0] = work.g_x;
+ pxy[1] = work.g_y;
+ pxy[2] = work.g_x + work.g_w;
+ pxy[3] = work.g_y + work.g_h-2;
+ v_bar( vdih, (short*)&pxy );
+
+ /* draw outer line, left top: */
+ pxy[0] = work.g_x + 2;
+ pxy[1] = work.g_y + ((TOOLBAR_HEIGHT - URLBOX_HEIGHT)/2);
+ /* right, top: */
+ pxy[2] = work.g_x + work.g_w - 4;
+ pxy[3] = work.g_y + ((TOOLBAR_HEIGHT - URLBOX_HEIGHT)/2);
+ /* right, bottom: */
+ pxy[4] = work.g_x + work.g_w - 4;
+ pxy[5] = work.g_y + ((TOOLBAR_HEIGHT - URLBOX_HEIGHT)/2) + URLBOX_HEIGHT;
+ /* left, bottom: */
+ pxy[6] = work.g_x + 2;
+ pxy[7] = work.g_y + ((TOOLBAR_HEIGHT - URLBOX_HEIGHT)/2) + URLBOX_HEIGHT;
+ /* left, top again: */
+ pxy[8] = work.g_x + 2;
+ pxy[9] = work.g_y + ((TOOLBAR_HEIGHT - URLBOX_HEIGHT)/2);
+ vsf_interior( vdih, FIS_SOLID );
+ vsf_style( vdih, 1);
+ vsl_color( vdih, BLACK);
+ v_pline( vdih, 5, pxy );
+
+ /* draw white txt box: */
+ pxy[0] = pxy[0] + 1;
+ pxy[1] = pxy[1] + ((TOOLBAR_HEIGHT - URLBOX_HEIGHT)/2) - 1;
+ pxy[2] = pxy[2] - 1;
+ pxy[3] = work.g_y + ((TOOLBAR_HEIGHT - URLBOX_HEIGHT)/2) + URLBOX_HEIGHT ;
+ vsf_color( vdih, WHITE);
+ v_bar( vdih, pxy );
+ if( strlen(gw->root->toolbar->url.text) > 0 )
+ strncpy( (char*)&textcpy, (char*)&gw->root->toolbar->url.text[start], mchars );
+ else
+ strcpy( (char*)&textcpy, " " );
+
+ vst_color( vdih, BLACK );
+ v_gtext( vdih, work.g_x + 3, work.g_y + ((TOOLBAR_HEIGHT - URLBOX_HEIGHT)/2) + 2, (char*)&textcpy );
+
+ if( window_url_widget_has_focus( gw ) ) {
+ /* draw caret: */
+ pxy[0] = 3 + work.g_x + ((gw->root->toolbar->url.caret_pos - gw->root->toolbar->url.scrollx) * cs);
+ pxy[1] = pxy[1] + 1;
+ pxy[2] = 3 + work.g_x + ((gw->root->toolbar->url.caret_pos - gw->root->toolbar->url.scrollx) * cs);
+ pxy[3] = pxy[3] - 1 ;
+ v_pline( vdih, 2, pxy );
+ /* draw selection: */
+ if( gw->root->toolbar->url.selection_len != 0 ) {
+ vswr_mode( vdih, MD_XOR);
+ vsl_color( vdih, BLACK);
+ pxy[0] = 3 + work.g_x + ((gw->root->toolbar->url.caret_pos - gw->root->toolbar->url.scrollx) * cs);
+ pxy[2] = pxy[0] + ( gw->root->toolbar->url.selection_len * cs);
+ v_bar( vdih, pxy );
+ vswr_mode( vdih, MD_REPLACE );
+ }
+ }
+
+ vs_clip( vdih, 0, (short*)&pxy );
+}
+
+static
+void __CDECL evnt_url_click( COMPONENT *c, long buff[8] )
+{
+ LGRECT work;
+ short pxy[4];
+ short mx, my, mb, kstat;
+ int old;
+ graf_mkstate( &mx, &my, &mb, &kstat );
+ struct gui_window * gw = (struct gui_window *)mt_CompDataSearch(&app, c, CDT_OWNER);
+ assert( gw != NULL );
+ CMP_TOOLBAR tb = gw->root->toolbar;
+ mt_CompGetLGrect(&app, c, WF_WORKXYWH, &work);
+ mx = evnt.mx - work.g_x;
+ my = evnt.my - work.g_y;
+
+ /* TODO: reset mouse state of browser window? */
+ /* select whole text when newly focused, otherwise set caret to end of text */
+ if( !window_url_widget_has_focus(gw) ) {
+ tb_url_place_caret( gw, strlen(tb->url.text), true);
+ tb->url.selection_len = -tb->url.caret_pos;
+ window_set_focus( gw, URL_WIDGET, (void*)&tb->url );
+ } else {
+ if( mb & 1 ) {
+ /* if the button is dragging, place selection: */
+ old = tb->url.selection_len;
+ tb->url.selection_len = (tb->url.scrollx + (mx / tb->url.char_size)) - tb->url.caret_pos;
+ if(tb->url.caret_pos + tb->url.selection_len > (int)strlen(tb->url.text) )
+ tb->url.selection_len = strlen(tb->url.text) - tb->url.caret_pos;
+ if( old == tb->url.selection_len )
+ /* avoid redraw when nothing changed */
+ return;
+ } else {
+ /* TODO: recognize click + shift key */
+ tb->url.selection_len = 0;
+ tb_url_place_caret( gw, tb->url.scrollx + (mx / tb->url.char_size), true);
+ }
+ }
+
+ ApplWrite( _AESapid, WM_REDRAW, gw->root->handle->handle,
+ work.g_x, work.g_y, work.g_w, work.g_h );
+
+}
+
+static void __CDECL evnt_toolbar_redraw( COMPONENT *c, long buff[8], void *data )
+{
+ LGRECT work, clip;
+ short pxy[4];
+
+ mt_CompGetLGrect(&app, c, WF_WORKXYWH, &work);
+ clip = work;
+ if( !rc_lintersect( (LGRECT*)&buff[4], &clip ) ) return;
+
+ if( work.g_y + work.g_h != clip.g_y + clip.g_h ) return;
+
+ vswr_mode( vdih, MD_REPLACE );
+ vsl_color( vdih, BLACK );
+ vsl_type( vdih, 1 );
+ vsl_width( vdih, 1 );
+ pxy[0] = clip.g_x;
+ pxy[1] = pxy[3] = work.g_y + work.g_h-1 ;
+ pxy[2] = clip.g_x + clip.g_w;
+ v_pline( vdih, 2, (short*)&pxy );
+}
+
+
+CMP_TOOLBAR tb_create( struct gui_window * gw )
+{
+ int i;
+ OBJECT * tbut;
+
+ CMP_TOOLBAR t = malloc( sizeof(struct s_toolbar) );
+ if( t == NULL )
+ return( NULL );
+
+ t->owner = gw;
+
+ /* create the root component: */
+ t->comp = (COMPONENT*)mt_CompCreate(&app, CLT_HORIZONTAL, TOOLBAR_HEIGHT, 0);
+ t->comp->rect.g_h = TOOLBAR_HEIGHT;
+ t->comp->bounds.max_height = TOOLBAR_HEIGHT;
+ mt_CompEvntDataAdd(&app, t->comp, WM_REDRAW, evnt_toolbar_redraw, NULL, EV_BOT);
+
+ /* count buttons and add them as components: */
+ RsrcGaddr( h_gem_rsrc, R_TREE, TOOLBAR , &tbut );
+ t->btdim.g_x = 0;
+ t->btdim.g_y = 1;
+ t->btdim.g_w = 0;
+ t->btdim.g_h = TB_BUTTON_HEIGHT+1;
+ i = 0;
+ while( tb_buttons[i].rsc_id > 0 ) {
+ i++;
+ }
+ t->btcnt = i;
+ t->buttons = malloc( sizeof(struct s_tb_button) * t->btcnt );
+ for( i=0; i < t->btcnt; i++ ) {
+ t->buttons[i].rsc_id = tb_buttons[i].rsc_id;
+ t->buttons[i].cb_click = tb_buttons[i].cb_click;
+ t->buttons[i].comp = button_create( &tbut[t->buttons[i].rsc_id] , CLT_VERTICAL, TB_BUTTON_WIDTH+1, 0);
+ mt_CompDataAttach( &app, t->buttons[i].comp, CDT_OWNER, gw );
+ t->buttons[i].comp->bounds.max_width = TB_BUTTON_WIDTH+1;
+ mt_CompAttach( &app, t->comp, t->buttons[i].comp );
+ t->btdim.g_w += TB_BUTTON_WIDTH+1;
+ }
+
+ /* create the url widget: */
+ t->url.char_size = 8;
+ t->url.text = malloc( 2*URL_WIDGET_BSIZE );
+ strcpy( t->url.text, "http://" );
+ t->url.allocated = 2*URL_WIDGET_BSIZE;
+ t->url.scrollx = 0;
+ t->url.comp = (COMPONENT*)mt_CompCreate(&app, CLT_HORIZONTAL, TOOLBAR_HEIGHT, 1);
+ mt_CompEvntAttach( &app, t->url.comp, WM_REDRAW, evnt_url_redraw );
+ mt_CompEvntAttach( &app, t->url.comp, WM_XBUTTON, evnt_url_click );
+ mt_CompDataAttach( &app, t->url.comp, CDT_OWNER, gw );
+ mt_CompAttach( &app, t->comp, t->url.comp );
+
+ /* create the throbber widget: */
+ if( throbber_form == NULL ) {
+ RsrcGaddr( h_gem_rsrc, R_TREE, THROBBER , &throbber_form );
+ throbber_form->ob_x = 0;
+ throbber_form->ob_y = 0;
+ }
+ t->throbber.comp = (COMPONENT*)mt_CompCreate(&app, CLT_HORIZONTAL, TOOLBAR_HEIGHT, 0);
+ t->throbber.comp->rect.g_h = TOOLBAR_HEIGHT;
+ t->throbber.comp->rect.g_w = 32;
+ t->throbber.comp->bounds.max_height = TOOLBAR_HEIGHT;
+ t->throbber.comp->bounds.max_width = 32;
+ t->throbber.index = 0;
+ t->throbber.max_index = 7;
+ t->throbber.running = false;
+ mt_CompEvntAttach( &app, t->throbber.comp, WM_REDRAW, evnt_throbber_redraw );
+ mt_CompDataAttach( &app, t->throbber.comp, CDT_OWNER, gw );
+ mt_CompAttach( &app, t->comp, t->throbber.comp );
+
+ return( t );
+}
+
+
+void tb_destroy( CMP_TOOLBAR tb )
+{
+ int i=0;
+ while( i < tb->btcnt ) {
+ mt_ObjcFree( &app, (OBJECT*)mt_CompDataSearch(&app, tb->buttons[i].comp, CDT_OBJECT) );
+ i++;
+ }
+ free( tb->buttons );
+ if( tb->url.text != NULL )
+ free( tb->url.text );
+ mt_CompDelete( &app, tb->comp);
+ free( tb );
+}
+
+
+struct gui_window * tb_gui_window( CMP_TOOLBAR tb )
+{
+ struct gui_window * gw;
+ gw = window_list;
+ while( gw != NULL ) {
+ if( gw->root->toolbar == tb ) {
+ LOG(("found tb gw: %p (tb: %p) for tb: %p", gw, gw->root->toolbar, tb ));
+ return( gw );
+ }
+ else
+ gw = gw->next;
+ }
+ return( NULL );
+}
+
+
+void tb_update_buttons( struct gui_window * gw )
+{
+ struct s_tb_button * bt;
+ return; /* not working correctly, buttons disabled, even if it shouldn't */
+
+ bt = find_button( gw, TOOLBAR_BT_BACK );
+ if( browser_window_back_available(gw->browser->bw) ) {
+ ((OBJECT*)mt_CompDataSearch(&app, bt->comp, CDT_OBJECT))->ob_state |= OS_DISABLED;
+ } else {
+ ((OBJECT*)mt_CompDataSearch(&app, bt->comp, CDT_OBJECT))->ob_state &= ~OS_DISABLED;
+ }
+ mt_CompEvntRedraw( &app, bt->comp );
+
+ bt = find_button( gw, TOOLBAR_BT_FORWARD );
+ if( browser_window_forward_available(gw->browser->bw) ) {
+ ((OBJECT*)mt_CompDataSearch(&app, bt->comp, CDT_OBJECT))->ob_state |= OS_DISABLED;
+ } else {
+ ((OBJECT*)mt_CompDataSearch(&app, bt->comp, CDT_OBJECT))->ob_state &= ~OS_DISABLED;
+ }
+ mt_CompEvntRedraw( &app, bt->comp );
+
+ bt = find_button( gw, TOOLBAR_BT_RELOAD );
+ if( browser_window_reload_available(gw->browser->bw) ) {
+ ((OBJECT*)mt_CompDataSearch(&app, bt->comp, CDT_OBJECT))->ob_state |= OS_DISABLED;
+ } else {
+ ((OBJECT*)mt_CompDataSearch(&app, bt->comp, CDT_OBJECT))->ob_state &= ~OS_DISABLED;
+ }
+ mt_CompEvntRedraw( &app, bt->comp );
+
+ bt = find_button( gw, TOOLBAR_BT_STOP );
+ if( browser_window_stop_available(gw->browser->bw) ) {
+ ((OBJECT*)mt_CompDataSearch(&app, bt->comp, CDT_OBJECT))->ob_state |= OS_DISABLED;
+ } else {
+ ((OBJECT*)mt_CompDataSearch(&app, bt->comp, CDT_OBJECT))->ob_state &= ~OS_DISABLED;
+ }
+ mt_CompEvntRedraw( &app, bt->comp );
+
+}
+
+
+
+void tb_url_set( struct gui_window * gw, char * text )
+{
+ LGRECT work;
+ int len = strlen(text);
+ char * newtext;
+ int newsize;
+
+ if( gw->root->toolbar == NULL )
+ return;
+
+ if( gw->browser->attached == false )
+ return;
+
+ struct s_url_widget * url = &gw->root->toolbar->url;
+
+ if( len+1 > url->allocated ) {
+ newsize = (len / (URL_WIDGET_BSIZE-1))+1;
+ newtext = realloc( url->text, newsize*URL_WIDGET_BSIZE );
+ if(newtext != NULL) {
+ url->text = newtext;
+ url->allocated = newsize * URL_WIDGET_BSIZE;
+ }
+ }
+ if( len+1 < url->allocated - URL_WIDGET_BSIZE
+ && url->allocated - URL_WIDGET_BSIZE > URL_WIDGET_BSIZE*2 ) {
+ newsize = (len / (URL_WIDGET_BSIZE-1) )+1;
+ newtext = realloc( url->text, newsize*URL_WIDGET_BSIZE );
+ if(newtext != NULL) {
+ url->text = newtext;
+ url->allocated = newsize * URL_WIDGET_BSIZE;
+ }
+ }
+
+ strncpy((char*)url->text, text, url->allocated-1 );
+ url->used = MIN(len+1,url->allocated );
+ tb_url_place_caret( gw, 0, true);
+ url->scrollx = 0;
+ mt_CompGetLGrect(&app, url->comp, WF_WORKXYWH, &work);
+ ApplWrite( _AESapid, WM_REDRAW, gw->root->handle->handle,
+ (short)work.g_x, (short)work.g_y, (short)work.g_w, (short)work.g_h );
+}
+
+
+/* place the caret and adjust scrolling position */
+void tb_url_place_caret( struct gui_window * gw, int steps, bool abs)
+{
+ LGRECT work;
+ CMP_TOOLBAR tb = gw->root->toolbar;
+ assert(tb!=NULL);
+ mt_CompGetLGrect(&app, tb->url.comp, WF_WORKXYWH, &work);
+ int ws = (work.g_w / tb->url.char_size)-1; /* widget size in chars */
+ if(abs) {
+ tb->url.caret_pos = steps;
+ } else {
+ tb->url.caret_pos = tb->url.caret_pos + steps;
+ }
+ if( (int)tb->url.caret_pos > (int)strlen(tb->url.text) )
+ tb->url.caret_pos = strlen(tb->url.text);
+ if( tb->url.caret_pos > tb->url.allocated-2 )
+ tb->url.caret_pos = tb->url.allocated-2;
+ if( tb->url.caret_pos < 0)
+ tb->url.caret_pos = 0;
+
+ if( tb->url.caret_pos < tb->url.scrollx ) {
+ /* the caret has moved out of the widget to the left */
+ tb->url.scrollx -= ws;
+ }
+ if( tb->url.caret_pos > tb->url.scrollx + ws ) {
+ /* the caret has moved out of the widget to the right */
+ if(!abs)
+ tb->url.scrollx += steps;
+ else
+ tb->url.scrollx = tb->url.caret_pos - ws;
+ }
+ if(tb->url.scrollx < 0)
+ tb->url.scrollx = 0;
+}
+
+
+/* -------------------------------------------------------------------------- */
+/* Public Module event handlers: */
+/* -------------------------------------------------------------------------- */
+
+bool tb_url_input( struct gui_window * gw, short nkc )
+{
+ CMP_TOOLBAR tb = gw->root->toolbar;
+ assert(tb!=NULL);
+ LGRECT work;
+ int start = 0;
+ int i;
+ char * newtext;
+ short newsize;
+ char backup;
+ bool ctrl = (nkc & NKF_CTRL);
+ bool shift = (nkc & NKF_SHIFT);
+ bool alt = (nkc & NKF_ALT);
+ bool ret = (ctrl) ? false : true;
+ char code = (nkc & 0xFF);
+
+ assert( gw != NULL );
+ /* make sure we navigate within the root window on enter: */
+ assert( gw->parent == NULL );
+
+ if( (code == NK_LEFT) && !shift ){
+ /* TODO: recognize shift + click */
+ tb->url.selection_len = 0;
+ tb_url_place_caret( gw, -1, false );
+ }
+ else if( (code == NK_RIGHT) && !shift ) {
+ /* TODO: recognize shift + click */
+ tb->url.selection_len = 0;
+ tb_url_place_caret( gw, +1, false );
+ }
+ else if( (ctrl && code == 'C') ) {
+ if( tb->url.selection_len != 0 ) {
+ char * from;
+ char tmp[abs(tb->url.selection_len)+1];
+ int len;
+ if( tb->url.selection_len < 0 ) {
+ from = &tb->url.text[tb->url.caret_pos+tb->url.selection_len];
+ } else {
+ from = &tb->url.text[tb->url.caret_pos];
+ }
+ len = MIN( abs(tb->url.selection_len), (int)strlen(from) ) ;
+ memcpy(&tmp, from, len);
+ tmp[len] = 0;
+ int r = scrap_txt_write(&app, (char*)&tmp);
+ ret = true;
+ }
+ }
+ else if( (ctrl && code == 'V') || code == NK_INS ) {
+ char * clip = scrap_txt_read( &app );
+ if( clip != NULL ) {
+ size_t l = strlen( clip );
+ unsigned int i = 0;
+ for( i = 0; i<l; i++) {
+ tb_url_input( gw, clip[i] );
+ }
+ free( clip );
+ ret = true;
+ }
+ }
+ else if( (code == NK_DEL) && tb->url.text[tb->url.caret_pos] != 0) {
+ if( tb->url.selection_len != 0 ) {
+ if( tb->url.selection_len < 0 ) {
+ strcpy(
+ &tb->url.text[tb->url.caret_pos+tb->url.selection_len],
+ &tb->url.text[tb->url.caret_pos]
+ );
+ tb_url_place_caret( gw, tb->url.selection_len, false );
+ } else {
+ strcpy(
+ &tb->url.text[tb->url.caret_pos],
+ &tb->url.text[tb->url.caret_pos+tb->url.selection_len]
+ );
+ }
+ tb->url.used = strlen( tb->url.text ) + 1;
+ } else {
+ strcpy(
+ &tb->url.text[tb->url.caret_pos+tb->url.selection_len],
+ &tb->url.text[tb->url.caret_pos+1]
+ );
+ tb->url.used--;
+ }
+ tb->url.selection_len = 0;
+ }
+ else if( code == NK_BS ) {
+ if( tb->url.caret_pos > 0 &&
+ tb->url.selection_len != 0 ) {
+ if( tb->url.selection_len < 0 ) {
+ strcpy(&tb->url.text[tb->url.caret_pos+tb->url.selection_len], &tb->url.text[tb->url.caret_pos]);
+ tb_url_place_caret( gw, tb->url.selection_len, false );
+ } else {
+ strcpy(&tb->url.text[tb->url.caret_pos], &tb->url.text[tb->url.caret_pos+tb->url.selection_len]);
+ }
+ tb->url.used = strlen( tb->url.text ) + 1;
+ } else {
+ tb->url.text[tb->url.caret_pos-1] = 0;
+ tb->url.used--;
+ strcat(tb->url.text, &tb->url.text[tb->url.caret_pos]);
+ tb_url_place_caret( gw , -1, false );
+ }
+ tb->url.selection_len = 0;
+ }
+ else if( code == NK_ESC ) {
+ tb->url.text[0] = 0;
+ tb->url.scrollx = 0;
+ tb->url.used = 1;
+ tb_url_place_caret( gw, 0, true );
+ }
+ else if( code == NK_CLRHOME ) {
+ tb_url_place_caret( gw, 0, true );
+ }
+ else if( code == NK_M_END ) {
+ tb_url_place_caret( gw,
+ strlen((char*)&tb->url.text)-1,
+ true
+ );
+ }
+ else if( code == NK_ENTER || code == NK_RET ) {
+ tb_url_place_caret( gw, 0, true );
+ window_set_focus( gw, BROWSER, gw->browser->bw);
+ browser_window_go(gw->browser->bw, (const char*)tb->url.text, 0, true);
+ }
+ else if( code > 30 ) {
+ if( tb->url.used+1 > tb->url.allocated ){
+ newsize = ( (tb->url.used+1) / (URL_WIDGET_BSIZE-1))+1;
+ newtext = realloc(tb->url.text, newsize*URL_WIDGET_BSIZE );
+ if(newtext) {
+ tb->url.text = newtext;
+ tb->url.allocated = newsize * URL_WIDGET_BSIZE;
+ }
+ }
+ i = tb->url.caret_pos;
+ backup = tb->url.text[tb->url.caret_pos];
+ while( i < tb->url.allocated - 1) {
+ tb->url.text[i] = code;
+ if( tb->url.text[i] == (char)0 )
+ break;
+ code = backup;
+ i++;
+ backup = tb->url.text[i];
+ }
+ tb->url.used++;
+ tb->url.text[tb->url.allocated-1] = 0;
+ tb_url_place_caret( gw, +1, false );
+ tb->url.selection_len = 0;
+ } else {
+ ret = false;
+ }
+ if(tb->url.used < 1)
+ tb->url.used = 1; /* at least one byte (0) is used */
+ mt_CompGetLGrect(&app, tb->url.comp, WF_WORKXYWH, &work);
+ ApplWrite( _AESapid, WM_REDRAW, gw->root->handle->handle,
+ work.g_x, work.g_y, work.g_w, work.g_h );
+ return( ret );
+}
+
+void tb_back_click( struct gui_window * gw )
+{
+ struct browser_window *bw = gw->browser->bw;
+
+
+ if( history_back_available(bw->history) )
+ history_back(bw, bw->history);
+ tb_update_buttons(gw);
+}
+
+void tb_reload_click( struct gui_window * gw )
+{
+ browser_window_reload( gw->browser->bw, true );
+}
+
+void tb_forward_click( struct gui_window * gw )
+{
+ struct browser_window *bw = gw->browser->bw;
+
+ if (history_forward_available(bw->history))
+ history_forward(bw, bw->history);
+
+ tb_update_buttons(gw);
+}
+
+void tb_home_click( struct gui_window * gw )
+{
+ browser_window_go(gw->browser->bw, cfg_homepage_url, 0, true);
+ tb_update_buttons(gw);
+}
+
+
+void tb_stop_click( struct gui_window * gw )
+{
+ browser_window_stop( gw->browser->bw );
+}
+
diff --git a/atari/toolbar.h b/atari/toolbar.h
new file mode 100644
index 000000000..32b93f5c5
--- /dev/null
+++ b/atari/toolbar.h
@@ -0,0 +1,51 @@
+/*
+ * 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_TOOLBAR_H
+#define NS_ATARI_TOOLBAR_H
+
+CMP_TOOLBAR tb_create( struct gui_window * gw );
+void tb_destroy( CMP_TOOLBAR tb );
+
+
+static void __CDECL evnt_toolbar_redraw( COMPONENT *c, long buff[8], void *data );
+//static void __CDECL evnt_toolbar_mbutton( COMPONENT *c, long buff[8], void *data );
+static void __CDECL evnt_toolbar_resize( COMPONENT *c, long buff[8], void *data );
+
+/* report click to toolbar, relative coords : */
+void tb_click( struct gui_window * gw, short mx, short my, short mb, short kstat );
+void tb_back_click( struct gui_window * gw );
+void tb_reload_click( struct gui_window * gw );
+void tb_forward_click( struct gui_window * gw );
+void tb_home_click( struct gui_window * gw );
+void tb_stop_click( struct gui_window * gw );
+
+/* enable / disable buttons etc. */
+void tb_update_buttons( struct gui_window * gw );
+/* handles clicks on url widget: */
+void tb_url_click( struct gui_window * gw, short mx, short my, short mb, short kstat );
+/* handle keybd event while url widget has focus:*/
+bool tb_url_input( struct gui_window * gw, short keycode );
+/* place the caret and adjust scrolling position: */
+void tb_url_place_caret( struct gui_window * gw, int steps, bool abs);
+/* set the url: */
+void tb_url_set( struct gui_window * gw, char * text );
+
+struct gui_window * tb_gui_window( CMP_TOOLBAR tb );
+
+#endif
diff --git a/atari/treeview.c b/atari/treeview.c
new file mode 100644
index 000000000..55ab238f3
--- /dev/null
+++ b/atari/treeview.c
@@ -0,0 +1,220 @@
+/*
+ * 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 <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <windom.h>
+
+#include "content/urldb.h"
+#include "desktop/browser.h"
+#include "desktop/plotters.h"
+#include "desktop/textinput.h"
+#include "desktop/tree.h"
+#include "desktop/tree_url_node.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/utils.h"
+#include "atari/gui.h"
+#include "atari/treeview.h"
+
+const char tree_directory_icon_name[] = "directory.png";
+const char tree_content_icon_name[] = "content.png";
+
+static void atari_treeview_request_redraw(int x,int y,int w,int h,void *pw);
+static void atari_treeview_resized(struct tree *tree,int w,int h,void *pw);
+static void atari_treeview_scroll_visible(int y, int h, void *pw);
+static void atari_treeview_get_dimensions(int *width, int *height,void *pw);
+
+static const struct treeview_table atari_tree_callbacks = {
+ atari_treeview_request_redraw,
+ atari_treeview_resized,
+ atari_treeview_scroll_visible,
+ atari_treeview_get_dimensions
+};
+
+
+NSTREEVIEW atari_treeview_create( uint32_t flags, WINDOW *win )
+{
+ LOG(("flags: %d", flags));
+ NSTREEVIEW new = malloc(sizeof(struct atari_treeview));
+ if (new == NULL)
+ return NULL;
+ memset( new, 0, sizeof(struct atari_treeview));
+ new->tree = tree_create(flags, &atari_tree_callbacks, new);
+ if (new->tree == NULL) {
+ free(new);
+ return NULL;
+ }
+ new->window = win;
+ return(new);
+}
+
+void atari_treeview_open( NSTREEVIEW tv )
+{
+ LOG(("tree: %p", tv));
+ if( tv->window != NULL ) {
+
+ }
+}
+
+void atari_treeview_close( NSTREEVIEW tv )
+{
+ if( tv->window != NULL ) {
+
+ }
+}
+
+void atari_treeview_destroy( NSTREEVIEW tv )
+{
+ LOG(("tree: %p", tv));
+ if( tv->tree != NULL ) {
+ tree_delete(tv->tree);
+ tv->tree = NULL;
+ }
+}
+
+struct tree * atari_treeview_get_tree( NSTREEVIEW tv )
+{
+ return( tv->tree );
+}
+
+WINDOW * atari_tree_get_window( NSTREEVIEW tv )
+{
+ return( tv->window );
+}
+
+
+/**
+ * Callback to force a redraw of part of the treeview window.
+ *
+ * \param x Min X Coordinate of area to be redrawn.
+ * \param y Min Y Coordinate of area to be redrawn.
+ * \param width Width of area to be redrawn.
+ * \param height Height of area to be redrawn.
+ * \param pw The treeview object to be redrawn.
+ */
+void atari_treeview_request_redraw(int x, int y, int w, int h, void *pw)
+{
+ LOG(("tree: %p", pw));
+ if (pw != NULL) {
+ NSTREEVIEW tv = (NSTREEVIEW) pw;
+ tv->redraw.required = true;
+ }
+}
+
+/**
+ * Callback to notify us of a new overall tree size.
+ *
+ * \param tree The tree being resized.
+ * \param width The new width of the window.
+ * \param height The new height of the window.
+ * \param *pw The treeview object to be resized.
+ */
+
+void atari_treeview_resized(struct tree *tree, int width, int height, void *pw)
+{
+ LOG(("tree: %p", pw));
+ if (pw != NULL) {
+ NSTREEVIEW tv = (NSTREEVIEW) pw;
+ }
+}
+
+
+/**
+ * Callback to request that a section of the tree is scrolled into view.
+ *
+ * \param y The Y coordinate of top of the area in NS units.
+ * \param height The height of the area in NS units.
+ * \param *pw The treeview object affected.
+ */
+
+void atari_treeview_scroll_visible(int y, int height, void *pw)
+{
+ LOG(("tree: %p", pw));
+ if (pw != NULL) {
+ NSTREEVIEW tv = (NSTREEVIEW) pw;
+ }
+}
+
+/**
+ * Callback to return the tree window dimensions to the treeview system.
+ *
+ * \param *width Return the window width.
+ * \param *height Return the window height.
+ * \param *pw The treeview object to use.
+ */
+
+void atari_treeview_get_dimensions(int *width, int *height,
+ void *pw)
+{
+ LOG(("tree: %p", pw));
+ if (pw != NULL && (width != NULL || height != NULL)) {
+ NSTREEVIEW tv = (NSTREEVIEW) pw;
+ }
+}
+
+
+/**
+ * Translates a content_type to the name of a respective icon
+ *
+ * \param content_type content type
+ * \param buffer buffer for the icon name
+ */
+void tree_icon_name_from_content_type(char *buffer, content_type type)
+{
+ switch (type) {
+ case CONTENT_HTML:
+ case CONTENT_TEXTPLAIN:
+ case CONTENT_CSS:
+#if defined(WITH_MNG) || defined(WITH_PNG)
+ case CONTENT_PNG:
+#endif
+#ifdef WITH_MNG
+ case CONTENT_JNG:
+ case CONTENT_MNG:
+#endif
+#ifdef WITH_JPEG
+ case CONTENT_JPEG:
+#endif
+#ifdef WITH_GIF
+ case CONTENT_GIF:
+#endif
+#ifdef WITH_BMP
+ case CONTENT_BMP:
+ case CONTENT_ICO:
+#endif
+#ifdef WITH_SPRITE
+ case CONTENT_SPRITE:
+#endif
+#ifdef WITH_DRAW
+ case CONTENT_DRAW:
+#endif
+#ifdef WITH_ARTWORKS
+ case CONTENT_ARTWORKS:
+#endif
+#ifdef WITH_NS_SVG
+ case CONTENT_SVG:
+#endif
+ default:
+ sprintf(buffer, tree_content_icon_name);
+ break;
+ }
+}
diff --git a/atari/treeview.h b/atari/treeview.h
new file mode 100644
index 000000000..c1d35fdf0
--- /dev/null
+++ b/atari/treeview.h
@@ -0,0 +1,51 @@
+/*
+ * 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_TREEVIEW_H
+#define NS_ATARI_TREEVIEW_H
+
+#include <stdbool.h>
+#include <windom.h>
+#include "desktop/tree.h"
+#include "atari/gui.h"
+
+/* defined in front end code */
+/*
+extern const char tree_directory_icon_name[];
+extern const char tree_content_icon_name[];
+*/
+
+struct atari_treeview
+{
+ struct tree * tree;
+ WINDOW * window;
+ struct s_browser_redrw_info redraw;
+ /*tree_drag_type drag;*/
+};
+
+typedef struct atari_treeview * NSTREEVIEW;
+
+NSTREEVIEW atari_treeview_create( uint32_t flags, WINDOW * win ) ;
+void atari_treeview_destroy( NSTREEVIEW tv );
+void atari_treeview_open( NSTREEVIEW tv );
+void atari_treeview_close( NSTREEVIEW tv );
+struct tree * atari_treeview_get_tree( NSTREEVIEW tv );
+WINDOW * atari_tree_get_window( NSTREEVIEW tv );
+
+
+#endif \ No newline at end of file
diff --git a/atari/verify_ssl.c b/atari/verify_ssl.c
new file mode 100644
index 000000000..1f56e46f9
--- /dev/null
+++ b/atari/verify_ssl.c
@@ -0,0 +1,272 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <windom.h>
+
+#include "utils/errors.h"
+#include "utils/utils.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "content/urldb.h"
+#include "content/fetch.h"
+#include "atari/res/netsurf.rsh"
+#include "atari/verify_ssl.h"
+
+/*
+ todo: this file need to use the treeview api - complete rework,
+ current implementation is not used in any way.
+*/
+
+extern void * h_gem_rsrc;
+extern short vdih;
+
+
+#define CERT_INF_LINES 8
+
+static struct ssl_info_draw_param
+{
+ struct ssl_cert_info * cert_infos_n;
+ unsigned long num_certs;
+ int current;
+ int scrollx;
+ int cols;
+ int scrolly;
+ int rows; /* assumed to be 8 */
+ OBJECT * tree;
+} dp;
+
+
+static int cert_display_width( struct ssl_cert_info * cert_info )
+{
+ int l1, l2;
+ int max=0;
+ int i;
+ int add = 16; /* strlen("Issuer: "); */
+
+ l1 = strlen(cert_info->issuer) + add;
+ l2 = strlen(cert_info->subject) + add;
+ return( MAX(l1, l2) );
+}
+
+
+static void __CDECL cert_info_draw( WINDOW * win, short buf[8], void * data)
+{
+ struct ssl_info_draw_param * dp = (struct ssl_info_draw_param *)data;
+ GRECT work;
+ short pxy[4];
+ int maxchars;
+ short d, cbh, cbw;
+ int i = 0;
+ short x,y,w,h;
+ int px_ypos, px_xpos;
+ char * line = malloc(512);
+ if( line == NULL )
+ return;
+
+ LOG(("Cert info draw, win: %p, data: %p, scrollx: %d", win, data, dp->scrollx ));
+
+ WindGet( win, WF_WORKXYWH, &x, &y, &w, &h );
+ /*using static values here, as RsrcUserDraw has mem leaks & a very small stack */
+ pxy[0] = work.g_x = x + 8;
+ pxy[1] = work.g_y = y + 80;
+ pxy[2] = x + 8 + 272;
+ pxy[3] = y + 80 + 176;
+ work.g_w = 272;
+ work.g_h = 176;
+
+ maxchars = (work.g_w / 8)+1;
+ vs_clip( vdih, 1,(short*) &pxy );
+ vswr_mode( vdih, MD_REPLACE );
+ vsf_interior( vdih, 1 );
+ vsf_color( vdih, LWHITE );
+ v_bar( vdih, (short*)&pxy );
+ vst_height( vdih, 16, &d, &d, &cbw, &cbh );
+ vst_alignment(vdih, 0, 5, &d, &d );
+ vst_color( vdih, BLACK );
+ vst_effects( vdih, 0 );
+ px_ypos = px_xpos = 0;
+ for(i=0; i<CERT_INF_LINES; i++ ) {
+ switch( i ) {
+ case 0:
+ sprintf(line, "Cert Version: %d", dp->cert_infos_n[dp->current].version );
+ break;
+
+ case 1:
+ sprintf(line, "Invalid before: %s", &dp->cert_infos_n[dp->current].not_before );
+ break;
+
+ case 2:
+ sprintf(line, "Invalid after: %s", &dp->cert_infos_n[dp->current].not_after );
+ break;
+
+ case 3:
+ sprintf(line, "Signature type: %d", dp->cert_infos_n[dp->current].sig_type );
+ break;
+
+ case 4:
+ sprintf(line, "Serial: %d", dp->cert_infos_n[dp->current].serial );
+ break;
+
+ case 5:
+ sprintf(line, "Issuer: %s", &dp->cert_infos_n[dp->current].issuer );
+ break;
+
+ case 6:
+ sprintf(line, "Subject: %s", &dp->cert_infos_n[dp->current].subject );
+ break;
+
+ case 7:
+ sprintf(line, "Cert type: %d", dp->cert_infos_n[dp->current].cert_type );
+ break;
+
+ default:
+ break;
+ }
+ if( (int)strlen(line) > dp->scrollx ) {
+ if( dp->scrollx + maxchars < 511 && ( (signed int)strlen(line) - dp->scrollx) > maxchars )
+ line[dp->scrollx + maxchars] = 0;
+ v_gtext(vdih, work.g_x + 1, work.g_y + px_ypos, &line[dp->scrollx]);
+ }
+ px_ypos += cbh;
+ }
+ vst_alignment(vdih, 0, 0, &d, &d );
+ vs_clip( vdih, 0, (short*)&pxy );
+ free( line );
+}
+
+
+static void do_popup( WINDOW *win, int index, int mode, void *data)
+{
+ struct ssl_info_draw_param * dp = (struct ssl_info_draw_param *)data;
+ char * items[dp->num_certs];
+ short x, y;
+ unsigned int i;
+ int dispw;
+ LOG(("do_popup: num certs: %d", dp->num_certs));
+ for( i = 0; i<dp->num_certs; i++) {
+ items[i] = malloc( 48 );
+ strncpy(items[i], (char*)&dp->cert_infos_n[i].issuer, 46 );
+ }
+ objc_offset( FORM(win), index, &x, &y );
+ dp->current = MenuPopUp( items, x, y,
+ dp->num_certs, MIN( 3, dp->num_certs), 0,
+ P_LIST + P_WNDW + P_CHCK );
+ ObjcChange( OC_FORM, win, index, NORMAL, TRUE );
+ dp->cols = cert_display_width( &dp->cert_infos_n[dp->current] );
+ dp->rows = 8;
+ dp->scrollx = 0;
+ dp->scrolly = 0;
+
+ /* Send (!) redraw ( OC_MSG ) */
+ ObjcDrawParent( OC_FORM, FORM(win), VERIFY_BOX_DETAILS, 1, 7 | OC_MSG );
+ for( i = 0; i<dp->num_certs; i++) {
+ free( items[i] );
+ }
+}
+
+
+
+bool verify_ssl_form_do( const char * url, const struct ssl_cert_info * cert_infos_n ,
+ unsigned long num_certs )
+{
+ OBJECT *tree;
+ WINDOW * form;
+
+ bool bres = false;
+ bool cont = true;
+ int res = 0;
+ dp.cert_infos_n = (struct ssl_cert_info *)cert_infos_n;
+ dp.num_certs = num_certs;
+ dp.scrollx = 0;
+ dp.scrolly = 0;
+ dp.current = 0;
+ dp.cols = cert_display_width( &dp.cert_infos_n[dp.current] );
+ dp.rows = 8;
+ dp.tree = tree;
+
+ RsrcGaddr (h_gem_rsrc , R_TREE, VERIFY, &tree);
+ ObjcString( tree, VERIFY_LBL_HOST, (char*)url );
+ ObjcChange( OC_OBJC, tree, VERIFY_BT_ACCEPT, 0, 0 );
+ ObjcChange( OC_OBJC, tree, VERIFY_BT_REJECT, 0, 0 );
+ form = FormWindBegin( tree, (char*)"SSL Verify failed" );
+ EvntDataAdd( form, WM_REDRAW, cert_info_draw, (void*)&dp, EV_BOT );
+ /* this results in some extended objects which can not be freed: :( */
+ /* RsrcUserDraw( OC_FORM, tree, VERIFY_BOX_DETAILS, cert_info_draw,(void*)&dp ) ; */
+ ObjcAttachFormFunc( form, VERIFY_BT_NEXT_CERT, do_popup, &dp );
+ /*
+ ObjcAttachFormFunc( form, VERIFY_BT_NEXT_CERT, do_popup, &dp );
+ ObjcAttachFormFunc( form, VERIFY_BT_NEXT_CERT, do_popup, &dp );
+ */
+ while( cont ) {
+ res = FormWindDo( MU_MESAG );
+ cont = false;
+ switch( res ){
+ case VERIFY_BT_ACCEPT:
+ bres = true;
+ break;
+
+ case VERIFY_BT_NEXT_CERT:
+ /* select box clicked or dragged... */
+ cont = true;
+ break;
+
+ case VERIFY_BT_REJECT:
+ bres = false;
+ break;
+
+ case VERIFY_BT_SCROLL_D:
+ cont = true;
+ dp.scrolly += 1;
+ ObjcDrawParent( OC_FORM, form, VERIFY_BOX_DETAILS, 1, 7 | OC_MSG );
+ break;
+
+ case VERIFY_BT_SCROLL_U:
+ cont = true;
+ dp.scrolly -= 1;
+ ObjcDrawParent( OC_FORM, form, VERIFY_BOX_DETAILS, 1, 7 | OC_MSG );
+ break;
+
+ case VERIFY_BT_SCROLL_R:
+ LOG(( "scroll r!" ));
+ cont = true;
+ dp.scrollx += 1;
+ if( dp.scrollx > (dp.cols - (272 / 8 )) )
+ dp.scrollx -= 1;
+ ObjcDrawParent( OC_FORM, form, VERIFY_BOX_DETAILS, 1, 7 | OC_MSG);
+ break;
+
+ case VERIFY_BT_SCROLL_L:
+ cont = true;
+ dp.scrollx -= 1;
+ if( dp.scrollx < 0 )
+ dp.scrollx = 0;
+ ObjcDrawParent( OC_FORM, form, VERIFY_BOX_DETAILS, 1, 7 | OC_MSG );
+ break;
+
+ default:
+ break;
+ }
+ }
+ FormWindEnd( );
+ return( bres );
+}
diff --git a/atari/verify_ssl.h b/atari/verify_ssl.h
new file mode 100644
index 000000000..97716ab88
--- /dev/null
+++ b/atari/verify_ssl.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NS_VERIFY_SSL_H_INCLUDED
+#define NS_VERIFY_SSL_H_INCLUDED
+
+bool verify_ssl_form_do( const char * url, const struct ssl_cert_info * cert_infos_n , unsigned long num_certs );
+
+#endif
diff --git a/desktop/options.c b/desktop/options.c
index 5d49b9490..49a2967b0 100644
--- a/desktop/options.c
+++ b/desktop/options.c
@@ -47,6 +47,8 @@
#include "amiga/options.h"
#elif defined(nsframebuffer)
#include "framebuffer/options.h"
+#elif defined(nsatari)
+#include "atari/options.h"
#else
#define EXTRA_OPTION_DEFINE
#define EXTRA_OPTION_TABLE
diff --git a/utils/utils.h b/utils/utils.h
index f1c193bac..84322156e 100644
--- a/utils/utils.h
+++ b/utils/utils.h
@@ -35,6 +35,10 @@
#ifndef ABS
#define ABS(x) (((x)>0)?(x):(-(x)))
#endif
+#ifdef __MINT__ /* avoid using GCCs builtin min/max functions */
+#undef min
+#undef max
+#endif
#ifndef min
#define min(x,y) (((x)<(y))?(x):(y))
#endif
@@ -52,6 +56,10 @@
#define strtof(s,p) ((float)(strtod((s),(p))))
#endif
+#if !defined(ceilf) && defined(__MINT__)
+#define ceilf(x) (float)ceil((double)x)
+#endif
+
/**
* Calculate length of constant C string.
*