netsurf: branch master updated. release/3.6-159-g3b1ef78

NetSurf Browser Project (Commit Mailer) no-reply at netsurf-browser.org
Mon Jan 2 19:22:01 GMT 2017


Gitweb links:

...log http://git.netsurf-browser.org/netsurf.git/shortlog/3b1ef784fd53095213fa8b89806982567359dca4
...commit http://git.netsurf-browser.org/netsurf.git/commit/3b1ef784fd53095213fa8b89806982567359dca4
...tree http://git.netsurf-browser.org/netsurf.git/tree/3b1ef784fd53095213fa8b89806982567359dca4

The branch, master has been updated
       via  3b1ef784fd53095213fa8b89806982567359dca4 (commit)
       via  2bd8eb8c0b468799109191e63e939ea7bd69f8a1 (commit)
       via  64bb74bdafa216d4163d6b717271a9f45ac0d287 (commit)
       via  48e95ad2b3ede2b6170b635074bf0ee1010dfb39 (commit)
       via  0fafa9576e8963928c13c81524e64b624b794c98 (commit)
       via  4892497a19083cf328711f28376d16133a684353 (commit)
       via  4b7abde7b0449a3a3fe03b43533b8d0697f55e0d (commit)
       via  98f94c4bf39db60b0b686bccc84175e15214b348 (commit)
       via  e7c9b863b3d2dd8579cb2c9f80f4a20933d04315 (commit)
       via  a9cc0792a43d108e5ff61055354422a6c7218a74 (commit)
       via  dab118b6f7e9a22ed01413a2ce2fd60e4c4df97b (commit)
       via  3227ed655609e731f3d216706c524028f566f114 (commit)
       via  eb1f39fe7d80893b1f7c804eb48ec61e89f17d78 (commit)
       via  31c08f39be64f739cac727ab5a13fc513d1a61aa (commit)
       via  c40e8197c270b1600fa7b32056a2019cd83e6f3f (commit)
       via  8196f5b60241a6389ca3b76446de131a3dd2e891 (commit)
      from  eb63c1cc50847b88e598cdf0f775814a43a2799e (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=3b1ef784fd53095213fa8b89806982567359dca4
commit 3b1ef784fd53095213fa8b89806982567359dca4
Merge: eb63c1c 2bd8eb8
Author: Chris Young <chris at unsatisfactorysoftware.co.uk>
Commit: Chris Young <chris at unsatisfactorysoftware.co.uk>

    Partially implement Amiga core window
    Migrate SSL cert window to use core window
    Core window implementation has some features missing but is good enough for SSL cert
    I will improve it as I migrate the other windows.



-----------------------------------------------------------------------

Summary of changes:
 frontends/amiga/Makefile     |    2 +-
 frontends/amiga/corewindow.c |  798 ++++++++++++++++++++++++++++++++++++++++++
 frontends/amiga/corewindow.h |  155 ++++++++
 frontends/amiga/gui.c        |   33 +-
 frontends/amiga/gui.h        |   14 +-
 frontends/amiga/object.h     |    1 +
 frontends/amiga/sslcert.c    |  350 ++++++++++++++++--
 frontends/amiga/sslcert.h    |   22 +-
 frontends/amiga/tree.c       |    2 +-
 9 files changed, 1335 insertions(+), 42 deletions(-)
 create mode 100644 frontends/amiga/corewindow.c
 create mode 100644 frontends/amiga/corewindow.h

diff --git a/frontends/amiga/Makefile b/frontends/amiga/Makefile
index f3c178e..8115f2f 100644
--- a/frontends/amiga/Makefile
+++ b/frontends/amiga/Makefile
@@ -46,7 +46,7 @@ S_FRONTEND := gui.c tree.c history.c hotlist.c schedule.c file.c	\
 	stringview/stringview.c stringview/urlhistory.c rtg.c		\
 	agclass/amigaguide_class.c os3support.c font_diskfont.c		\
 	selectmenu.c hash/xxhash.c font_cache.c font_bullet.c		\
-	nsoption.c desktop-tree.c
+	nsoption.c desktop-tree.c corewindow.c
 
 # This is the final source build list
 # Note this is deliberately *not* expanded here as common and image
diff --git a/frontends/amiga/corewindow.c b/frontends/amiga/corewindow.c
new file mode 100644
index 0000000..38b980a
--- /dev/null
+++ b/frontends/amiga/corewindow.c
@@ -0,0 +1,798 @@
+/*
+ * Copyright 2017 Chris Young <chris at unsatisfactorysoftware.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/>.
+ */
+
+/**
+ * \file
+ * Amiga core window interface.
+ *
+ * Provides interface for core renderers to the Amiga Intuition drawable area.
+ *
+ * This module is an object that must be encapsulated. Client users
+ * should embed a struct ami_corewindow at the beginning of their
+ * context for this display surface, fill in relevant data and then
+ * call ami_corewindow_init()
+ *
+ * The Amiga core window structure requires the callback for draw, key and
+ * mouse operations.
+ */
+
+#include "amiga/os3support.h"
+
+#include <assert.h>
+#include <string.h>
+#include <math.h>
+
+#include "utils/log.h"
+#include "utils/utils.h"
+#include "utils/messages.h"
+#include "utils/utf8.h"
+#include "netsurf/keypress.h"
+#include "netsurf/mouse.h"
+#include "desktop/plot_style.h"
+
+#include <proto/exec.h>
+#include <proto/intuition.h>
+#include <proto/layout.h>
+#include <proto/utility.h>
+
+#include <classes/window.h>
+#include <gadgets/layout.h>
+#include <gadgets/scroller.h>
+#include <gadgets/space.h>
+#include <intuition/icclass.h>
+#include <reaction/reaction_macros.h>
+
+#include "amiga/corewindow.h"
+#include "amiga/memory.h"
+#include "amiga/misc.h"
+#include "amiga/object.h"
+#include "amiga/schedule.h"
+#include "amiga/utf8.h"
+
+static void
+ami_cw_scroller_top(struct ami_corewindow *ami_cw, ULONG *restrict x, ULONG *restrict y)
+{
+	ULONG xs = 0;
+	ULONG ys = 0;
+
+	if(ami_cw->scroll_x_visible == true) {
+		GetAttr(SCROLLER_Top, ami_cw->objects[GID_CW_HSCROLL], (ULONG *)&xs);
+	}
+
+	if(ami_cw->scroll_y_visible == true) {
+		GetAttr(SCROLLER_Top, ami_cw->objects[GID_CW_VSCROLL], (ULONG *)&ys);
+	}
+
+	*x = xs;
+	*y = ys;
+}
+
+
+/**
+ * Convert co-ordinates relative to space.gadget
+ * into document co-ordinates
+ *
+ * @param ami_cw core window
+ * @param x co-ordinate, will be updated to new x co-ordinate
+ * @param y co-ordinate, will be updated to new y co-ordinate
+ */
+static void
+ami_cw_coord_amiga_to_ns(struct ami_corewindow *ami_cw, int *restrict x, int *restrict y)
+{
+	ULONG xs = 0;
+	ULONG ys = 0;
+
+	ami_cw_scroller_top(ami_cw, &xs, &ys);
+
+	*x = *x + xs;
+	*y = *y + ys;
+}
+
+
+/* get current mouse position in the draw area, adjusted for scroll.
+ * @return true if the mouse was in the draw area and co-ordinates updated
+ */
+static bool
+ami_cw_mouse_pos(struct ami_corewindow *ami_cw, int *restrict x, int *restrict y)
+{
+	int16 xm, ym;
+	ULONG xs, ys;
+	struct IBox *bbox;
+
+	xm = ami_cw->win->MouseX;
+	ym = ami_cw->win->MouseY;
+
+	if(ami_gui_get_space_box((Object *)ami_cw->objects[GID_CW_DRAW], &bbox) != NSERROR_OK) {
+		amiga_warn_user("NoMemory", "");
+		return false;
+	}
+
+	xm -= bbox->Left;
+	ym -= bbox->Top;
+
+	ami_gui_free_space_box(bbox);
+
+	if((xm < 0) || (ym < 0) || (xm > bbox->Width) || (ym > bbox->Height))
+		return false;
+
+	ami_cw_scroller_top(ami_cw, &xs, &ys);
+
+	xm += xs;
+	ym += ys;
+	*x = xm;
+	*y = ym;
+
+	return true;
+}
+
+/* handle keypress */
+static void
+ami_cw_key(struct ami_corewindow *ami_cw, int nskey)
+{
+	ami_cw->key(ami_cw, nskey);
+
+	switch(nskey) {
+		case NS_KEY_COPY_SELECTION:
+			/* if we've copied a selection we need to clear it - style guide rules */
+			ami_cw->key(ami_cw, NS_KEY_CLEAR_SELECTION);
+		break;
+
+		/* we may need to deal with scroll-related keys here */
+	}
+}
+
+
+/**
+ * Redraw functions
+ *
+ * This is slightly over-engineered as it was taken from the main browser/old tree redraws
+ * and supports deferred drawing of rectangles and tiling
+ */
+
+/**
+ * Redraw an area of a core window
+ *
+ * \param  g   a struct ami_corewindow 
+ * \param  r  rect (in document co-ordinates)
+ */
+
+static void
+ami_cw_redraw_rect(struct ami_corewindow *ami_cw, struct rect *r)
+{
+	struct IBox *bbox;
+	ULONG pos_x, pos_y;
+	struct rect draw_rect;
+	int tile_size_x = ami_cw->gg.width;
+	int tile_size_y = ami_cw->gg.height;
+	int tile_x, tile_y, tile_w, tile_h;
+	int x = r->x0;
+	int y = r->y0;
+	int width = r->x1 - r->x0;
+	int height = r->y1 - r->y0;
+
+	struct redraw_context ctx = {
+		.interactive = true,
+		.background_images = true,
+		.plot = &amiplot
+	};
+
+	if(ami_gui_get_space_box((Object *)ami_cw->objects[GID_CW_DRAW], &bbox) != NSERROR_OK) {
+		amiga_warn_user("NoMemory", "");
+		return;
+	}
+
+	ami_cw_scroller_top(ami_cw, &pos_x, &pos_y);
+
+	glob = &ami_cw->gg;
+
+	if(x - pos_x + width > bbox->Width) width = bbox->Width - (x - pos_x);
+	if(y - pos_y + height > bbox->Height) height = bbox->Height - (y - pos_y);
+
+	if(x < pos_x) {
+		width -= pos_x - x;
+		x = pos_x;
+	}
+
+	if(y < pos_y) {
+		height -= pos_y - y;
+		y = pos_y;
+	}
+
+	for(tile_y = y; tile_y < (y + height); tile_y += tile_size_y) {
+		tile_h = tile_size_y;
+		if(((y + height) - tile_y) < tile_size_y)
+			tile_h = (y + height) - tile_y;
+
+		for(tile_x = x; tile_x < (x + width); tile_x += tile_size_x) {
+			tile_w = tile_size_x;
+			if(((x + width) - tile_x) < tile_size_x)
+				tile_w = (x + width) - tile_x;
+
+			draw_rect.x0 = tile_x; // was -
+			draw_rect.y0 = tile_y; // was -
+			draw_rect.x1 = tile_x + tile_w;
+			draw_rect.y1 = tile_y + tile_h;
+
+			ami_cw->draw(ami_cw, -tile_x, -tile_y, &draw_rect, &ctx);
+
+#ifdef __amigaos4__
+			BltBitMapTags(BLITA_SrcType, BLITT_BITMAP, 
+					BLITA_Source, ami_cw->gg.bm,
+					BLITA_SrcX, 0,
+					BLITA_SrcY, 0,
+					BLITA_DestType, BLITT_RASTPORT, 
+					BLITA_Dest, ami_cw->win->RPort,
+					BLITA_DestX, bbox->Left + tile_x - pos_x,
+					BLITA_DestY, bbox->Top + tile_y - pos_y,
+					BLITA_Width, tile_w,
+					BLITA_Height, tile_h,
+					TAG_DONE);
+#else
+			BltBitMapRastPort(ami_cw->gg.bm, 0, 0,
+					ami_cw->win->RPort, bbox->Left + tile_x - pos_x, bbox->Top + tile_y - pos_y,
+					tile_w, tile_h, 0xC0);
+#endif
+		}
+	}
+
+	ami_gui_free_space_box(bbox);
+	ami_clearclipreg(glob);
+	ami_gui_set_default_gg();
+}
+
+
+/**
+ * Draw the deferred rectangles
+ *
+ * @param draw set to false to just delete the queue
+ */
+static void ami_cw_redraw_queue(struct ami_corewindow *ami_cw, bool draw)
+{
+	struct nsObject *node;
+	struct nsObject *nnode;
+	struct rect *rect;
+	
+	if(IsMinListEmpty(ami_cw->deferred_rects)) return;
+
+	if(draw == false) {
+		LOG("Ignoring deferred box redraw queue");
+	} // else should probably show busy pointer
+
+	node = (struct nsObject *)GetHead((struct List *)ami_cw->deferred_rects);
+
+	do {
+		if(draw == true) {
+			rect = (struct rect *)node->objstruct;
+			ami_cw_redraw_rect(ami_cw, rect);
+		}
+		nnode = (struct nsObject *)GetSucc((struct Node *)node);
+		ami_memory_itempool_free(ami_cw->deferred_rects_pool, node->objstruct, sizeof(struct rect));
+		DelObjectNoFree(node);
+	} while((node = nnode));
+}
+
+static void
+ami_cw_redraw_cb(void *p)
+{
+	struct ami_corewindow *ami_cw = (struct ami_corewindow *)p;
+
+	ami_cw_redraw_queue(ami_cw, true);
+}
+
+/**
+ * Queue a redraw of a rectangle
+ *
+ * @param ami_cw the core window to redraw
+ * @param r the rectangle (in doc coords) to redraw, or NULL for full window
+ */
+
+static void
+ami_cw_redraw(struct ami_corewindow *ami_cw, const struct rect *restrict r)
+{
+	struct nsObject *nsobj;
+	struct rect *restrict deferred_rect;
+	struct rect new_rect;
+
+	if(r == NULL) {
+		struct IBox *bbox;
+		if(ami_gui_get_space_box((Object *)ami_cw->objects[GID_CW_DRAW], &bbox) != NSERROR_OK) {
+			amiga_warn_user("NoMemory", "");
+			return;
+		}
+
+		new_rect.x0 = 0;
+		new_rect.y0 = 0;
+		ami_cw_coord_amiga_to_ns(ami_cw, &new_rect.x0, &new_rect.y0);
+		new_rect.x1 = new_rect.x0 + bbox->Width;
+		new_rect.y1 = new_rect.y0 + bbox->Height;
+
+		ami_gui_free_space_box(bbox);
+
+		r = &new_rect;
+	}
+
+	if(ami_gui_window_update_box_deferred_check(ami_cw->deferred_rects, r,
+			ami_cw->deferred_rects_pool)) {
+		deferred_rect = ami_memory_itempool_alloc(ami_cw->deferred_rects_pool, sizeof(struct rect));
+		CopyMem(r, deferred_rect, sizeof(struct rect));
+		nsobj = AddObject(ami_cw->deferred_rects, AMINS_RECT);
+		nsobj->objstruct = deferred_rect;
+	} else {
+		LOG("Ignoring duplicate or subset of queued box redraw");
+	}
+	ami_schedule(1, ami_cw_redraw_cb, ami_cw);
+}
+
+static void
+ami_cw_toggle_scrollbar(struct ami_corewindow *ami_cw, bool vert, bool visible)
+{
+	Object *scroller;
+	Object *layout;
+	ULONG tag;
+
+	if(vert == true) {
+		if(visible == ami_cw->scroll_y_visible) {
+			return;
+		} else {
+			scroller = ami_cw->objects[GID_CW_VSCROLL];
+			layout = ami_cw->objects[GID_CW_VSCROLLLAYOUT];
+			tag = WINDOW_VertProp;
+			ami_cw->scroll_y_visible = visible;
+		}
+	} else {
+		if(visible == ami_cw->scroll_x_visible) {
+			return;
+		} else {
+			scroller = ami_cw->objects[GID_CW_HSCROLL];
+			layout = ami_cw->objects[GID_CW_HSCROLLLAYOUT];
+			tag = WINDOW_HorizProp;
+			ami_cw->scroll_x_visible = visible;
+		}
+	}
+
+	if(visible == true) {
+		if(ami_cw->in_border_scroll == true) {
+			SetAttrs(ami_cw->objects[GID_CW_WIN],
+				tag, 1,
+				TAG_DONE);
+		} else {
+#ifdef __amigaos4__
+			IDoMethod(layout, LM_ADDCHILD, ami_cw->win, scroller, NULL);
+#else
+			SetAttrs(layout, LAYOUT_AddChild, scroller, TAG_DONE);
+#endif
+		}
+	} else {
+		if(ami_cw->in_border_scroll == true) {
+			SetAttrs(ami_cw->objects[GID_CW_WIN],
+				tag, -1,
+				TAG_DONE);
+		} else {
+#ifdef __amigaos4__
+			IDoMethod(layout, LM_REMOVECHILD, ami_cw->win, scroller);
+#else
+			SetAttrs(layout, LAYOUT_RemoveChild, scroller, TAG_DONE);
+#endif
+		}
+	}
+
+#if 0
+	/* in-window scrollbars aren't getting hidden until the window is resized
+	 * this code should fix it, but it isn't working */
+	if(ami_cw->in_border_scroll == false) {
+		FlushLayoutDomainCache((struct Gadget *)ami_cw->objects[GID_CW_WIN]);
+		RethinkLayout((struct Gadget *)ami_cw->objects[GID_CW_WIN],
+					ami_cw->win, NULL, TRUE);
+
+		/* probably need to redraw here */
+		ami_cw_redraw(ami_cw, NULL);
+	}
+#endif
+}
+
+static void
+ami_cw_close(void *w)
+{
+	struct ami_corewindow *ami_cw = (struct ami_corewindow *)w;
+
+	ami_cw->close(ami_cw);
+}
+
+HOOKF(void, ami_cw_idcmp_hook, Object *, object, struct IntuiMessage *) 
+{
+	struct ami_corewindow *ami_cw = hook->h_Data;
+	struct IntuiWheelData *wheel;
+	ULONG gid = GetTagData( GA_ID, 0, msg->IAddress ); 
+
+	switch(msg->Class)
+	{
+		case IDCMP_IDCMPUPDATE:
+			switch(gid) 
+			{
+ 				case GID_CW_HSCROLL: 
+ 				case GID_CW_VSCROLL:
+					ami_cw_redraw(ami_cw, NULL);
+ 				break; 
+			} 
+		break;
+#ifdef __amigaos4__
+		case IDCMP_EXTENDEDMOUSE:
+			if(msg->Code == IMSGCODE_INTUIWHEELDATA)
+			{
+				wheel = (struct IntuiWheelData *)msg->IAddress;
+
+				//ami_tree_scroll(twin, (wheel->WheelX * 20), (wheel->WheelY * 20));
+			}
+		break;
+#endif
+	}
+} 
+
+
+/**
+ * Main event loop for our core window
+ *
+ * \return TRUE if window destroyed
+ */
+static BOOL
+ami_cw_event(void *w)
+{
+	struct ami_corewindow *ami_cw = (struct ami_corewindow *)w;
+
+	ULONG result;
+	ULONG storage;
+	uint16 code;
+	struct InputEvent *ie;
+	int nskey;
+	int key_state = 0;
+	struct timeval curtime;
+	int x = 0, y = 0;
+
+	while((result = RA_HandleInput(ami_cw->objects[GID_CW_WIN], &code)) != WMHI_LASTMSG) {
+		switch(result & WMHI_CLASSMASK) {
+			case WMHI_MOUSEMOVE:
+				if(ami_cw_mouse_pos(ami_cw, &x, &y)) {
+					key_state = ami_gui_get_quals(ami_cw->objects[GID_CW_WIN]);
+					ami_cw->mouse(ami_cw, ami_cw->mouse_state | key_state, x, y);
+				}
+			break;
+
+			case WMHI_MOUSEBUTTONS:
+				if(ami_cw_mouse_pos(ami_cw, &x, &y) == false)
+					break;
+
+				key_state = ami_gui_get_quals(ami_cw->objects[GID_CW_WIN]);
+
+				switch(code) {
+					case SELECTDOWN:
+						ami_cw->mouse_state = BROWSER_MOUSE_PRESS_1;
+					break;
+
+					case MIDDLEDOWN:
+						ami_cw->mouse_state = BROWSER_MOUSE_PRESS_2;
+					break;
+
+					case SELECTUP:
+						if(ami_cw->mouse_state & BROWSER_MOUSE_PRESS_1) {
+							CurrentTime((ULONG *)&curtime.tv_sec, (ULONG *)&curtime.tv_usec);
+
+							ami_cw->mouse_state = BROWSER_MOUSE_CLICK_1;
+
+							if(ami_cw->lastclick.tv_sec) {
+								if(DoubleClick(ami_cw->lastclick.tv_sec,
+											ami_cw->lastclick.tv_usec,
+											curtime.tv_sec, curtime.tv_usec))
+									ami_cw->mouse_state |= BROWSER_MOUSE_DOUBLE_CLICK;
+							}
+
+							if(ami_cw->mouse_state & BROWSER_MOUSE_DOUBLE_CLICK) {
+								ami_cw->lastclick.tv_sec = 0;
+								ami_cw->lastclick.tv_usec = 0;
+							} else {
+								ami_cw->lastclick.tv_sec = curtime.tv_sec;
+								ami_cw->lastclick.tv_usec = curtime.tv_usec;
+							}
+						}
+
+						ami_cw->mouse(ami_cw, ami_cw->mouse_state | key_state, x, y);
+						ami_cw->mouse_state = BROWSER_MOUSE_HOVER;
+					break;
+
+					case MIDDLEUP:
+						if(ami_cw->mouse_state & BROWSER_MOUSE_PRESS_2)
+							ami_cw->mouse_state = BROWSER_MOUSE_CLICK_2;
+
+						ami_cw->mouse(ami_cw, ami_cw->mouse_state | key_state, x, y);
+						ami_cw->mouse_state = BROWSER_MOUSE_HOVER;
+					break;
+				}
+				ami_cw->mouse(ami_cw, ami_cw->mouse_state | key_state, x, y);
+			break;
+
+			case WMHI_RAWKEY:
+				storage = result & WMHI_GADGETMASK;
+
+				GetAttr(WINDOW_InputEvent, ami_cw->objects[GID_CW_WIN], (ULONG *)&ie);
+				nskey = ami_key_to_nskey(storage, ie);
+
+				ami_cw_key(ami_cw, nskey);
+			break;
+
+			case WMHI_NEWSIZE:
+				ami_cw_redraw(ami_cw, NULL);
+			break;
+
+			case WMHI_CLOSEWINDOW:
+				ami_cw_close(ami_cw);
+				return TRUE;
+			break;
+
+			case WMHI_GADGETUP:
+				switch(result & WMHI_GADGETMASK) {
+					case GID_CW_HSCROLL:
+					case GID_CW_VSCROLL:
+						ami_cw_redraw(ami_cw, NULL);
+					break;
+
+					default:
+						/* pass the event to the window owner */
+						if(ami_cw->event != NULL)
+							if(ami_cw->event(ami_cw, result) == TRUE) {
+								return TRUE;
+							}
+					break;
+				}
+
+			default:
+				/* pass the event to the window owner */
+				if(ami_cw->event != NULL)
+					if(ami_cw->event(ami_cw, result) == TRUE) {
+						return TRUE;
+					}
+			break;
+		}
+	};
+
+	return FALSE;
+}
+
+static const struct ami_win_event_table ami_cw_table = {
+	ami_cw_event,
+	ami_cw_close,
+};
+
+/**
+ * callback from core to request a redraw
+ */
+static void
+ami_cw_redraw_request(struct core_window *cw, const struct rect *r)
+{
+	struct ami_corewindow *ami_cw = (struct ami_corewindow *)cw;
+
+	ami_cw_redraw(ami_cw, r);
+}
+
+
+static void
+ami_cw_get_window_dimensions(struct core_window *cw, int *width, int *height)
+{
+	struct ami_corewindow *ami_cw = (struct ami_corewindow *)cw;
+	struct IBox *bbox;
+
+	if(ami_gui_get_space_box((Object *)ami_cw->objects[GID_CW_DRAW], &bbox) != NSERROR_OK) {
+		amiga_warn_user("NoMemory", "");
+		return;
+	}
+
+	*width = bbox->Width;
+	*height = bbox->Height;
+
+	ami_gui_free_space_box(bbox);
+}
+
+
+static void
+ami_cw_update_size(struct core_window *cw, int width, int height)
+{
+	struct ami_corewindow *ami_cw = (struct ami_corewindow *)cw;
+	int win_w, win_h;
+
+	ami_cw_get_window_dimensions((struct core_window *)ami_cw, &win_w, &win_h);
+
+	if(width == -1) {
+		ami_cw_toggle_scrollbar(ami_cw, false, false);
+		return;
+	}
+
+	if(height == -1) {
+		ami_cw_toggle_scrollbar(ami_cw, true, false);
+		return;
+	}
+
+	if(ami_cw->objects[GID_CW_VSCROLL]) {
+		ami_cw_toggle_scrollbar(ami_cw, true, true);
+		RefreshSetGadgetAttrs((struct Gadget *)ami_cw->objects[GID_CW_VSCROLL], ami_cw->win, NULL,
+			SCROLLER_Total, (ULONG)height,
+			SCROLLER_Visible, win_h,
+		TAG_DONE);
+	}
+
+	if(ami_cw->objects[GID_CW_HSCROLL]) {
+		ami_cw_toggle_scrollbar(ami_cw, false, true);
+		RefreshSetGadgetAttrs((struct Gadget *)ami_cw->objects[GID_CW_HSCROLL], ami_cw->win, NULL,
+			SCROLLER_Total, (ULONG)width,
+			SCROLLER_Visible, win_w,
+		TAG_DONE);
+	}
+}
+
+
+static void
+ami_cw_scroll_visible(struct core_window *cw, const struct rect *r)
+{
+	struct ami_corewindow *ami_cw = (struct ami_corewindow *)cw;
+
+	int scrollsetx;
+	int scrollsety;
+	int win_w = 0, win_h = 0;
+	ULONG win_x0, win_y0;
+	int win_x1, win_y1;
+
+	ami_cw_get_window_dimensions((struct core_window *)ami_cw, &win_w, &win_h);
+
+	ami_cw_scroller_top(ami_cw, &win_x0, &win_y0);
+
+	win_x1 = win_x0 + win_w;
+	win_y1 = win_y0 + win_h;
+
+	if(r->y1 > win_y1) scrollsety = r->y1 - win_h;
+	if(r->y0 < win_y0) scrollsety = r->y0;
+	if(r->x1 > win_x1) scrollsetx = r->x1 - win_w;
+	if(r->x0 < win_x0) scrollsetx = r->x0;
+
+	if(ami_cw->scroll_y_visible == true) {
+		RefreshSetGadgetAttrs((APTR)ami_cw->objects[GID_CW_VSCROLL], ami_cw->win, NULL,
+				SCROLLER_Top, scrollsety,
+				TAG_DONE);
+	}
+
+	if(ami_cw->scroll_x_visible == true) {
+		RefreshSetGadgetAttrs((APTR)ami_cw->objects[GID_CW_HSCROLL], ami_cw->win, NULL,
+				SCROLLER_Top, scrollsetx,
+				TAG_DONE);
+	}
+
+	/* probably need to redraw here */
+	ami_cw_redraw(ami_cw, NULL);
+}
+
+
+static void
+ami_cw_drag_status(struct core_window *cw, core_window_drag_status ds)
+{
+	struct ami_corewindow *ami_cw = (struct ami_corewindow *)cw;
+	ami_cw->drag_status = ds;
+}
+
+
+struct core_window_callback_table ami_cw_cb_table = {
+        .redraw_request = ami_cw_redraw_request,
+        .update_size = ami_cw_update_size,
+        .scroll_visible = ami_cw_scroll_visible,
+        .get_window_dimensions = ami_cw_get_window_dimensions,
+        .drag_status = ami_cw_drag_status
+};
+
+/* exported function documented example/corewindow.h */
+nserror ami_corewindow_init(struct ami_corewindow *ami_cw)
+{
+	/* setup the core window callback table */
+	ami_cw->cb_table = &ami_cw_cb_table;
+
+	/* clear some vars */
+	ami_cw->mouse_state = BROWSER_MOUSE_HOVER;
+	ami_cw->lastclick.tv_sec = 0;
+	ami_cw->lastclick.tv_usec = 0;
+	ami_cw->scroll_x_visible = true;
+	ami_cw->scroll_y_visible = true;
+	ami_cw->in_border_scroll = false;
+
+	/* allocate drawing area etc */
+	ami_init_layers(&ami_cw->gg, 0, 0, false);
+	ami_cw->gg.shared_pens = ami_AllocMinList();
+
+	ami_cw->deferred_rects = NewObjList();
+	ami_cw->deferred_rects_pool = ami_memory_itempool_create(sizeof(struct rect));
+
+	/* add the core window to our window list so we process events */
+	ami_gui_win_list_add(ami_cw, AMINS_COREWINDOW, &ami_cw_table);
+
+	/* set up the IDCMP hook for event processing (extended mouse, scrollbars) */
+	ami_cw->idcmp_hook.h_Entry = (void *)ami_cw_idcmp_hook;
+	ami_cw->idcmp_hook.h_Data = ami_cw;
+
+	/* open the window */
+	ami_cw->win = (struct Window *)RA_OpenWindow(ami_cw->objects[GID_CW_WIN]);
+
+	/* attach the scrollbars for event processing _if they are in the window border_ */
+	if(ami_cw->objects[GID_CW_HSCROLL] == NULL) {
+		GetAttr(WINDOW_HorizObject, ami_cw->objects[GID_CW_WIN],
+					(ULONG *)&ami_cw->objects[GID_CW_HSCROLL]);
+
+		RefreshSetGadgetAttrs((APTR)ami_cw->objects[GID_CW_HSCROLL], ami_cw->win, NULL,
+			GA_ID, GID_CW_HSCROLL,
+			ICA_TARGET, ICTARGET_IDCMP,
+			TAG_DONE);
+
+		ami_cw->in_border_scroll = true;
+	}
+
+	if(ami_cw->objects[GID_CW_VSCROLL] == NULL) {
+		GetAttr(WINDOW_VertObject, ami_cw->objects[GID_CW_WIN],
+					(ULONG *)&ami_cw->objects[GID_CW_VSCROLL]);
+
+		RefreshSetGadgetAttrs((APTR)ami_cw->objects[GID_CW_VSCROLL], ami_cw->win, NULL,
+			GA_ID, GID_CW_VSCROLL,
+			ICA_TARGET, ICTARGET_IDCMP,
+			TAG_DONE);
+
+		ami_cw->in_border_scroll = true;
+	}
+
+	return NSERROR_OK;
+}
+
+/* exported interface documented in example/corewindow.h */
+nserror ami_corewindow_fini(struct ami_corewindow *ami_cw)
+{
+	/* remove any pending redraws */
+	ami_schedule(-1, ami_cw_redraw_cb, ami_cw);
+	FreeObjList(ami_cw->deferred_rects);
+	ami_memory_itempool_delete(ami_cw->deferred_rects_pool);
+
+	/* destroy the window */
+	ami_cw->win = NULL;
+	DisposeObject(ami_cw->objects[GID_CW_WIN]);
+
+#if 0
+	/* ensure our scrollbars are destroyed */
+	/* it appears these are disposed anyway,
+	 * even if the gadgets are no longer attached to the window */
+	if(ami_cw->in_border_scroll == false) {
+		if(ami_cw->scroll_x_visible == false) {
+			DisposeObject(ami_cw->objects[GID_CW_HSCROLL]);
+		}
+		if(ami_cw->scroll_y_visible == false) {
+			DisposeObject(ami_cw->objects[GID_CW_VSCROLL]);
+		}
+	}
+#endif
+
+	/* release off-screen bitmap stuff */
+	ami_plot_release_pens(ami_cw->gg.shared_pens);
+	ami_free_layers(&ami_cw->gg);
+
+	/* free the window title */
+	ami_utf8_free(ami_cw->wintitle);
+
+	/* remove the core window from our window list */
+	ami_gui_win_list_remove(ami_cw);
+
+	return NSERROR_OK;
+}
+
diff --git a/frontends/amiga/corewindow.h b/frontends/amiga/corewindow.h
new file mode 100644
index 0000000..8d93882
--- /dev/null
+++ b/frontends/amiga/corewindow.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2017 Chris Young <chris at unsatisfactorysoftware.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 AMIGA_COREWINDOW_H
+#define AMIGA_COREWINDOW_H
+
+#include "netsurf/core_window.h"
+
+#include "amiga/gui.h" /* need to know the size of ami_generic_window :( */
+#include "amiga/plotters.h"
+
+/**
+ * BOOPSI objects
+ */
+
+enum {
+	GID_CW_WIN = 0, /* window object */
+	GID_CW_MAIN, /* root layout object */
+	GID_CW_DRAW, /* drawing area (space.gadget) */
+	GID_CW_HSCROLL, /* horizontal scroller */
+	GID_CW_VSCROLL, /* vertical scroller */
+	GID_CW_HSCROLLLAYOUT, /* horizontal scroller container*/
+	GID_CW_VSCROLLLAYOUT, /* vertical scroller container */
+	GID_CW_LAST
+};
+
+/**
+ * Amiga core window state
+ */
+struct ami_corewindow {
+		/*
+		 * Any variables common to any frontend window would go here.
+		 * e.g. drawing area handles, toolkit pointers or other state
+		 */
+		struct ami_generic_window w;
+		struct Window *win;
+		Object *objects[GID_CW_LAST];
+
+		struct Hook idcmp_hook;
+		struct timeval lastclick;
+
+		int mouse_state;
+
+		APTR deferred_rects_pool;
+		struct MinList *deferred_rects;
+
+		/** keep track of the scrollbar type we're using */
+		bool in_border_scroll;
+		bool scroll_x_visible;
+		bool scroll_y_visible;
+
+		/** window title, must be allocated wth ami_utf8 function */
+		char *wintitle;
+
+		/** stuff for our off-screen render bitmap */
+		struct gui_globals gg;
+		struct MinList *shared_pens;
+
+		/** drag status set by core */
+		core_window_drag_status drag_status;
+
+		/** table of callbacks for core window operations */
+		struct core_window_callback_table *cb_table;
+
+		/**
+		 * callback to draw on drawable area of Amiga core window
+		 *
+		 * \param ami_cw The Amiga core window structure.
+		 * \param x Plot origin (X)
+		 * \param r Plot origin (Y)
+		 * \param r The rectangle of the window that needs updating.
+		 * \param ctx Redraw context
+		 * \return NSERROR_OK on success otherwise apropriate error code
+		 */
+		nserror (*draw)(struct ami_corewindow *ami_cw, int x, int y, struct rect *r,
+						struct redraw_context *ctx);
+
+		/**
+		 * callback for keypress on Amiga core window
+		 *
+		 * \param ami_cw The Amiga core window structure.
+		 * \param nskey The netsurf key code.
+		 * \return NSERROR_OK if key processed,
+		 *         NSERROR_NOT_IMPLEMENTED if key not processed
+		 *         otherwise apropriate error code
+		 */
+		nserror (*key)(struct ami_corewindow *ami_cw, uint32_t nskey);
+
+		/**
+		 * callback for mouse event on Amiga core window
+		 *
+		 * \param ami_cw The Amiga core window structure.
+		 * \param mouse_state mouse state
+		 * \param x location of event
+		 * \param y location of event
+		 * \return NSERROR_OK on sucess otherwise apropriate error code.
+		 */
+		nserror (*mouse)(struct ami_corewindow *ami_cw, browser_mouse_state mouse_state, int x, int y);
+
+		/**
+		 * callback for unknown events on Amiga core window
+		 * eg. buttons in the ssl cert window
+		 * (result & WMHI_CLASSMASK) gives the class of event (eg. WMHI_GADGETUP)
+		 * (result & WMHI_GADGETMASK) gives the gadget ID (eg. GID_SSLCERT_ACCEPT)
+		 *
+		 * \param ami_cw The Amiga core window structure.
+		 * \param result event as returned by RA_HandleInput()
+ 		 * \return TRUE if window closed during event processing
+		 */
+		BOOL (*event)(struct ami_corewindow *ami_cw, ULONG result);
+
+		/**
+		 * callback to close an Amiga core window
+		 *
+		 * \param ami_cw The Amiga core window structure.
+		 */
+		void (*close)(struct ami_corewindow *ami_cw);
+
+};
+
+/**
+ * initialise elements of Amiga core window.
+ *
+ * As a pre-requisite the draw, key and mouse callbacks must be defined
+ *
+ * \param example_cw An Amiga core window structure to initialise
+ * \return NSERROR_OK on successful initialisation otherwise error code.
+ */
+nserror ami_corewindow_init(struct ami_corewindow *ami_cw);
+
+/**
+ * finalise elements of Amiga core window.
+ *
+ * \param ami_cw An Amiga core window structure to finialise
+ * \return NSERROR_OK on successful finalisation otherwise error code.
+ */
+nserror ami_corewindow_fini(struct ami_corewindow *ami_cw);
+
+#endif
+
diff --git a/frontends/amiga/gui.c b/frontends/amiga/gui.c
index ba0a786..f94090b 100644
--- a/frontends/amiga/gui.c
+++ b/frontends/amiga/gui.c
@@ -1376,27 +1376,34 @@ int ami_key_to_nskey(ULONG keycode, struct InputEvent *ie)
 	return nskey;
 }
 
-static void ami_update_quals(struct gui_window_2 *gwin)
+int ami_gui_get_quals(Object *win_obj)
 {
 	uint32 quals = 0;
+	int key_state = 0;
 #ifdef __amigaos4__
-	GetAttr(WINDOW_Qualifier,gwin->objects[OID_MAIN],(uint32 *)&quals);
+	GetAttr(WINDOW_Qualifier, win_obj, (uint32 *)&quals);
 #else
 #warning qualifier needs fixing for OS3
 #endif
-	gwin->key_state = 0;
 
 	if(quals & NSA_QUAL_SHIFT) {
-		gwin->key_state |= BROWSER_MOUSE_MOD_1;
+		key_state |= BROWSER_MOUSE_MOD_1;
 	}
 
 	if(quals & IEQUALIFIER_CONTROL) {
-		gwin->key_state |= BROWSER_MOUSE_MOD_2;
+		key_state |= BROWSER_MOUSE_MOD_2;
 	}
 
 	if(quals & NSA_QUAL_ALT) {
-		gwin->key_state |= BROWSER_MOUSE_MOD_3;
+		key_state |= BROWSER_MOUSE_MOD_3;
 	}
+
+	return key_state;
+}
+
+static void ami_update_quals(struct gui_window_2 *gwin)
+{
+	gwin->key_state = ami_gui_get_quals(gwin->objects[OID_MAIN]);
 }
 
 /* exported interface documented in amiga/gui.h */
@@ -1682,7 +1689,7 @@ static bool ami_gui_hscroll_remove(struct gui_window_2 *gwin)
 	IDoMethod(gwin->objects[GID_HSCROLLLAYOUT], LM_REMOVECHILD,
 			gwin->win, gwin->objects[GID_HSCROLL]);
 #else
-	SetAttrs(gwin->objects[GID_HSCROLLLAYOUT], LAYOUT_RemoveChild, gwin->objects[GID_HSCROLL]);
+	SetAttrs(gwin->objects[GID_HSCROLLLAYOUT], LAYOUT_RemoveChild, gwin->objects[GID_HSCROLL], TAG_DONE);
 #endif
 
 	gwin->objects[GID_HSCROLL] = NULL;
@@ -1727,7 +1734,7 @@ static bool ami_gui_vscroll_remove(struct gui_window_2 *gwin)
 	IDoMethod(gwin->objects[GID_VSCROLLLAYOUT], LM_REMOVECHILD,
 			gwin->win, gwin->objects[GID_VSCROLL]);
 #else
-	SetAttrs(gwin->objects[GID_VSCROLLLAYOUT], LAYOUT_RemoveChild, gwin->objects[GID_VSCROLL]);
+	SetAttrs(gwin->objects[GID_VSCROLLLAYOUT], LAYOUT_RemoveChild, gwin->objects[GID_VSCROLL], TAG_DONE);
 #endif
 
 	gwin->objects[GID_VSCROLL] = NULL;
@@ -3259,8 +3266,10 @@ static void ami_gui_hotlist_toolbar_remove(struct gui_window_2 *gwin)
 	IDoMethod(gwin->objects[GID_HOTLISTLAYOUT], LM_REMOVECHILD,
 			gwin->win, gwin->objects[GID_HOTLISTSEPBAR]);
 #else
-	SetAttrs(gwin->objects[GID_HOTLISTLAYOUT], LAYOUT_RemoveChild, gwin->objects[GID_HOTLIST]);
-	SetAttrs(gwin->objects[GID_HOTLISTLAYOUT], LAYOUT_RemoveChild, gwin->objects[GID_HOTLISTSEPBAR]);
+	SetAttrs(gwin->objects[GID_HOTLISTLAYOUT],
+		LAYOUT_RemoveChild, gwin->objects[GID_HOTLIST], TAG_DONE);
+	SetAttrs(gwin->objects[GID_HOTLISTLAYOUT],
+		LAYOUT_RemoveChild, gwin->objects[GID_HOTLISTSEPBAR], TAG_DONE);
 #endif
 	FlushLayoutDomainCache((struct Gadget *)gwin->objects[GID_MAIN]);
 
@@ -4734,7 +4743,7 @@ static void ami_gui_window_update_box_deferred(struct gui_window *g, bool draw)
 	if(draw == true) ami_reset_pointer(g->shared);
 }
 
-static bool ami_gui_window_update_box_deferred_check(struct MinList *deferred_rects,
+bool ami_gui_window_update_box_deferred_check(struct MinList *deferred_rects,
 				const struct rect *restrict new_rect, APTR mempool)
 {
 	struct nsObject *node;
@@ -5603,7 +5612,7 @@ static struct gui_misc_table amiga_misc_table = {
 
 	.quit = gui_quit,
 	.launch_url = gui_launch_url,
-	.cert_verify = gui_cert_verify,
+	.cert_verify = ami_cert_verify,
 	.login = gui_401login_open,
 };
 
diff --git a/frontends/amiga/gui.h b/frontends/amiga/gui.h
index eb39e9e..4c3e586 100644
--- a/frontends/amiga/gui.h
+++ b/frontends/amiga/gui.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2008-2016 Chris Young <chris at unsatisfactorysoftware.co.uk>
+ * Copyright 2008-2017 Chris Young <chris at unsatisfactorysoftware.co.uk>
  *
  * This file is part of NetSurf, http://www.netsurf-browser.org/
  *
@@ -282,5 +282,17 @@ nserror ami_gui_win_list_add(void *win, int type, const struct ami_win_event_tab
  * Remove a window from the NetSurf window list
  */
 void ami_gui_win_list_remove(void *win);
+
+/**
+ * Get which qualifier keys are being pressed
+ */
+int ami_gui_get_quals(Object *win_obj);
+
+/**
+ * Check rect is not already queued for redraw
+ */
+bool ami_gui_window_update_box_deferred_check(struct MinList *deferred_rects,
+				const struct rect *restrict new_rect, APTR mempool);
+
 #endif
 
diff --git a/frontends/amiga/object.h b/frontends/amiga/object.h
index be96504..70bb550 100755
--- a/frontends/amiga/object.h
+++ b/frontends/amiga/object.h
@@ -33,6 +33,7 @@ enum
 	AMINS_HISTORYWINDOW,
 	AMINS_GUIOPTSWINDOW,
 	AMINS_PRINTWINDOW,
+	AMINS_COREWINDOW,
 	AMINS_FONT,
 	AMINS_MIME,
 	AMINS_RECT
diff --git a/frontends/amiga/sslcert.c b/frontends/amiga/sslcert.c
index 83798f2..d56a1fe 100644
--- a/frontends/amiga/sslcert.c
+++ b/frontends/amiga/sslcert.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2009 Chris Young <chris at unsatisfactorysoftware.co.uk>
+ * Copyright 2017 Chris Young <chris at unsatisfactorysoftware.co.uk>
  *
  * This file is part of NetSurf, http://www.netsurf-browser.org/
  *
@@ -16,39 +16,347 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <proto/exec.h>
+/**
+ * \file
+ * Implementation of Amiga certificate viewing using core windows.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <proto/intuition.h>
+
+#include <classes/window.h>
+#include <gadgets/button.h>
+#include <gadgets/layout.h>
+#include <gadgets/scroller.h>
+#include <gadgets/space.h>
+#include <images/label.h>
+
+#include <reaction/reaction_macros.h>
 
-#include "utils/nsurl.h"
-#include "content/llcache.h"
-#include "netsurf/mouse.h"
-#include "netsurf/window.h"
+#include "utils/log.h"
+#include "netsurf/keypress.h"
+#include "netsurf/plotters.h"
 #include "desktop/sslcert_viewer.h"
+#include "utils/messages.h"
 
-#include "amiga/tree.h"
+#include "amiga/corewindow.h"
+#include "amiga/libs.h"
 #include "amiga/sslcert.h"
+#include "amiga/utf8.h"
+
+
+/**
+ * Amiga certificate viewing window context
+ */
+enum {
+	GID_SSLCERT_ACCEPT = GID_CW_LAST,
+	GID_SSLCERT_REJECT,
+	GID_SSLCERT_LAST
+};
+
+#define GID_SSLCERT_SIZE GID_SSLCERT_LAST - GID_CW_LAST
+
+struct ami_crtvrfy_window {
+	/** Amiga core window context */
+	struct ami_corewindow core;
+
+	/** Amiga GUI stuff */
+	Object *sslcert_objects[GID_SSLCERT_LAST]; // technically wasting a few bytes here
+
+	char *sslerr;
+	char *sslaccept;
+	char *sslreject;
+
+	/** SSL certificate viewer context data */
+	struct sslcert_session_data *ssl_data;
+};
+
+/**
+ * destroy a previously created certificate view
+ */
+static nserror
+ami_crtvrfy_destroy(struct ami_crtvrfy_window *crtvrfy_win)
+{
+	nserror res;
+
+	res = sslcert_viewer_fini(crtvrfy_win->ssl_data);
+	if (res == NSERROR_OK) {
+		ami_utf8_free(crtvrfy_win->sslerr);
+		ami_utf8_free(crtvrfy_win->sslaccept);
+		ami_utf8_free(crtvrfy_win->sslreject);
+		res = ami_corewindow_fini(&crtvrfy_win->core); /* closes the window for us */
+	}
+	return res;
+}
 
-nserror gui_cert_verify(nsurl *url, 
-		const struct ssl_cert_info *certs, unsigned long num,
-		nserror (*cb)(bool proceed, void *pw), void *cbpw)
+static void
+ami_crtvrfy_accept(struct ami_corewindow *ami_cw)
 {
-	struct sslcert_session_data *data;
-	struct treeview_window *ssl_window;
+	struct ami_crtvrfy_window *crtvrfy_win;
+	/* technically degenerate container of */
+	crtvrfy_win = (struct ami_crtvrfy_window *)ami_cw;
 
-	sslcert_viewer_create_session_data(num, url, cb, cbpw,
-			certs, &data);
-	ssl_current_session = data;
+	sslcert_viewer_accept(crtvrfy_win->ssl_data);
 
-	ssl_window = ami_tree_create(TREE_SSLCERT, data);
-	if (!ssl_window) {
-		return NSERROR_INIT_FAILED;
+	ami_crtvrfy_destroy(crtvrfy_win);
+}
+
+static void
+ami_crtvrfy_reject(struct ami_corewindow *ami_cw)
+{
+	struct ami_crtvrfy_window *crtvrfy_win;
+	/* technically degenerate container of */
+	crtvrfy_win = (struct ami_crtvrfy_window *)ami_cw;
+
+	sslcert_viewer_reject(crtvrfy_win->ssl_data);
+
+	ami_crtvrfy_destroy(crtvrfy_win);
+}
+
+/**
+ * callback for unknown events on Amiga core window
+ * eg. buttons in the ssl cert window
+ * (result & WMHI_CLASSMASK) gives the class of event (eg. WMHI_GADGETUP)
+ * (result & WMHI_GADGETMASK) gives the gadget ID (eg. GID_SSLCERT_ACCEPT)
+ *
+ * \param ami_cw The Amiga core window structure.
+ * \param result event as returned by RA_HandleInput()
+ * \return TRUE if window closed during event processing
+ */
+static BOOL
+ami_crtvrfy_event(struct ami_corewindow *ami_cw, ULONG result)
+{
+	if((result & WMHI_CLASSMASK) == WMHI_GADGETUP) {
+		switch(result & WMHI_GADGETMASK) {
+			case GID_SSLCERT_ACCEPT:
+				ami_crtvrfy_accept(ami_cw);
+				return TRUE;
+			break;
+
+			case GID_SSLCERT_REJECT:
+				ami_crtvrfy_reject(ami_cw);
+				return TRUE;
+			break;
+		}
 	}
+	return FALSE;
+}
 
-	ami_tree_open(ssl_window, AMI_TREE_SSLCERT);
+/**
+ * callback for mouse action for certificate verify on core window
+ *
+ * \param ami_cw The Amiga core window structure.
+ * \param mouse_state netsurf mouse state on event
+ * \param x location of event
+ * \param y location of event
+ * \return NSERROR_OK on success otherwise apropriate error code
+ */
+static nserror
+ami_crtvrfy_mouse(struct ami_corewindow *ami_cw,
+					browser_mouse_state mouse_state,
+					int x, int y)
+{
+	struct ami_crtvrfy_window *crtvrfy_win;
+	/* technically degenerate container of */
+	crtvrfy_win = (struct ami_crtvrfy_window *)ami_cw;
+
+	sslcert_viewer_mouse_action(crtvrfy_win->ssl_data, mouse_state, x, y);
 
 	return NSERROR_OK;
 }
 
-void ami_ssl_free(struct treeview_window *twin)
+/**
+ * callback for keypress for certificate verify on core window
+ *
+ * \param example_cw The Amiga core window structure.
+ * \param nskey The netsurf key code
+ * \return NSERROR_OK on success otherwise apropriate error code
+ */
+static nserror
+ami_crtvrfy_key(struct ami_corewindow *ami_cw, uint32_t nskey)
 {
-	ami_tree_destroy(twin);
+	struct ami_crtvrfy_window *crtvrfy_win;
+
+	/* technically degenerate container of */
+	crtvrfy_win = (struct ami_crtvrfy_window *)ami_cw;
+
+	if (sslcert_viewer_keypress(crtvrfy_win->ssl_data, nskey)) {
+			return NSERROR_OK;
+	}
+	return NSERROR_NOT_IMPLEMENTED;
+}
+
+/**
+ * callback on draw event for certificate verify on core window
+ *
+ * \param ami_cw The Amiga core window structure.
+ * \param r The rectangle of the window that needs updating.
+ * \param ctx The drawing context
+ * \return NSERROR_OK on success otherwise apropriate error code
+ */
+static nserror
+ami_crtvrfy_draw(struct ami_corewindow *ami_cw, int x, int y, struct rect *r, struct redraw_context *ctx)
+{
+	struct ami_crtvrfy_window *crtvrfy_win;
+
+	/* technically degenerate container of */
+	crtvrfy_win = (struct ami_crtvrfy_window *)ami_cw;
+
+	sslcert_viewer_redraw(crtvrfy_win->ssl_data, x, y, r, ctx);
+
+	return NSERROR_OK;
+}
+
+static nserror
+ami_crtvrfy_create_window(struct ami_crtvrfy_window *crtvrfy_win)
+{
+	struct ami_corewindow *ami_cw = (struct ami_corewindow *)&crtvrfy_win->core;
+
+	ami_cw->objects[GID_CW_WIN] = WindowObj,
+  	    WA_ScreenTitle, ami_gui_get_screen_title(),
+       	WA_Title, ami_cw->wintitle,
+       	WA_Activate, TRUE,
+       	WA_DepthGadget, TRUE,
+       	WA_DragBar, TRUE,
+       	WA_CloseGadget, FALSE,
+       	WA_SizeGadget, TRUE,
+		WA_SizeBBottom, TRUE,
+		WA_Height, scrn->Height / 2,
+		WA_PubScreen, scrn,
+		WA_ReportMouse, TRUE,
+       	WA_IDCMP, IDCMP_MOUSEMOVE | IDCMP_MOUSEBUTTONS | IDCMP_NEWSIZE |
+				IDCMP_RAWKEY | IDCMP_GADGETUP | IDCMP_IDCMPUPDATE |
+				IDCMP_EXTENDEDMOUSE | IDCMP_SIZEVERIFY,
+		WINDOW_IDCMPHook, &ami_cw->idcmp_hook,
+		WINDOW_IDCMPHookBits, IDCMP_IDCMPUPDATE | IDCMP_EXTENDEDMOUSE,
+		WINDOW_SharedPort, sport,
+		WINDOW_UserData, crtvrfy_win,
+		/* WINDOW_NewMenu, twin->menu,   -> No menu for SSL Cert */
+		WINDOW_IconifyGadget, FALSE,
+		WINDOW_Position, WPOS_CENTERSCREEN,
+		WINDOW_ParentGroup, ami_cw->objects[GID_CW_MAIN] = LayoutVObj,
+			LAYOUT_AddImage, LabelObj,
+				LABEL_Text, crtvrfy_win->sslerr,
+			LabelEnd,
+			LAYOUT_AddChild, ami_cw->objects[GID_CW_HSCROLLLAYOUT] = LayoutVObj,
+				LAYOUT_AddChild, ami_cw->objects[GID_CW_VSCROLLLAYOUT] = LayoutHObj,
+					LAYOUT_AddChild, ami_cw->objects[GID_CW_DRAW] = SpaceObj,
+						GA_ID, GID_CW_DRAW,
+						SPACE_Transparent, TRUE,
+						SPACE_BevelStyle, BVS_DISPLAY,
+						GA_RelVerify, TRUE,
+		   			SpaceEnd,
+					LAYOUT_AddChild, ami_cw->objects[GID_CW_VSCROLL] = ScrollerObj,
+						GA_ID, GID_CW_VSCROLL,
+						GA_RelVerify, TRUE,
+		   			ScrollerEnd,
+				LayoutEnd,
+				LAYOUT_AddChild, ami_cw->objects[GID_CW_HSCROLL] = ScrollerObj,
+					GA_ID, GID_CW_HSCROLL,
+					GA_RelVerify, TRUE,
+					SCROLLER_Orientation, SORIENT_HORIZ,
+	   			ScrollerEnd,
+			LayoutEnd,
+			LAYOUT_AddChild, LayoutHObj,
+				LAYOUT_AddChild, crtvrfy_win->sslcert_objects[GID_SSLCERT_ACCEPT] = ButtonObj,
+					GA_ID, GID_SSLCERT_ACCEPT,
+					GA_Text, crtvrfy_win->sslaccept,
+					GA_RelVerify, TRUE,
+				ButtonEnd,
+				LAYOUT_AddChild, crtvrfy_win->sslcert_objects[GID_SSLCERT_REJECT] = ButtonObj,
+					GA_ID, GID_SSLCERT_REJECT,
+					GA_Text, crtvrfy_win->sslreject,
+					GA_RelVerify, TRUE,
+				ButtonEnd,
+			EndGroup,
+			CHILD_WeightedHeight, 0,
+		EndGroup,
+	EndWindow;
+
+	if(ami_cw->objects[GID_CW_WIN] == NULL) {
+		return NSERROR_NOMEM;
+	}
+
+	return NSERROR_OK;
 }
+
+/* exported interface documented in amiga/ssl_cert.h */
+nserror ami_cert_verify(struct nsurl *url,
+						const struct ssl_cert_info *certs,
+						unsigned long num,
+						nserror (*cb)(bool proceed, void *pw),
+						void *cbpw)
+{
+	struct ami_crtvrfy_window *ncwin;
+	nserror res;
+
+	ncwin = calloc(1, sizeof(struct ami_crtvrfy_window));
+	if (ncwin == NULL) {
+		return NSERROR_NOMEM;
+	}
+
+	ncwin->core.wintitle = ami_utf8_easy((char *)messages_get("SSLCerts"));
+	ncwin->sslerr = ami_utf8_easy((char *)messages_get("SSLError"));
+	ncwin->sslaccept = ami_utf8_easy((char *)messages_get("SSL_Certificate_Accept"));
+	ncwin->sslreject = ami_utf8_easy((char *)messages_get("SSL_Certificate_Reject"));
+
+	res = ami_crtvrfy_create_window(ncwin);
+	if (res != NSERROR_OK) {
+		LOG("SSL UI builder init failed");
+		ami_utf8_free(ncwin->core.wintitle);
+		ami_utf8_free(ncwin->sslerr);
+		ami_utf8_free(ncwin->sslaccept);
+		ami_utf8_free(ncwin->sslreject);
+		free(ncwin);
+		return res;
+	}
+
+	/* initialise example core window */
+	ncwin->core.draw = ami_crtvrfy_draw;
+	ncwin->core.key = ami_crtvrfy_key;
+	ncwin->core.mouse = ami_crtvrfy_mouse;
+	ncwin->core.close = ami_crtvrfy_reject;
+	ncwin->core.event = ami_crtvrfy_event;
+
+	res = ami_corewindow_init(&ncwin->core);
+	if (res != NSERROR_OK) {
+		ami_utf8_free(ncwin->core.wintitle);
+		ami_utf8_free(ncwin->sslerr);
+		ami_utf8_free(ncwin->sslaccept);
+		ami_utf8_free(ncwin->sslreject);
+		DisposeObject(ncwin->core.objects[GID_CW_WIN]);
+		free(ncwin);
+		return res;
+	}
+
+	/* initialise certificate viewing interface */
+	res = sslcert_viewer_create_session_data(num, url, cb, cbpw, certs,
+									   &ncwin->ssl_data);
+	if (res != NSERROR_OK) {
+		ami_utf8_free(ncwin->core.wintitle);
+		ami_utf8_free(ncwin->sslerr);
+		ami_utf8_free(ncwin->sslaccept);
+		ami_utf8_free(ncwin->sslreject);
+		DisposeObject(ncwin->core.objects[GID_CW_WIN]);
+		free(ncwin);
+		return res;
+	}
+
+	res = sslcert_viewer_init(ncwin->core.cb_table,
+							  (struct core_window *)ncwin,
+							  ncwin->ssl_data);
+	if (res != NSERROR_OK) {
+		ami_utf8_free(ncwin->core.wintitle);
+		ami_utf8_free(ncwin->sslerr);
+		ami_utf8_free(ncwin->sslaccept);
+		ami_utf8_free(ncwin->sslreject);
+		DisposeObject(ncwin->core.objects[GID_CW_WIN]);
+		free(ncwin);
+		return res;
+	}
+
+	return NSERROR_OK;
+}
+
diff --git a/frontends/amiga/sslcert.h b/frontends/amiga/sslcert.h
index 86ce9c4..392989f 100644
--- a/frontends/amiga/sslcert.h
+++ b/frontends/amiga/sslcert.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2009 Chris Young <chris at unsatisfactorysoftware.co.uk>
+ * Copyright 2017 Chris Young <chris at unsatisfactorysoftware.co.uk>
  *
  * This file is part of NetSurf, http://www.netsurf-browser.org/
  *
@@ -18,11 +18,21 @@
 
 #ifndef AMIGA_SSLCERT_H
 #define AMIGA_SSLCERT_H
+struct nsurl;
+struct ssl_cert_info;
 
-nserror gui_cert_verify(nsurl *url, 
+/**
+ * Prompt the user to verify a certificate with issues.
+ *
+ * \param url The URL being verified.
+ * \param certs The certificate to be verified
+ * \param num The number of certificates to be verified.
+ * \param cb Callback upon user decision.
+ * \param cbpw Context pointer passed to cb
+ * \return NSERROR_OK or error code if prompt creation failed.
+ */
+nserror ami_cert_verify(struct nsurl *url, 
 		const struct ssl_cert_info *certs, unsigned long num,
-		     nserror (*cb)(bool proceed, void *pw), void *cbpw);
-
-void ami_ssl_free(struct treeview_window *twin);
-
+		nserror (*cb)(bool proceed, void *pw), void *cbpw);
 #endif
+
diff --git a/frontends/amiga/tree.c b/frontends/amiga/tree.c
index f1c5327..b9747c0 100644
--- a/frontends/amiga/tree.c
+++ b/frontends/amiga/tree.c
@@ -916,7 +916,7 @@ void ami_tree_close(void *w)
 		ami_utf8_free(twin->sslerr);
 		ami_utf8_free(twin->sslaccept);
 		ami_utf8_free(twin->sslreject);
-		ami_ssl_free(twin);
+		//ami_ssl_free(twin);
 	}
 
 	if(twin->type == AMI_TREE_HOTLIST)


-- 
NetSurf Browser



More information about the netsurf-commits mailing list