From 49f4fa0d787c867ed24ac49897feb347939d4ef3 Mon Sep 17 00:00:00 2001
From: Ole Loots <ole@monochrom.net>
Date: Sat, 21 Sep 2013 05:29:04 +0200
Subject: [PATCH] Hotlist and History and Cookies Manager implemented.

(The Cookie Manager window is a new one)
---
 atari/Makefile.target |  14 +-
 atari/cookies.c       | 239 +++++++++++++++++++++++++++
 atari/cookies.h       |  38 +++++
 atari/deskmenu.c      |  13 +-
 atari/gemtk/gemtk.h   |  18 ++
 atari/gemtk/guiwin.c  |  49 +++++-
 atari/gemtk/utils.c   |  19 +++
 atari/gui.c           |  44 ++++-
 atari/gui.h           |   6 +-
 atari/history.c       | 260 +++++++++++++++++++++++++++++
 atari/history.h       |  38 +++++
 atari/hotlist.c       | 138 ++++++++++++----
 atari/hotlist.h       |   4 +-
 atari/res/netsurf.rsc | Bin 34578 -> 34722 bytes
 atari/res/netsurf.rsh |  11 +-
 atari/res/netsurf.rsm |  17 +-
 atari/toolbar.c       |   4 +-
 atari/treeview.c      | 372 ++++++++++++++++++++++++++++++++++--------
 atari/treeview.h      |  28 +++-
 19 files changed, 1167 insertions(+), 145 deletions(-)

diff --git a/atari/Makefile.target b/atari/Makefile.target
index fee49633e..e47eb5d44 100644
--- a/atari/Makefile.target
+++ b/atari/Makefile.target
@@ -78,6 +78,7 @@ S_ATARI := \
 	bitmap.c \
 	clipboard.c \
 	ctxmenu.c \
+	cookies.c \
 	deskmenu.c \
 	download.c \
 	encoding.c \
@@ -85,18 +86,20 @@ S_ATARI := \
 	filetype.c \
 	font.c \
 	gui.c \
+	hotlist.c \
+	history.c \
 	login.c \
 	misc.c \
 	osspec.c \
+	redrawslots.c \
+	rootwin.c \
 	schedule.c \
 	search.c \
 	statusbar.c \
+	settings.c \
+	toolbar.c \
 	thumbnail.c \
 	treeview.c \
-	redrawslots.c \
-	rootwin.c \
-	toolbar.c \
-	settings.c \
 	plot/plot.c \
 	plot/fontplot.c \
 	plot/eddi.s \
@@ -110,9 +113,6 @@ S_ATARI := \
 	gemtk/utils.c \
 	gemtk/objc.c
 
-#	cookies.c \
-#	hotlist.c \
-#	history.c\
 
 S_ATARI := $(addprefix atari/,$(S_ATARI))
 
diff --git a/atari/cookies.c b/atari/cookies.c
index dfed6d037..9ac1890d7 100644
--- a/atari/cookies.c
+++ b/atari/cookies.c
@@ -15,3 +15,242 @@
  * 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 "utils/nsoption.h"
+#include "desktop/cookie_manager.h"
+#include "desktop/tree.h"
+#include "desktop/gui.h"
+#include "desktop/core_window.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/cookies.h"
+#include "atari/findfile.h"
+#include "atari/gemtk/gemtk.h"
+#include "atari/res/netsurf.rsh"
+
+extern GRECT desk_area;
+
+struct atari_cookie_manager_s atari_cookie_manager;
+
+
+/* Setup Atari Treeview Callbacks: */
+static nserror atari_cookie_manager_init_phase2(struct core_window *cw,
+				struct core_window_callback_table * default_callbacks);
+static void atari_cookie_manager_finish(struct core_window *cw);
+static void atari_cookie_manager_keypress(struct core_window *cw,
+												uint32_t ucs4);
+static void atari_cookie_manager_mouse_action(struct core_window *cw,
+												browser_mouse_state mouse,
+												int x, int y);
+static void atari_cookie_manager_draw(struct core_window *cw, int x,
+											int y, struct rect *clip,
+											const struct redraw_context *ctx);
+static short handle_event(GUIWIN *win, EVMULT_OUT *ev_out, short msg[8]);
+
+static struct atari_treeview_callbacks atari_cookie_manager_treeview_callbacks = {
+	.init_phase2 = atari_cookie_manager_init_phase2,
+	.finish = atari_cookie_manager_finish,
+	.draw = atari_cookie_manager_draw,
+	.keypress = atari_cookie_manager_keypress,
+	.mouse_action = atari_cookie_manager_mouse_action,
+	.gemtk_user_func = handle_event
+};
+
+
+static nserror atari_cookie_manager_init_phase2(struct core_window *cw,
+								struct core_window_callback_table *cb_t)
+{
+	LOG((""));
+	return(cookie_manager_init(cb_t, cw));
+}
+
+static void atari_cookie_manager_finish(struct core_window *cw)
+{
+	LOG((""));
+	cookie_manager_fini();
+}
+
+static void atari_cookie_manager_draw(struct core_window *cw, int x,
+											int y, struct rect *clip,
+											const struct redraw_context *ctx)
+{
+	cookie_manager_redraw(x, y, clip, ctx);
+}
+
+static void atari_cookie_manager_keypress(struct core_window *cw, uint32_t ucs4)
+{
+	LOG(("ucs4: %lu\n", ucs4));
+	cookie_manager_keypress(ucs4);
+}
+
+static void atari_cookie_manager_mouse_action(struct core_window *cw,
+												browser_mouse_state mouse,
+												int x, int y)
+{
+	if((mouse & BROWSER_MOUSE_HOVER) && cookie_manager_has_selection()){
+		cookie_manager_mouse_action(mouse, x, y);
+	} else {
+		cookie_manager_mouse_action(mouse, x, y);
+	}
+
+}
+
+
+
+static short handle_event(GUIWIN *win, EVMULT_OUT *ev_out, short msg[8])
+{
+	struct atari_treeview_window *tv=NULL;
+	GRECT tb_area;
+	GUIWIN * gemtk_win;
+	struct gui_window * gw;
+	char *cur_url = NULL;
+	char *cur_title = NULL;
+
+	LOG((""));
+
+	if(ev_out->emo_events & MU_MESAG){
+		switch (msg[0]) {
+
+			case WM_TOOLBAR:
+				LOG(("WM_TOOLBAR"));
+				/*
+				tv = (struct atari_treeview_window*) gemtk_wm_get_user_data(win);
+				assert(tv);
+				switch	(msg[4]) {
+
+					case TOOLBAR_HOTLIST_EDIT:
+						hotlist_edit_selection();
+						break;
+				}
+
+				gemtk_win = atari_treeview_get_gemtk_window(tv);
+				assert(gemtk_win);
+				gemtk_obj_get_tree(TOOLBAR_HOTLIST)[msg[4]].ob_state &= ~OS_SELECTED;
+				atari_treeview_get_grect(tv, TREEVIEW_AREA_TOOLBAR, &tb_area);
+				evnt_timer(150);
+				gemtk_wm_exec_redraw(gemtk_win, &tb_area);
+				*/
+			break;
+
+			case WM_CLOSED:
+				atari_cookie_manager_close();
+			break;
+
+			default: break;
+		}
+	}
+
+	// TODO: implement selectable objects in toolbar API:
+	// ObjcChange( OC_TOOLBAR, win, buff[4], ~SELECTED, OC_MSG );
+}
+
+void atari_cookie_manager_init(void)
+{
+	if (atari_cookie_manager.init == false) {
+
+		if (atari_cookie_manager.window == NULL) {
+			int flags = ATARI_TREEVIEW_WIDGETS;
+			short handle = -1;
+			GRECT desk;
+			OBJECT * tree = gemtk_obj_get_tree(TOOLBAR_COOKIES);
+			assert( tree );
+
+			handle = wind_create(flags, 0, 0, desk_area.g_w, desk_area.g_h);
+			atari_cookie_manager.window = gemtk_wm_add(handle,
+												GEMTK_WM_FLAG_DEFAULTS, NULL);
+			if( atari_cookie_manager.window == NULL ) {
+				gemtk_msg_box_show(GEMTK_MSG_BOX_ALERT,
+									"Failed to allocate Treeview:\nCookies");
+				return;
+			}
+			wind_set_str(handle, WF_NAME, (char*)messages_get("Cookies"));
+			gemtk_wm_set_toolbar(atari_cookie_manager.window, tree, 0, 0);
+			gemtk_wm_unlink(atari_cookie_manager.window);
+
+			atari_cookie_manager.tv = atari_treeview_create(
+										atari_cookie_manager.window,
+										&atari_cookie_manager_treeview_callbacks,
+										flags);
+
+			if (atari_cookie_manager.tv == NULL) {
+				/* handle it properly, clean up previous allocs */
+				LOG(("Failed to allocate treeview"));
+				return;
+			}
+
+		} else {
+
+		}
+	}
+	atari_cookie_manager.init = true;
+}
+void atari_cookie_manager_open(void)
+{
+	assert(atari_cookie_manager.init);
+
+	if (atari_cookie_manager.init == false) {
+		// TODO
+		return;
+	}
+
+	if (atari_treeview_is_open(atari_cookie_manager.tv) == false) {
+
+	    GRECT pos;
+	    pos.g_x = desk_area.g_w - desk_area.g_w / 4;
+	    pos.g_y = desk_area.g_y;
+	    pos.g_w = desk_area.g_w / 4;
+	    pos.g_h = desk_area.g_h;
+
+		atari_treeview_open(atari_cookie_manager.tv, &pos);
+	} else {
+		wind_set(gemtk_wm_get_handle(atari_cookie_manager.window), WF_TOP, 1, 0,
+				0, 0);
+	}
+}
+
+
+void atari_cookie_manager_close(void)
+{
+	atari_treeview_close(atari_cookie_manager.tv);
+}
+
+
+void atari_cookie_manager_destroy(void)
+{
+	if( atari_cookie_manager.init == false) {
+		return;
+	}
+	if( atari_cookie_manager.window != NULL ) {
+		if (atari_treeview_is_open(atari_cookie_manager.tv))
+			atari_cookie_manager_close();
+		wind_delete(gemtk_wm_get_handle(atari_cookie_manager.window));
+		gemtk_wm_remove(atari_cookie_manager.window);
+		atari_cookie_manager.window = NULL;
+		atari_treeview_delete(atari_cookie_manager.tv);
+		atari_cookie_manager.init = false;
+	}
+	LOG(("done"));
+
+}
+
+
+void atari_cookie_manager_redraw(void)
+{
+	atari_treeview_redraw(atari_cookie_manager.tv);
+}
diff --git a/atari/cookies.h b/atari/cookies.h
index e69de29bb..1ef03b795 100644
--- a/atari/cookies.h
+++ b/atari/cookies.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2013 Ole Loots <ole@monochrom.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+ #ifndef NS_ATARI_COOKIE_MANAGER_H
+ #define NS_ATARI_COOKIE_MANAGER_H
+
+struct core_window;
+
+struct atari_cookie_manager_s {
+	GUIWIN * window;
+	struct atari_treeview_window * tv;/*< The hotlist treeview handle.  */
+	bool init;
+};
+
+extern struct atari_cookie_manager_s atari_cookie_manager;
+
+void atari_cookie_manager_init(void);
+void atari_cookie_manager_open(void);
+void atari_cookie_manager_close(void);
+void atari_cookie_manager_destroy(void);
+void atari_cookie_manager_redraw(void);
+
+#endif
diff --git a/atari/deskmenu.c b/atari/deskmenu.c
index 0de2cc124..4084d83a0 100644
--- a/atari/deskmenu.c
+++ b/atari/deskmenu.c
@@ -12,6 +12,7 @@
 #include "atari/deskmenu.h"
 #include "atari/hotlist.h"
 #include "atari/history.h"
+#include "atari/cookies.h"
 #include "atari/toolbar.h"
 #include "atari/settings.h"
 #include "atari/search.h"
@@ -92,6 +93,7 @@ static void __CDECL menu_lhistory(short item, short title, void *data);
 static void __CDECL menu_ghistory(short item, short title, void *data);
 static void __CDECL menu_add_bookmark(short item, short title, void *data);
 static void __CDECL menu_bookmarks(short item, short title, void *data);
+static void __CDECL menu_cookies(short item, short title, void *data);
 static void __CDECL menu_vlog(short item, short title, void *data);
 static void __CDECL menu_help_content(short item, short title, void *data);
 
@@ -121,7 +123,8 @@ struct s_menu_item_evnt menu_evnt_tbl[] =
 	{T_UTIL, MAINMENU_M_LHISTORY,menu_lhistory, {0,NK_F7,0}, NULL},
 	{T_UTIL, MAINMENU_M_GHISTORY, menu_ghistory, {0,NK_F7,K_CTRL}, NULL},
 	{T_UTIL, MAINMENU_M_ADD_BOOKMARK, menu_add_bookmark, {'D',0,K_CTRL}, NULL},
-	{T_UTIL, MAINMENU_M_BOOKMARKS, menu_bookmarks, {0,NK_F6,0}, NULL},
+	{T_UTIL, MAINMENU_M_BOOKMARKS, menu_bookmarks, {0,NK_F6,0}, NULL},
+	{T_UTIL, MAINMENU_M_COOKIES, menu_cookies, {0,0,0}, NULL},
 	{T_UTIL, MAINMENU_M_CHOICES, menu_choices, {0,0,0}, NULL},
 	{T_UTIL, MAINMENU_M_VLOG, menu_vlog, {'V',0,K_ALT}, NULL},
 	{T_HELP, MAINMENU_M_HELP_CONTENT, menu_help_content, {0,NK_F1,0}, NULL},
@@ -459,7 +462,7 @@ static void __CDECL menu_lhistory(short item, short title, void *data)
 static void __CDECL menu_ghistory(short item, short title, void *data)
 {
 	LOG(("%s", __FUNCTION__));
-	atari_global_history_open();
+	//atari_global_history_open();
 }
 
 static void __CDECL menu_add_bookmark(short item, short title, void *data)
@@ -479,6 +482,12 @@ static void __CDECL menu_bookmarks(short item, short title, void *data)
 {
 	LOG(("%s", __FUNCTION__));
 	atari_hotlist_open();
+}
+
+static void __CDECL menu_cookies(short item, short title, void *data)
+{
+	LOG(("%s", __FUNCTION__));
+	atari_cookie_manager_open();
 }
 
 static void __CDECL menu_vlog(short item, short title, void *data)
diff --git a/atari/gemtk/gemtk.h b/atari/gemtk/gemtk.h
index 3e406b5e3..88ad0ccdb 100644
--- a/atari/gemtk/gemtk.h
+++ b/atari/gemtk/gemtk.h
@@ -33,6 +33,17 @@
 extern unsigned short _systype_v;
 unsigned short _systype (void);
 
+/* GEMTK Utils API: */
+
+#define GEMTK_DBG_GRECT(s,g) 				\
+	printf("%s", s);							\
+	printf("\tx0: %d, \n", (g)->g_x); 			\
+	printf("\ty0: %d, \n", (g)->g_y);			\
+	printf("\tx1: %d, \n", (g)->g_x+(g)->g_w); 	\
+	printf("\ty1: %d, \n", (g)->g_y+(g)->g_h);		\
+	printf("\tw:  %d, \n", (g)->g_w);			\
+	printf("\th:  %d  \n", (g)->g_h);			\
+
 /*
 * Chech for GRECT intersection without modifiend the src rectangles
 * return true when the  GRECT's intersect, fals otherwise.
@@ -47,6 +58,9 @@ int gemtk_keybd2ascii( int keybd, int shift);
 /** set VDI clip area by passing an GRECT */
 void gemtk_clip_grect(VdiHdl vh, GRECT *rect);
 
+void gemtk_wind_get_str(short aes_handle, short mode, char *str, int len);
+
+
 #ifndef POINT_WITHIN
 # define POINT_WITHIN(_x,_y, r) ((_x >= r.g_x) && (_x <= r.g_x + r.g_w ) \
 		&& (_y >= r.g_y) && (_y <= r.g_y + r.g_h))
@@ -180,6 +194,8 @@ GUIWIN * gemtk_wm_add(short handle, uint32_t flags,
 
 GUIWIN * gemtk_wm_find(short handle);
 
+void gemtk_wm_dump_window_info(GUIWIN *win);
+
 short gemtk_wm_remove(GUIWIN *win);
 
 GUIWIN * gemtk_wm_validate_ptr(GUIWIN *win);
@@ -192,6 +208,8 @@ short gemtk_wm_dispatch_event(EVMULT_IN *ev_in, EVMULT_OUT *ev_out, short msg[8]
 
 void gemtk_wm_get_grect(GUIWIN *win, enum guwin_area_e mode, GRECT *dest);
 
+short gemtk_wm_get_toolbar_edit_obj(GUIWIN *win);
+
 short gemtk_wm_get_handle(GUIWIN *win);
 
 uint32_t gemtk_wm_get_state(GUIWIN *win);
diff --git a/atari/gemtk/guiwin.c b/atari/gemtk/guiwin.c
index 01f548305..4ad3561f2 100644
--- a/atari/gemtk/guiwin.c
+++ b/atari/gemtk/guiwin.c
@@ -701,13 +701,13 @@ GUIWIN * gemtk_wm_add(short handle, uint32_t flags, gemtk_wm_event_handler_f cb)
 }
 
 /**
-* Returns an GUIWIN* for AES handle, when that AES window is managed by guiwin
+* Returns an GUIWIN* for AES handle, when that AES window is managed by gemtk_wm
 */
 GUIWIN *gemtk_wm_find(short handle)
 {
     GUIWIN *g;
     DEBUG_PRINT(("guiwin search handle: %d\n", handle));
-    for( g = winlist; g != NULL; g=g->next ) {
+    for (g = winlist; g != NULL; g=g->next) {
         if(g->handle == handle) {
             DEBUG_PRINT(("guiwin found handle: %p\n", g));
             return(g);
@@ -716,6 +716,48 @@ GUIWIN *gemtk_wm_find(short handle)
     return(NULL);
 }
 
+void gemtk_wm_dump_window_info(GUIWIN *win)
+{
+
+
+
+	char title[255];
+	GRECT work_area;
+	GRECT curr_area;
+	GRECT gemtk_work_area;
+	GRECT gemtk_toolbar_area;
+	GRECT gemtk_free_area;
+	short handle;
+	struct gemtk_wm_scroll_info_s *slid;
+
+	handle = gemtk_wm_get_handle(win);
+
+	assert(handle);
+
+	gemtk_wind_get_str(handle, WF_NAME, title, 255);
+	wind_get_grect(handle, WF_WORKXYWH, &work_area);
+	wind_get_grect(handle, WF_CURRXYWH, &curr_area);
+	gemtk_wm_get_grect(win, GEMTK_WM_AREA_CONTENT, &gemtk_free_area);
+	gemtk_wm_get_grect(win, GEMTK_WM_AREA_WORK, &gemtk_work_area);
+	gemtk_wm_get_grect(win, GEMTK_WM_AREA_TOOLBAR, &gemtk_toolbar_area);
+	slid = gemtk_wm_get_scroll_info(win);
+
+	printf ("GEMTK Window:       %p (AES handle: %d)\n", win, win->handle);
+	printf ("Title:              %s\n", title);
+    GEMTK_DBG_GRECT ("WF_WORKXYWH:          \n", &work_area)
+    GEMTK_DBG_GRECT ("WF_CURRXYWH:          \n", &curr_area)
+    GEMTK_DBG_GRECT ("GEMTK_WM_AREA_CONTENT:\n", &gemtk_free_area)
+    GEMTK_DBG_GRECT ("GEMTK_WM_AREA_WORK:\n",    &gemtk_work_area)
+    GEMTK_DBG_GRECT ("GEMTK_WM_AREA_TOOLBAR:\n", &gemtk_toolbar_area)
+    printf ("Slider X pos:       %d\n", slid->x_pos);
+    printf ("Slider Y pos:       %d\n", slid->y_pos);
+    printf ("Slider X units:     %d\n", slid->x_unit_px);
+    printf ("Slider Y units:     %d\n", slid->y_unit_px);
+
+
+#undef DBG_GRECT
+};
+
 /**
 * Check's if the pointer is managed by the guiwin API.
 */
@@ -1024,7 +1066,6 @@ uint32_t gemtk_wm_get_state(GUIWIN *win)
     return(win->state);
 }
 
-
 /**
 * Set and new event handler function.
 */
@@ -1066,7 +1107,7 @@ void gemtk_wm_set_toolbar_size(GUIWIN *win, uint16_t s)
 	win->toolbar_size = s;
 }
 
-short getm_wm_get_toolbar_edit_obj(GUIWIN *win)
+short gemtk_wm_get_toolbar_edit_obj(GUIWIN *win)
 {
 	return(win->toolbar_edit_obj);
 }
diff --git a/atari/gemtk/utils.c b/atari/gemtk/utils.c
index f080e307c..20fe5d424 100644
--- a/atari/gemtk/utils.c
+++ b/atari/gemtk/utils.c
@@ -95,4 +95,23 @@ void gemtk_clip_grect(VdiHdl vh, GRECT *rect)
 	vs_clip_pxy(vh, pxy);
 }
 
+void gemtk_wind_get_str(short aes_handle, short mode, char *str, int len)
+{
+	char tmp_str[255];
+
+	if(len>255) {
+		len = 255;
+	}
+
+	memset(str, 0, len);
+	return;
+	/*
+
+	wind_get(aes_handle, mode, (short)(((unsigned long)tmp_str)>>16),
+			(short)(((unsigned long)tmp_str) & 0xffff), 0, 0);
+
+	strncpy(str, tmp_str, len);
+	*/
+}
+
 
diff --git a/atari/gui.c b/atari/gui.c
index 3f056a1bc..33d63b436 100644
--- a/atari/gui.c
+++ b/atari/gui.c
@@ -63,6 +63,7 @@
 #include "atari/statusbar.h"
 #include "atari/toolbar.h"
 #include "atari/hotlist.h"
+#include "atari/cookies.h"
 #include "atari/history.h"
 #include "atari/login.h"
 #include "atari/encoding.h"
@@ -171,12 +172,14 @@ void gui_poll(bool active)
 		tmp = tmp->next;
     }
 
-	// TODO: reenable treeview redraws
-/*
-    if(hl.tv->redraw){
-		atari_treeview_redraw(hl.tv);
-    }
+	// TODO: implement generic treeview redraw function
+	// TODO: rename hl to atari_hotlist or create getter for it...
+	//atari_treeview_redraw(hl.tv);
+	atari_hotlist_redraw();
+	atari_cookie_manager_redraw();
+	atari_global_history_redraw();
 
+/*	// TODO: reenable history redraws
     if(gl_history.tv->redraw){
 		atari_treeview_redraw(gl_history.tv);
     }
@@ -541,6 +544,27 @@ void gui_window_set_url(struct gui_window *w, const char *url)
     }
 }
 
+struct gui_window * gui_window_get_input_window(void)
+{
+	return(input_window);
+}
+
+char * gui_window_get_url(struct gui_window *gw)
+{
+	if (gw == NULL) {
+		return(NULL);
+	}
+	return(gw->url);
+}
+
+char * gui_window_get_title(struct gui_window *gw)
+{
+	if (gw == NULL) {
+		return(NULL);
+	}
+	return(gw->title);
+}
+
 static void throbber_advance( void * data )
 {
 
@@ -809,15 +833,16 @@ void gui_quit(void)
     struct gui_window * tmp = window_list;
 
 	/* Destroy all remaining browser windows: */
-    while( gw ) {
+    while (gw) {
         tmp = gw->next;
         browser_window_destroy(gw->browser->bw);
         gw = tmp;
     }
 
 	/* destroy the treeview windows: */
-    atari_global_history_destroy();
+    //atari_global_history_destroy();
     atari_hotlist_destroy();
+    atari_cookie_manager_destroy();
 
 	/* shutdown netsurf treeview framework: */
     treeview_fini();
@@ -1036,8 +1061,9 @@ static void gui_init2(int argc, char** argv)
     treeview_init(0);
 
 	/* Initialize the specific treeview windows: */
-    atari_global_history_init();
+    //atari_global_history_init();
     atari_hotlist_init();
+    atari_cookie_manager_init();
 
     /* Initialize the toolbar framework: */
     toolbar_init();
@@ -1084,7 +1110,7 @@ int main(int argc, char** argv)
     /* user options setup */
     ret = nsoption_init(set_defaults, &nsoptions, &nsoptions_default);
     if (ret != NSERROR_OK) {
-	die("Options failed to initialise");
+		die("Options failed to initialise");
     }
     nsoption_read(options, NULL);
     nsoption_commandline(&argc, argv, NULL);
diff --git a/atari/gui.h b/atari/gui.h
index 2146a26a5..c582d668b 100755
--- a/atari/gui.h
+++ b/atari/gui.h
@@ -142,7 +142,7 @@ struct s_browser
 */
 struct gui_window {
 	struct s_gui_win_root * root;
-	CMP_BROWSER browser;
+	struct s_browser * browser;
 	MFORM_EX *cursor;
     /* icon to be drawn when iconified, or NULL for default resource. */
     char * status;
@@ -157,8 +157,10 @@ struct gui_window {
 extern struct gui_window *window_list;
 
 /* -------------------------------------------------------------------------- */
-/* Public - non standard gui window functions                                 */
+/* Public - non core gui window functions     		                          */
 /* -------------------------------------------------------------------------- */
 void gui_set_input_gui_window(struct gui_window *gw);
+char *gui_window_get_url(struct gui_window *gw);
+char * gui_window_get_title(struct gui_window *gw);
 
 #endif
diff --git a/atari/history.c b/atari/history.c
index dfed6d037..c43b8296b 100644
--- a/atari/history.c
+++ b/atari/history.c
@@ -15,3 +15,263 @@
  * 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 "utils/nsoption.h"
+#include "desktop/global_history.h"
+#include "desktop/tree.h"
+#include "desktop/gui.h"
+#include "desktop/core_window.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/history.h"
+#include "atari/findfile.h"
+#include "atari/gemtk/gemtk.h"
+#include "atari/res/netsurf.rsh"
+
+extern GRECT desk_area;
+
+struct atari_global_history_s atari_global_history;
+
+/* Setup Atari Treeview Callbacks: */
+static nserror atari_global_history_init_phase2(struct core_window *cw,
+				struct core_window_callback_table * default_callbacks);
+static void atari_global_history_finish(struct core_window *cw);
+static void atari_global_history_keypress(struct core_window *cw,
+												uint32_t ucs4);
+static void atari_global_history_mouse_action(struct core_window *cw,
+												browser_mouse_state mouse,
+												int x, int y);
+static void atari_global_history_draw(struct core_window *cw, int x,
+											int y, struct rect *clip,
+											const struct redraw_context *ctx);
+static short handle_event(GUIWIN *win, EVMULT_OUT *ev_out, short msg[8]);
+
+static struct atari_treeview_callbacks atari_global_history_treeview_callbacks = {
+	.init_phase2 = atari_global_history_init_phase2,
+	.finish = atari_global_history_finish,
+	.draw = atari_global_history_draw,
+	.keypress = atari_global_history_keypress,
+	.mouse_action = atari_global_history_mouse_action,
+	.gemtk_user_func = handle_event
+};
+
+static nserror atari_global_history_init_phase2(struct core_window *cw,
+								struct core_window_callback_table *cb_t)
+{
+	LOG((""));
+	return(global_history_init(cb_t, cw));
+}
+
+static void atari_global_history_finish(struct core_window *cw)
+{
+	LOG((""));
+	global_history_fini();
+}
+
+static void atari_global_history_draw(struct core_window *cw, int x,
+											int y, struct rect *clip,
+											const struct redraw_context *ctx)
+{
+	global_history_redraw(x, y, clip, ctx);
+}
+
+static void atari_global_history_keypress(struct core_window *cw, uint32_t ucs4)
+{
+	LOG(("ucs4: %lu\n", ucs4));
+	global_history_keypress(ucs4);
+}
+
+static void atari_global_history_mouse_action(struct core_window *cw,
+												browser_mouse_state mouse,
+												int x, int y)
+{
+	LOG(("x:  %d, y: %d\n", x, y));
+	if((mouse & BROWSER_MOUSE_HOVER) && global_history_has_selection()){
+		global_history_mouse_action(mouse, x, y);
+	} else {
+		global_history_mouse_action(mouse, x, y);
+	}
+
+}
+
+
+
+static short handle_event(GUIWIN *win, EVMULT_OUT *ev_out, short msg[8])
+{
+	struct atari_treeview_window *tv=NULL;
+	GRECT tb_area;
+	GUIWIN * gemtk_win;
+	struct gui_window * gw;
+	char *cur_url = NULL;
+	char *cur_title = NULL;
+
+	LOG((""));
+
+	if(ev_out->emo_events & MU_MESAG){
+		switch (msg[0]) {
+
+//			case WM_TOOLBAR:
+//				LOG(("WM_TOOLBAR"));
+//				tv = (struct atari_treeview_window*) gemtk_wm_get_user_data(win);
+//				assert(tv);
+//				switch	(msg[4]) {
+//					case TOOLBAR_HOTLIST_CREATE_FOLDER:
+//						hotlist_add_folder(NULL, 0, 0);
+//						break;
+//
+//					case TOOLBAR_HOTLIST_ADD:
+//						gw = gui_window_get_input_window();
+//						if(gw && gw->browser){
+//							cur_url = gui_window_get_url(gw);
+//							cur_title = gui_window_get_title(gw);
+//							// TODO: read language string.
+//							cur_title = (cur_title ? cur_title : "New bookmark");
+//						} else {
+//							cur_url = "http://www";
+//						}
+//						atari_global_history_add_page(cur_url, cur_title);
+//						break;
+//
+//					case TOOLBAR_HOTLIST_DELETE:
+//						hotlist_keypress(KEY_DELETE_LEFT);
+//						// TODO: check if redraw is really required,
+//						// 		  - implement treeview getter for the gemtk
+//						//          handle.
+//						break;
+//
+//					case TOOLBAR_HOTLIST_EDIT:
+//						hotlist_edit_selection();
+//						break;
+//				}
+//
+//				gemtk_win = atari_treeview_get_gemtk_window(tv);
+//				assert(gemtk_win);
+//				gemtk_obj_get_tree(TOOLBAR_HOTLIST)[msg[4]].ob_state &= ~OS_SELECTED;
+//				atari_treeview_get_grect(tv, TREEVIEW_AREA_TOOLBAR, &tb_area);
+//				evnt_timer(150);
+//				gemtk_wm_exec_redraw(gemtk_win, &tb_area);
+//
+//			break;
+
+			case WM_CLOSED:
+				atari_global_history_close();
+			break;
+
+			default: break;
+		}
+	}
+
+	// TODO: implement selectable objects in toolbar API:
+	// ObjcChange( OC_TOOLBAR, win, buff[4], ~SELECTED, OC_MSG );
+}
+
+
+
+void atari_global_history_init(void)
+{
+	if (atari_global_history.init == false) {
+
+
+		if( atari_global_history.window == NULL ){
+			int flags = ATARI_TREEVIEW_WIDGETS;
+			short handle = -1;
+			GRECT desk;
+			OBJECT * tree = gemtk_obj_get_tree(TOOLBAR_HISTORY);
+			assert( tree );
+
+			handle = wind_create(flags, 0, 0, desk_area.g_w, desk_area.g_h);
+			atari_global_history.window = gemtk_wm_add(handle, GEMTK_WM_FLAG_DEFAULTS, NULL);
+			if( atari_global_history.window == NULL ) {
+				gemtk_msg_box_show(GEMTK_MSG_BOX_ALERT,
+									"Failed to allocate History");
+				return;
+			}
+			wind_set_str(handle, WF_NAME, (char*)messages_get("History"));
+			gemtk_wm_set_toolbar(atari_global_history.window, tree, 0, 0);
+			gemtk_wm_unlink(atari_global_history.window);
+
+			atari_global_history.tv = atari_treeview_create(
+									atari_global_history.window,
+									&atari_global_history_treeview_callbacks,
+									flags);
+
+			if (atari_global_history.tv == NULL) {
+				/* handle it properly, clean up previous allocs */
+				LOG(("Failed to allocate treeview"));
+				return;
+			}
+
+		} else {
+
+		}
+	}
+	atari_global_history.init = true;
+}
+
+void atari_global_history_open(void)
+{
+	assert(atari_global_history.init);
+
+	if (atari_global_history.init == false) {
+		return;
+	}
+
+	if (atari_treeview_is_open(atari_global_history.tv) == false) {
+
+	    GRECT pos;
+	    pos.g_x = desk_area.g_w - desk_area.g_w / 4;
+	    pos.g_y = desk_area.g_y;
+	    pos.g_w = desk_area.g_w / 4;
+	    pos.g_h = desk_area.g_h;
+
+		atari_treeview_open(atari_global_history.tv, &pos);
+	} else {
+		wind_set(gemtk_wm_get_handle(atari_global_history.window), WF_TOP, 1, 0, 0, 0);
+	}
+}
+
+void atari_global_history_close(void)
+{
+	atari_treeview_close(atari_global_history.tv);
+}
+
+void atari_global_history_destroy(void)
+{
+
+	if( atari_global_history.init == false) {
+		return;
+	}
+	if( atari_global_history.window != NULL ) {
+		if (atari_treeview_is_open(atari_global_history.tv))
+			atari_global_history_close();
+		wind_delete(gemtk_wm_get_handle(atari_global_history.window));
+		gemtk_wm_remove(atari_global_history.window);
+		atari_global_history.window = NULL;
+		atari_treeview_delete(atari_global_history.tv);
+		atari_global_history.init = false;
+	}
+	LOG(("done"));
+}
+
+void atari_global_history_redraw(void)
+{
+	atari_treeview_redraw(atari_global_history.tv);
+}
diff --git a/atari/history.h b/atari/history.h
index e69de29bb..c6b821fe7 100644
--- a/atari/history.h
+++ b/atari/history.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2013 Ole Loots <ole@monochrom.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NS_ATARI_HISTORY_H
+#define NS_ATARI_HISTORY_H
+
+struct core_window;
+
+struct atari_global_history_s {
+	GUIWIN * window;
+	struct atari_treeview_window * tv;/*< The hotlist treeview handle.  */
+	bool init;
+};
+
+extern struct atari_global_history_s atari_global_history;
+
+void atari_global_history_init(void);
+void atari_global_history_open(void);
+void atari_global_history_close(void);
+void atari_global_history_destroy(void);
+void atari_global_history_redraw(void);
+
+#endif
diff --git a/atari/hotlist.c b/atari/hotlist.c
index e44ce7db3..016cbc458 100644
--- a/atari/hotlist.c
+++ b/atari/hotlist.c
@@ -32,6 +32,7 @@
 #include "desktop/hotlist.h"
 #include "desktop/tree.h"
 #include "desktop/gui.h"
+#include "desktop/core_window.h"
 #include "utils/log.h"
 #include "utils/messages.h"
 #include "utils/utils.h"
@@ -48,30 +49,111 @@ extern GRECT desk_area;
 
 struct atari_hotlist hl;
 
+/* Setup Atari Treeview Callbacks: */
+static nserror atari_hotlist_init_phase2(struct core_window *cw,
+				struct core_window_callback_table * default_callbacks);
+static void atari_hotlist_finish(struct core_window *cw);
+static void atari_hotlist_keypress(struct core_window *cw,
+												uint32_t ucs4);
+static void atari_hotlist_mouse_action(struct core_window *cw,
+												browser_mouse_state mouse,
+												int x, int y);
+static void atari_hotlist_draw(struct core_window *cw, int x,
+											int y, struct rect *clip,
+											const struct redraw_context *ctx);
+static short handle_event(GUIWIN *win, EVMULT_OUT *ev_out, short msg[8]);
+
+static struct atari_treeview_callbacks atari_hotlist_treeview_callbacks = {
+	.init_phase2 = atari_hotlist_init_phase2,
+	.finish = atari_hotlist_finish,
+	.draw = atari_hotlist_draw,
+	.keypress = atari_hotlist_keypress,
+	.mouse_action = atari_hotlist_mouse_action,
+	.gemtk_user_func = handle_event
+};
+
+static nserror atari_hotlist_init_phase2(struct core_window *cw,
+								struct core_window_callback_table *cb_t)
+{
+	LOG((""));
+	return(hotlist_init(cb_t, cw, hl.path));
+}
+
+static void atari_hotlist_finish(struct core_window *cw)
+{
+	LOG((""));
+	hotlist_fini(hl.path);
+}
+
+static void atari_hotlist_draw(struct core_window *cw, int x,
+											int y, struct rect *clip,
+											const struct redraw_context *ctx)
+{
+	hotlist_redraw(x, y, clip, ctx);
+}
+
+static void atari_hotlist_keypress(struct core_window *cw, uint32_t ucs4)
+{
+	LOG(("ucs4: %lu\n", ucs4));
+	hotlist_keypress(ucs4);
+}
+
+static void atari_hotlist_mouse_action(struct core_window *cw,
+												browser_mouse_state mouse,
+												int x, int y)
+{
+	LOG(("x:  %d, y: %d\n", x, y));
+	if((mouse & BROWSER_MOUSE_HOVER) && hotlist_has_selection()){
+		hotlist_mouse_action(mouse, x, y);
+	} else {
+		hotlist_mouse_action(mouse, x, y);
+	}
+
+}
+
+
+
 static short handle_event(GUIWIN *win, EVMULT_OUT *ev_out, short msg[8])
 {
-	NSTREEVIEW tv=NULL;
+	struct atari_treeview_window *tv=NULL;
 	GRECT tb_area;
+	GUIWIN * gemtk_win;
+	struct gui_window * gw;
+	char *cur_url = NULL;
+	char *cur_title = NULL;
+
+	LOG((""));
 
 	if(ev_out->emo_events & MU_MESAG){
 		switch (msg[0]) {
 
 			case WM_TOOLBAR:
-
-				tv = (NSTREEVIEW) gemtk_wm_get_user_data(win);
-
+				LOG(("WM_TOOLBAR"));
+				tv = (struct atari_treeview_window*) gemtk_wm_get_user_data(win);
+				assert(tv);
 				switch	(msg[4]) {
 					case TOOLBAR_HOTLIST_CREATE_FOLDER:
-						hotlist_add_folder(NULL, false, 0);
+						hotlist_add_folder(NULL, 0, 0);
 						break;
 
 					case TOOLBAR_HOTLIST_ADD:
-						atari_hotlist_add_page(NULL, NULL);
+						gw = gui_window_get_input_window();
+						if(gw && gw->browser){
+							cur_url = gui_window_get_url(gw);
+							cur_title = gui_window_get_title(gw);
+							// TODO: read language string.
+							cur_title = (cur_title ? cur_title : "New bookmark");
+						} else {
+							cur_url = "http://www";
+						}
+						atari_hotlist_add_page(cur_url, cur_title);
 						break;
 
 					case TOOLBAR_HOTLIST_DELETE:
 						hotlist_keypress(KEY_DELETE_LEFT);
-						gemtk_wm_exec_redraw(tv->window, NULL);
+						// TODO: check if redraw is really required,
+						// 		  - implement treeview getter for the gemtk
+						//          handle.
 						break;
 
 					case TOOLBAR_HOTLIST_EDIT:
@@ -79,10 +161,12 @@ static short handle_event(GUIWIN *win, EVMULT_OUT *ev_out, short msg[8])
 						break;
 				}
 
+				gemtk_win = atari_treeview_get_gemtk_window(tv);
+				assert(gemtk_win);
 				gemtk_obj_get_tree(TOOLBAR_HOTLIST)[msg[4]].ob_state &= ~OS_SELECTED;
-				gemtk_wm_get_grect(tv->window, GEMTK_WM_AREA_TOOLBAR, &tb_area);
+				atari_treeview_get_grect(tv, TREEVIEW_AREA_TOOLBAR, &tb_area);
 				evnt_timer(150);
-				gemtk_wm_exec_redraw(tv->window, &tb_area);
+				gemtk_wm_exec_redraw(gemtk_win, &tb_area);
 			break;
 
 			case WM_CLOSED:
@@ -116,7 +200,6 @@ void atari_hotlist_init(void)
 			GRECT desk;
 			OBJECT * tree = gemtk_obj_get_tree(TOOLBAR_HOTLIST);
 			assert( tree );
-			hl.open = false;
 
 			handle = wind_create(flags, 0, 0, desk_area.g_w, desk_area.g_h);
 			hl.window = gemtk_wm_add(handle, GEMTK_WM_FLAG_DEFAULTS, NULL);
@@ -129,11 +212,10 @@ void atari_hotlist_init(void)
 			gemtk_wm_set_toolbar(hl.window, tree, 0, 0);
 			gemtk_wm_unlink(hl.window);
 			tree_hotlist_path = (const char*)&hl.path;
-			hl.tv = atari_treeview_create(
-				TREE_HOTLIST,
-				hl.window,
-				handle_event
-			);
+
+			hl.tv = atari_treeview_create(hl.window, &atari_hotlist_treeview_callbacks,
+									flags);
+
 			if (hl.tv == NULL) {
 				/* handle it properly, clean up previous allocs */
 				LOG(("Failed to allocate treeview"));
@@ -147,14 +229,14 @@ void atari_hotlist_init(void)
 	hl.init = true;
 }
 
-
 void atari_hotlist_open(void)
 {
-	if( hl.init == false ) {
+	assert(hl.init);
+	if (hl.init == false) {
 		return;
 	}
 
-	if( hl.open == false ) {
+	if (atari_treeview_is_open(hl.tv) == false) {
 
 	    GRECT pos;
 	    pos.g_x = desk_area.g_w - desk_area.g_w / 4;
@@ -162,9 +244,7 @@ void atari_hotlist_open(void)
 	    pos.g_w = desk_area.g_w / 4;
 	    pos.g_h = desk_area.g_h;
 
-		wind_open_grect(gemtk_wm_get_handle(hl.window), &pos);
-		hl.open = true;
-		atari_treeview_open( hl.tv );
+		atari_treeview_open(hl.tv, &pos);
 	} else {
 		wind_set(gemtk_wm_get_handle(hl.window), WF_TOP, 1, 0, 0, 0);
 	}
@@ -172,8 +252,6 @@ void atari_hotlist_open(void)
 
 void atari_hotlist_close(void)
 {
-	wind_close(gemtk_wm_get_handle(hl.window));
-	hl.open = false;
 	atari_treeview_close(hl.tv);
 }
 
@@ -184,12 +262,12 @@ void atari_hotlist_destroy(void)
 		return;
 	}
 	if( hl.window != NULL ) {
-		if (hl.open)
+		if (atari_treeview_is_open(hl.tv))
 			atari_hotlist_close();
 		wind_delete(gemtk_wm_get_handle(hl.window));
 		gemtk_wm_remove(hl.window);
 		hl.window = NULL;
-		atari_treeview_destroy(hl.tv);
+		atari_treeview_delete(hl.tv);
 		hl.init = false;
 	}
 	LOG(("done"));
@@ -197,7 +275,6 @@ void atari_hotlist_destroy(void)
 
 void atari_hotlist_redraw(void)
 {
-	int i = 01;
 	atari_treeview_redraw(hl.tv);
 }
 
@@ -209,7 +286,7 @@ void atari_hotlist_add_page( const char * url, const char * title )
 	struct node * selected = NULL;
 	struct node * folder = NULL;
 	nsurl *nsurl;
-	NSTREEVIEW tv = hl.tv;
+	ATARI_TREEVIEW_PTR tv = hl.tv;
 	if(hl.tv == NULL )
 		return;
 
@@ -218,11 +295,14 @@ void atari_hotlist_add_page( const char * url, const char * title )
 	if (nsurl_create(url, &nsurl) != NSERROR_OK)
 		return;
 
+	/* doesn't look nice:
 	if( hl.tv->click.x >= 0 && hl.tv->click.y >= 0 ){
 		hotlist_add_entry( nsurl, title, true, hl.tv->click.y );
 	} else {
-		hotlist_add_url( nsurl );
-	}
+
+	}*/
+	//hotlist_add_url(nsurl);
+	hotlist_add_entry(nsurl, title, 0, 0);
 	nsurl_unref(nsurl);
 }
 
diff --git a/atari/hotlist.h b/atari/hotlist.h
index c6fc4649a..2bcda5f01 100644
--- a/atari/hotlist.h
+++ b/atari/hotlist.h
@@ -26,8 +26,7 @@
 
 struct atari_hotlist {
 	GUIWIN * window;
-	NSTREEVIEW tv;		/*< The hotlist treeview handle.  */
-	bool open;
+	ATARI_TREEVIEW_PTR tv;/*< The hotlist treeview handle.  */
 	bool init;
 	char path[PATH_MAX];
 };
@@ -39,7 +38,6 @@ void atari_hotlist_open( void );
 void atari_hotlist_close( void );
 void atari_hotlist_destroy( void );
 void atari_hotlist_add_page( const char * url, const char * title );
-
 void atari_hotlist_redraw( void );
 
 
diff --git a/atari/res/netsurf.rsc b/atari/res/netsurf.rsc
index 64a8e35a60122fa06b1491201fc9f56336c1cb40..21373281c255c760ea8feebd7539f1e68ea851da 100755
GIT binary patch
delta 5180
zcmZ{oe~eUD701t;dHd$a{$hXc4zs(n%)Ht8wKFU%EtF-YNTFI*DPX~7b;T5+Ed^~z
zBz4W(>Y6kS(&}AXOfacPu~GhLf+1A5g(z*Rw*F{pL(Ik)#L&i8TdiqpknwxYeednO
zbbXU^ci-pSbMC$8-h1wy`S#J!iAO>XnKYA_?Yq?fLSi;CTbfAB(x}l%tu#mxG6+xk
z^tSO`xAK3r&*5#`$MHTxWI>`^AhVE*L@~U_OGNckkavk1t`If8O4MW$HD@4r?><hH
zNJ8rFLNWENsh!Tec&`r|R9D4ADcxHCRjS8-5pXNO|BgOt9trS&QxA9?^`ik^r8GGE
zkJa*2oXX%0DJVj|B1)9%q?_CZU`Au=eq*(h>IEX|L}Z$zGR8n$nSB_-n|%(Hx&=i@
z_>us>6Fe-uCBW|kH-)zb_%wJO6}jQIfI>lGi9vmUpHe$Q73Udf2>~&vE1>;7s3E*N
zz~2B53Gb=p1H2Hz!V^Bnum_fao5Gj+9B80`qK<kBXe8+?*kA(`mKe1AoDC*aDO}lo
z2>%i#VU-GK9|46Y$UuPq2s|Wwna{bE=fT6mdwmWxa9PcTE6#uMFHs-7Woxy|5}=0g
zL7&6hvKzod!gB%sDe$oHe1Pu(H-#5`4zz3rMIH4yXr$;XxPd32u*9I`b2d1SA|iY!
zz+VB63NHsZHWtN%rvv<b@VM}mw4Br%=75uK0K+~+UslxCP4gx(gjWKb_d-bc7>&?6
zYG-q*wh%lLb;18Czdpv4zFG8L@O6XFfzo%NFvwxWjlO~n_CgVYBZF4^oDCclVc}~6
z{5#;L@SA+jetryICw#5X+0QRfSi(oERR;;i-MVR{CPbMVUKcQU6Fe$>Wq|YYi3yL>
zNAOvQ#3(dv@H6JtPvM<1oW6vkO#^XiH;L3vYh@zSOH0vX3)B>gL`afJCZ$eV<rSH<
zX++6fvY@t%X@oVig4$r#1g<k&uZdTr(OG3i%Aw4s)kx&L@v3?^GHE=mc0?zgO9(8o
z8ze04^mBFWfd3#+n(Ovm-k-#{HP@-w<73E!n(I{T@y|(T*uPH29{(D(aQ#*k<Tjk*
zhWk&djj_$fOX^6hGW@z}Vt#v3M>|be5w4TDM9t_PcSPGJEL-@W&b%3W&ltYq$4-wa
zVH$*Nl(}kdLeOer3f>L=mTGU99DbWR5vv%S>JfKfF7PZh&9EC%-B_=g6ONf^_^h*Z
zlzTy0lsX^@3-dr^SEwIrko&0n&P$5<Do~RW;5r~)GrK@S)PYjZoW~C#frn%=^x5R`
zM-i70sRtW37%!-cjTPs#_~%nVkGcb+!?W~76#Dq_#-%xD1bzJIj=S}xpZfUG9rrjZ
z^zq|$T>K<ggV#|fr!KGOTCoEPef)Sm*Zhm%5jmFPGV@*oN5G>s$CbyQ0*?#V6VPD}
zfKc)xiWqa*JnEgMHHqwCm@JNC*gdd$>hWZAYGd<JC!42L`0%8-D+85TU8a)Dn=r=4
zSi+?1>%m9Jh!&91;_l?~>c0TK9^8->uVcj9>``>-&t@}t3I27Am}BK7ubIv0lEaFH
zeF;TxHw;WM&@plidPiVj3D+_5_*T@92=|V3=}@i<?!z*$28pTL(Oe20HPL;88okV>
z4T=boC97RW!ZX0~L<4-it6-BAy-4KNfh1{Nw21<jmE2||B3yW&)t41Sj-T8eW(#-&
zxW23;kf2trhhjHnpy14<FDtBIeh`kLvi<|7e{M?6v{a1!>L)Fe#zU&Tb+hpUHPKoz
z&Z;9QPpUbP-zu}MVq8@tC_hklwUrb3dW?^de{0WEfPAkyjY=2PeA^}`e+$%2nBFED
zmZ-UX$&XVAeQbtSAAlTvJiYU>vWnn=w4Z;9h7f%NpAqrn)qfxN$FS^OeE@p?&%wV*
z4)0Zc0=fo$?J_IF;Q9dc_;MITh`D<JqC?X}g$Kc75;XS!)EzA-_^B7}9)K=Ch58M`
z$7roebu0_@ZBZLLzHIDMa~+e$j7oM^oLA5cNmOpF9Zla8SWD<Iv>(&a3dzhBc{At>
z;K!NoaYtF)j+(gWp}bAkH;HGucn?-USfabd<=W3-%AkG=Cz5edxGA&vFomOWY6Sm;
zHqg7ac#LeUFy@~O)IS9hkp{N94Xig1t>Rgnz!BLbxBK-mvBhWMKPrB<fv2m4tYJI^
z#jkOiM#W&eZ-CGgf1~zyP4@6=;M8YOP<vTj>Dp|}sZw{vcuP%mSDb&M9`+S#dYg??
zDHY!XHiYZc><#!Dcv!ej%`PwTyqLlRXG$ps9ult8j#nQyFsd`73#r*t@Yf(q40PJ@
zcprE~xK2AB=bK+txR-VSh)OvWG2vd?(R>Jh;=+-3s@wI2iVaqvs29b;cO>RFqG%8v
z_>NQ>1#c9tbAOUjAXK_p&G(d@(k6b9^tPZzU`w}y@_h<NgG^kznc|8Z4@9uRT$EEQ
z9~POl5ctjP#MZ^rGL1{db?hb>XC@)IjAr&>+AVTihq6K_gL5r2133Xhi$bnpJ1*Ch
zISDxjd2JEh2e=hr8QL-E&;hiANs;ACb{xC|lKpUJ?3@DyB5jwYH_{mx@`5CLE9481
zz0#nk<BUW0J_x={+6P2ua8!J|gWz9*Oa*kD$I1RG<m-?b*QdjwsbZ|G{00OkxcyC6
zsde%@fqfMGG05Wqo!sB-W8hChP6c$lsmcB!<XOmbqSFzr>YIRlp2)FrKezu7Fyspq
z*{?w^L;e!b=}}w({|DslfR1mkWWNKs4yguo(wQuxltrkrt-j9T(epKyvTYC>!t-Rg
zi>8WSAy{`C<S^vPfNlt924ykAECw-%%ur(|I$ULFa5>~Ni|DWr2ajO>2cKC)`7`j>
zain&9SeL`s<s5z&$njL*k-5K)WQ1Ll`!3{rknb;|dmj9kke6$8j%%1-gM)Pp^3fXQ
zbu7d>F#MX4e*nVs%MDJ;c1qz6LwS5h&p!=08_-!CiTuluf8mI;1G+3BgA@iK<Cy<~
zvxxGiP-4*(F1R{0iv7#iBP#qHf{_$nTtxRPa5P%@-6Fa_B3VZuW3FzR;_z7<BIK>&
zUm*y0@o%E^_PsP%nm{s|!oI&-UFhqH9mm@o-tLjNdAwc2+r4<}c7~EfL!)@zzl5*N
z2mziY`0$A(&(H*FOrgeosKLh)KU_ls%`Zd8A#<p4;Q!W`M~!Q!aS$~;&+Mb#cT!HC
z`F#I#VPk_DNVlO}mCiREJb3Tjds5@O5A5E%=YCSV2fEJOnf_Ar%uB`Xp}G_J9q^nQ
N9zJyDSowin{{z(-5>)^I

delta 5054
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
S=09;2|7W9nPE;EEH~$w<*z`dF

diff --git a/atari/res/netsurf.rsh b/atari/res/netsurf.rsh
index 268aff523..6797c054a 100755
--- a/atari/res/netsurf.rsh
+++ b/atari/res/netsurf.rsh
@@ -36,9 +36,10 @@
 #define MAINMENU_M_GHISTORY 53  /* STRING in tree MAINMENU */
 #define MAINMENU_M_ADD_BOOKMARK 55  /* STRING in tree MAINMENU */
 #define MAINMENU_M_BOOKMARKS 56  /* STRING in tree MAINMENU */
-#define MAINMENU_M_CHOICES 58  /* STRING in tree MAINMENU */
-#define MAINMENU_M_VLOG 59  /* STRING in tree MAINMENU */
-#define MAINMENU_M_HELP_CONTENT 61  /* STRING in tree MAINMENU */
+#define MAINMENU_M_COOKIES 58  /* STRING in tree MAINMENU */
+#define MAINMENU_M_CHOICES 60  /* STRING in tree MAINMENU */
+#define MAINMENU_M_VLOG 61  /* STRING in tree MAINMENU */
+#define MAINMENU_M_HELP_CONTENT 63  /* STRING in tree MAINMENU */
 
 #define TOOLBAR 1  /* form/dial */
 #define TOOLBAR_AREA_SEARCH 1  /* BOX in tree TOOLBAR */
@@ -209,3 +210,7 @@
 #define POP_FONT_RENDERER 15  /* form/dial */
 #define POP_FONT_RENDERER_INTERNAL 1  /* STRING in tree POP_FONT_RENDERER */
 #define POP_FONT_RENDERER_FREETYPE 2  /* STRING in tree POP_FONT_RENDERER */
+
+#define TOOLBAR_COOKIES 16  /* form/dial */
+
+#define TOOLBAR_HISTORY 17  /* form/dial */
diff --git a/atari/res/netsurf.rsm b/atari/res/netsurf.rsm
index 2ede40593..27df3d755 100755
--- a/atari/res/netsurf.rsm
+++ b/atari/res/netsurf.rsm
@@ -1,10 +1,10 @@
 ResourceMaster v3.65   
-#C 16@0@0@0@
+#C 18@0@0@0@
 #N 99@32@AZAaza___  _@AZAaza090___  _@@_@
 #FoC-Header@rsm2out@C-Header@rsh@@@[C-Header@0@
 #R 0@0@1@1@2@1@
-#M 20010100@0@7728@641@
-#T 0@1@MAINMENU@@62@@
+#M 20010100@0@7728@643@
+#T 0@1@MAINMENU@@64@@
 #O 4@32@T_FILE@@
 #O 5@32@T_EDIT@@
 #O 6@32@T_VIEW@@
@@ -40,9 +40,10 @@ ResourceMaster v3.65
 #O 53@28@M_GHISTORY@@
 #O 55@28@M_ADD_BOOKMARK@@
 #O 56@28@M_BOOKMARKS@@
-#O 58@28@M_CHOICES@@
-#O 59@28@M_VLOG@@
-#O 61@28@M_HELP_CONTENT@@
+#O 58@28@M_COOKIES@@
+#O 60@28@M_CHOICES@@
+#O 61@28@M_VLOG@@
+#O 63@28@M_HELP_CONTENT@@
 #T 1@2@TOOLBAR@@19@@
 #O 1@20@AREA_SEARCH@@
 #O 2@26@BT_SEARCH_FWD@@
@@ -196,4 +197,6 @@ ResourceMaster v3.65
 #T 15@2@POP_FONT_RENDERER@@3@@
 #O 1@28@INTERNAL@@
 #O 2@28@FREETYPE@@
-#c 22411@
+#T 16@2@TOOLBAR_COOKIES@@1@@
+#T 17@2@TOOLBAR_HISTORY@@1@@
+#c 24594@
diff --git a/atari/toolbar.c b/atari/toolbar.c
index e190c9676..6c08428a1 100644
--- a/atari/toolbar.c
+++ b/atari/toolbar.c
@@ -444,6 +444,7 @@ void toolbar_redraw(struct s_toolbar *tb, GRECT *clip)
 
 	//dbg_grect("toolbar redraw clip", clip);
 
+	/* Redraw the AES objects: */
     objc_draw_grect(tb->form,0,8,clip);
     objc_draw_grect(&throbber_form[tb->throbber.index], 0, 1, clip);
 
@@ -461,6 +462,7 @@ void toolbar_redraw(struct s_toolbar *tb, GRECT *clip)
 		};
 		//dbg_rect("tb textarea clip: ", &r);
 		// TODO: let this be handled by an userdef object redraw function:
+		/* Redraw the url input: */
         textarea_redraw(tb->url.textarea, 0, 0, 0xffffff, 1.0, &r, &toolbar_rdrw_ctx);
     }
 }
@@ -594,7 +596,7 @@ void toolbar_set_url(struct s_toolbar *tb, const char * text)
     LOG((""));
     textarea_set_text(tb->url.textarea, text);
 
-    if (tb->attached) {
+    if (tb->attached && tb->visible) {
         GRECT area;
         toolbar_get_grect(tb, TOOLBAR_AREA_URL, &area);
         window_schedule_redraw_grect(tb->owner, &area);
diff --git a/atari/treeview.c b/atari/treeview.c
index 6dd43d3db..99711c0f4 100644
--- a/atari/treeview.c
+++ b/atari/treeview.c
@@ -68,6 +68,7 @@ struct atari_treeview_window {
 	GUIWIN * window;
 	bool disposing;
 	bool redraw;
+	bool is_open;
 	GRECT rdw_area;
 	POINT extent;
 	POINT click;
@@ -75,20 +76,16 @@ struct atari_treeview_window {
 	struct atari_treeview_callbacks *io;
 };
 
-enum treeview_area_e {
-	TREEVIEW_AREA_WORK = 0,
-	TREEVIEW_AREA_TOOLBAR,
-	TREEVIEW_AREA_CONTENT
-};
-
 /* native GUI event handlers: */
-static void __CDECL on_mbutton_event(struct atari_treeview_window *tvw,
+static void on_mbutton_event(struct atari_treeview_window *tvw,
 									EVMULT_OUT *ev_out, short msg[8]);
-static void __CDECL on_keybd_event(struct atari_treeview_window *tvw,
+static void on_keybd_event(struct atari_treeview_window *tvw,
 									EVMULT_OUT *ev_out, short msg[8]);
-static void __CDECL on_redraw_event(struct atari_treeview_window *tvw,
+static void on_redraw_event(struct atari_treeview_window *tvw,
 									EVMULT_OUT *ev_out, short msg[8]);
 
+/* static utils: */
+static void atari_treeview_dump_info(struct atari_treeview_window *tv, char *s);
 
 /**
  * Schedule a redraw of the treeview content
@@ -116,12 +113,12 @@ static void atari_treeview_redraw_grect_request(struct core_window *cw,
 			tv->rdw_area.g_w = ( oldx1 > newx1 ) ? oldx1 - tv->rdw_area.g_x : newx1 - tv->rdw_area.g_x;
 			tv->rdw_area.g_h = ( oldy1 > newy1 ) ? oldy1 - tv->rdw_area.g_y : newy1 - tv->rdw_area.g_y;
 		}
-		// dbg_grect("atari_treeview_request_redraw", &tv->rdw_area);
+		//dbg_grect("atari_treeview_request_redraw_grect", &tv->rdw_area);
 	}
 }
 
 
-static void atari_treeview_get_grect(ATARI_TREEVIEW_PTR tptr, enum treeview_area_e mode,
+void atari_treeview_get_grect(ATARI_TREEVIEW_PTR tptr, enum treeview_area_e mode,
 									GRECT *dest)
 {
 
@@ -135,40 +132,33 @@ static void atari_treeview_get_grect(ATARI_TREEVIEW_PTR tptr, enum treeview_area
 	}
 }
 
+GUIWIN * atari_treeview_get_gemtk_window(struct atari_treeview_window *tv)
+{
+	return(tv->window);
+}
+
+static void atari_treeview_dump_info(struct atari_treeview_window *tv,
+									char * title)
+{
+	printf("Treeview Dump (%s)\n", title);
+	printf("=================================\n");
+	gemtk_wm_dump_window_info(atari_treeview_get_gemtk_window(tv));
+	GEMTK_DBG_GRECT("Redraw Area: \n", &tv->rdw_area)
+	dbg_grect("Redraw Area2:      \n", &tv->rdw_area);
+	printf("Extent: x: %d, y: %d\n", tv->extent, tv->extent);
+}
+
 
 void atari_treeview_redraw(struct atari_treeview_window *tv)
 {
-	static FONT_PLOTTER vdi_txt_plotter = NULL;
-	FONT_PLOTTER old_txt_plotter;
+	if (tv != NULL && tv->is_open) {
+		if( tv->redraw && ((plot_get_flags() & PLOT_FLAG_OFFSCREEN) == 0) ) {
 
-	VdiHdl plot_vdi_handle = 0;
-	long atari_plot_flags = 0;
-
-	/* TODO: do not use the global vdi handle for plot actions! */
-	/* TODO: implement getter/setter for the vdi handle */
-
-	if (tv != NULL) {
-		if( tv->redraw && ((atari_plot_flags & PLOT_FLAG_OFFSCREEN) == 0) ) {
-
-			plot_vdi_handle = plot_get_vdi_handle();
-			long atari_plot_flags = plot_get_flags();
 			short todo[4];
 			GRECT work;
 			short handle = gemtk_wm_get_handle(tv->window);
 			struct gemtk_wm_scroll_info_s *slid;
 
-/*
-			if (vdi_txt_plotter == NULL) {
-				int err = 0;
-				VdiHdl vdih = plot_get_vdi_handle();
-				vdi_txt_plotter = new_font_plotter(vdih, (char*)"vdi", PLOT_FLAG_TRANS,
-													&err);
-				if(err) {
-					const char * desc = plot_err_str(err);
-					die(("Unable to load vdi font plotter %s -> %s", "vdi", desc ));
-				}
-			}
-*/
 			gemtk_wm_get_grect(tv->window, GEMTK_WM_AREA_CONTENT, &work);
 			slid = gemtk_wm_get_scroll_info(tv->window);
 
@@ -180,26 +170,37 @@ void atari_treeview_redraw(struct atari_treeview_window *tv)
 			plot_set_dimensions(work.g_x, work.g_y, work.g_w, work.g_h);
 			if (plot_lock() == false)
 				return;
-/*
-			if(vdi_txt_plotter != NULL){
-				old_txt_plotter = plot_get_text_plotter();
-				plot_set_text_plotter(vdi_txt_plotter);
-			}
-*/
+
 			if( wind_get(handle, WF_FIRSTXYWH,
 							&todo[0], &todo[1], &todo[2], &todo[3] )!=0 ) {
 				while (todo[2] && todo[3]) {
 
 					short pxy[4];
+
+					if(!rc_intersect(&work, (GRECT*)&todo)){
+						if (wind_get(handle, WF_NEXTXYWH,
+							&todo[0], &todo[1], &todo[2], &todo[3])==0) {
+							break;
+						}
+						continue;
+					}
 					pxy[0] = todo[0];
 					pxy[1] = todo[1];
 					pxy[2] = todo[0] + todo[2]-1;
 					pxy[3] = todo[1] + todo[3]-1;
-					vs_clip(plot_vdi_handle, 1, (short*)&pxy);
+					vs_clip(plot_get_vdi_handle(), 1, (short*)&pxy);
+
+					// Debug code: this 3 lines help to inspect the redraw
+					// areas...
+					/*
+					vsf_color(plot_get_vdi_handle(), 3);
+					v_bar(plot_get_vdi_handle(), (short*)&pxy);
+					evnt_timer(500);
+					*/
 
 					/* convert screen to treeview coords: */
-					todo[0] = todo[0] - work.g_x + slid->x_pos*slid->x_unit_px;
-					todo[1] = todo[1] - work.g_y + slid->y_pos*slid->y_unit_px;
+					todo[0] = todo[0] - work.g_x ;//+ slid->x_pos*slid->x_unit_px;
+					todo[1] = todo[1] - work.g_y ;//+ slid->y_pos*slid->y_unit_px;
 					if( todo[0] < 0 ){
 						todo[2] = todo[2] + todo[0];
 						todo[0] = 0;
@@ -209,27 +210,29 @@ void atari_treeview_redraw(struct atari_treeview_window *tv)
 						todo[1] = 0;
 					}
 
+					// TODO: get slider values
 					if (rc_intersect((GRECT *)&tv->rdw_area,(GRECT *)&todo)) {
-						tv->io->draw(tv, -(slid->x_pos*slid->x_unit_px),
+							struct rect clip;
+
+							clip.x0 = todo[0]+(slid->x_pos*slid->x_unit_px);
+							clip.y0 = todo[1]+(slid->y_pos*slid->y_unit_px);
+							clip.x1 = clip.x0 + todo[2]+(slid->x_pos*slid->x_unit_px);
+							clip.y1 = clip.y0 + todo[3]+(slid->y_pos*slid->y_unit_px);
+
+							tv->io->draw(tv, -(slid->x_pos*slid->x_unit_px),
 										-(slid->y_pos*slid->y_unit_px),
-							todo[0], todo[1], todo[2], todo[3], &ctx);
+												&clip, &ctx);
 					}
-					vs_clip(plot_vdi_handle, 0, (short*)&pxy);
+					vs_clip(plot_get_vdi_handle(), 0, (short*)&pxy);
 					if (wind_get(handle, WF_NEXTXYWH,
 							&todo[0], &todo[1], &todo[2], &todo[3])==0) {
 						break;
 					}
 				}
 			} else {
-				/*
-				plot_set_text_plotter(old_txt_plotter);
-				*/
 				plot_unlock();
 				return;
 			}
-			/*
-			plot_set_text_plotter(old_txt_plotter);
-			*/
 			plot_unlock();
 			tv->redraw = false;
 			tv->rdw_area.g_x = 65000;
@@ -242,6 +245,137 @@ void atari_treeview_redraw(struct atari_treeview_window *tv)
 	}
 }
 
+//
+//// TODO: rename to atari_treeview_draw_content
+//void atari_treeview_redraw(struct atari_treeview_window *tv)
+//{
+//	static FONT_PLOTTER vdi_txt_plotter = NULL;
+//	FONT_PLOTTER old_txt_plotter;
+//
+//	VdiHdl plot_vdi_handle = 0;
+//	long atari_plot_flags = 0;
+//	short pxy[4];
+//	struct rect clip;
+//
+//	/* TODO: do not use the global vdi handle for plot actions! */
+//	/* TODO: implement getter/setter for the vdi handle */
+//
+//	if (tv != NULL && tv->is_open) {
+//		if( tv->redraw && ((atari_plot_flags & PLOT_FLAG_OFFSCREEN) == 0) ) {
+//
+//			atari_treeview_dump_info(tv, "atari_treeview_redraw");
+//
+//			plot_vdi_handle = plot_get_vdi_handle();
+//			long atari_plot_flags = plot_get_flags();
+//			short todo[4];
+//			GRECT work;
+//			short handle = gemtk_wm_get_handle(tv->window);
+//			struct gemtk_wm_scroll_info_s *slid;
+//
+///*
+//			if (vdi_txt_plotter == NULL) {
+//				int err = 0;
+//				VdiHdl vdih = plot_get_vdi_handle();
+//				vdi_txt_plotter = new_font_plotter(vdih, (char*)"vdi", PLOT_FLAG_TRANS,
+//													&err);
+//				if(err) {
+//					const char * desc = plot_err_str(err);
+//					die(("Unable to load vdi font plotter %s -> %s", "vdi", desc ));
+//				}
+//			}
+//*/
+//			gemtk_wm_get_grect(tv->window, GEMTK_WM_AREA_CONTENT, &work);
+//			slid = gemtk_wm_get_scroll_info(tv->window);
+//
+//			struct redraw_context ctx = {
+//				.interactive = true,
+//				.background_images = true,
+//				.plot = &atari_plotters
+//			};
+//			plot_set_dimensions(work.g_x, work.g_y, work.g_w, work.g_h);
+//			if (plot_lock() == false)
+//				return;
+///*
+//			if(vdi_txt_plotter != NULL){
+//				old_txt_plotter = plot_get_text_plotter();
+//				plot_set_text_plotter(vdi_txt_plotter);
+//			}
+//*/
+//			if( wind_get(handle, WF_FIRSTXYWH,
+//							&todo[0], &todo[1], &todo[2], &todo[3] )!=0 ) {
+//				while (todo[2] && todo[3]) {
+//
+//					pxy[0] = todo[0];
+//					pxy[1] = todo[1];
+//					pxy[2] = todo[0] + todo[2]-1;
+//					pxy[3] = todo[1] + todo[3]-1;
+//					//vs_clip(plot_vdi_handle, 1, (short*)&pxy);
+//
+//					/* convert screen to treeview coords: */
+//					todo[0] = todo[0] - work.g_x + slid->x_pos*slid->x_unit_px;
+//					todo[1] = todo[1] - work.g_y + slid->y_pos*slid->y_unit_px;
+//					if( todo[0] < 0 ){
+//						todo[2] = todo[2] + todo[0];
+//						todo[0] = 0;
+//					}
+//					if( todo[1] < 0 ){
+//						todo[3] = todo[3] + todo[1];
+//						todo[1] = 0;
+//					}
+//
+//					clip.x0 = todo[0];
+//					clip.y0 = todo[1];
+//					clip.x1 = clip.x0 + todo[2];
+//					clip.y1 = clip.y0 + todo[3];
+//
+//					clip.x0 = todo[0];
+//					clip.y0 = todo[1];
+//					clip.x1 = clip.x0 + todo[2] ;
+//					clip.y1 = clip.y0 + todo[3] ;
+///*
+//					clip.x0 = 0;
+//					clip.y0 = 0;
+//					clip.x1 = work.g_w;//MAX(tv->extent.x, work.g_w);
+//					clip.y1 = MAX(tv->extent.y, work.g_h)+200;
+//*/
+//					dbg_rect("treeview redraw clip", &clip);
+//
+//					if (rc_intersect((GRECT *)&tv->rdw_area,(GRECT *)&todo)) {
+//						tv->io->draw(tv, -(slid->x_pos*slid->x_unit_px),
+//										-(slid->y_pos*slid->y_unit_px), &clip,
+//										&ctx);
+//
+//						/*tv->io->draw(tv, 0,0, &clip,
+//										&ctx);*/
+//					}
+//					//vs_clip(plot_vdi_handle, 0, (short*)&pxy);
+//					if (wind_get(handle, WF_NEXTXYWH,
+//							&todo[0], &todo[1], &todo[2], &todo[3])==0) {
+//						break;
+//					}
+//				}
+//			} else {
+//				/*
+//				plot_set_text_plotter(old_txt_plotter);
+//				*/
+//				plot_unlock();
+//				return;
+//			}
+//			/*
+//			plot_set_text_plotter(old_txt_plotter);
+//			*/
+//			plot_unlock();
+//			tv->redraw = false;
+//			tv->rdw_area.g_x = 65000;
+//			tv->rdw_area.g_y = 65000;
+//			tv->rdw_area.g_w = -1;
+//			tv->rdw_area.g_h = -1;
+//		} else {
+//			/* just copy stuff from the offscreen buffer */
+//		}
+//	}
+//}
+
 
 /**
  * GEMTK event sink
@@ -272,14 +406,10 @@ static short handle_event(GUIWIN *win, EVMULT_OUT *ev_out, short msg[8])
         on_mbutton_event(tv, ev_out, msg);
     }
 
-	if (tv) {
-
-	}
-/*
-    if(tv != NULL && tv->user_func != NULL){
-		tv->user_func(win, ev_out, msg);
+    if(tv != NULL && tv->io->gemtk_user_func != NULL){
+		tv->io->gemtk_user_func(win, ev_out, msg);
     }
-*/
+
     return(0);
 }
 
@@ -325,12 +455,24 @@ static void __CDECL on_redraw_event(ATARI_TREEVIEW_PTR tptr, EVMULT_OUT *ev_out,
 		return;
 
 	gemtk_wm_get_grect(tv->window, GEMTK_WM_AREA_CONTENT, &work);
+	//dbg_grect("treeview work: ", &work);
+
+	atari_treeview_get_grect(tv, TREEVIEW_AREA_CONTENT, &work);
+	//dbg_grect("treeview work: ", &work);
 	slid = gemtk_wm_get_scroll_info(tv->window);
 
 	clip = work;
-	if ( !rc_intersect( (GRECT*)&msg[4], &clip ) ) return;
+
+	/* check if the redraw area intersects with the content area: */
+	if ( !rc_intersect( (GRECT*)&msg[4], &clip)) {
+		return;
+	}
+
+	/* make redraw coords relative to content viewport */
 	clip.g_x -= work.g_x;
 	clip.g_y -= work.g_y;
+
+	/* normalize the redraw coords: */
 	if( clip.g_x < 0 ) {
 		clip.g_w = work.g_w + clip.g_x;
 		clip.g_x = 0;
@@ -339,15 +481,19 @@ static void __CDECL on_redraw_event(ATARI_TREEVIEW_PTR tptr, EVMULT_OUT *ev_out,
 		clip.g_h = work.g_h + clip.g_y;
 		clip.g_y = 0;
 	}
+
+	/* Merge redraw coords: */
 	if( clip.g_h > 0 && clip.g_w > 0 ) {
 
 		GRECT rdrw_area;
 
-		rdrw_area.g_x = (slid->x_pos*slid->x_unit_px) + clip.g_x;
-		rdrw_area.g_y =(slid->y_pos*slid->y_unit_px) + clip.g_y;
+		rdrw_area.g_x = clip.g_x;
+		rdrw_area.g_y = clip.g_y;
 		rdrw_area.g_w = clip.g_w;
 		rdrw_area.g_h = clip.g_h;
 
+		//dbg_grect("treeview on_redraw_event ", &rdrw_area);
+
 		atari_treeview_redraw_grect_request(tptr, &rdrw_area);
 	}
 }
@@ -410,7 +556,10 @@ static void __CDECL on_mbutton_event(ATARI_TREEVIEW_PTR tptr, EVMULT_OUT *ev_out
 
 			tv->startdrag.x = origin_rel_x;
 			tv->startdrag.y = origin_rel_y;
-
+			/* First, report mouse press, to trigger entry selection */
+			tv->io->mouse_action(tv, BROWSER_MOUSE_CLICK_1 | BROWSER_MOUSE_PRESS_1, cur_rel_x,
+									cur_rel_y);
+			atari_treeview_redraw(tv);
 			tv->io->mouse_action(tv, BROWSER_MOUSE_DRAG_1 | BROWSER_MOUSE_DRAG_ON,
 								cur_rel_x, cur_rel_y);
 			do{
@@ -477,9 +626,15 @@ atari_treeview_create(GUIWIN *win, struct atari_treeview_callbacks * callbacks,
 	slid->x_unit_px = 16;
 
 	assert(cw->io);
-	assert(cw->io->init);
+	assert(cw->io->init_phase2);
 
-	nserror err = cw->io->init(cw, &cw_t);
+	/* Now that the window is configured for treeview content,			*/
+	/* call init_phase2 which must create the treeview 					*/
+	/* descriptor, and at least setup the the default					*/
+	/* event handlers of the treeview:			 						*/
+	/* It would be more simple to not pass around the callbacks			*/
+	/* but the treeview constructor requires them for initialization...	*/
+	nserror err = cw->io->init_phase2(cw, &cw_t);
 	if (err != NSERROR_OK) {
 		free(cw);
 		cw = NULL;
@@ -491,14 +646,37 @@ atari_treeview_create(GUIWIN *win, struct atari_treeview_callbacks * callbacks,
 void atari_treeview_delete(struct atari_treeview_window * cw)
 {
 	assert(cw);
-	assert(cw->io->fini);
+	assert(cw->io->finish);
 
-	cw->io->fini(cw);
+	cw->io->finish(cw);
 
 	free(cw);
 }
 
 
+void atari_treeview_open(struct atari_treeview_window *cw, GRECT *pos)
+{
+	if (cw->window != NULL) {
+		cw->is_open = true;
+		wind_open_grect(gemtk_wm_get_handle(cw->window), pos);
+		gemtk_wm_link(cw->window);
+	}
+}
+
+bool atari_treeview_is_open(struct atari_treeview_window *cw)
+{
+	return(cw->is_open);
+}
+
+void atari_treeview_close(struct atari_treeview_window *cw)
+{
+	if (cw->window != NULL) {
+		cw->is_open = false;
+		wind_close(gemtk_wm_get_handle(cw->window));
+		gemtk_wm_unlink(cw->window);
+	}
+}
+
 
 /**
  * Core Window Callbacks:
@@ -513,9 +691,21 @@ void atari_treeview_delete(struct atari_treeview_window * cw)
 void atari_treeview_redraw_request(struct core_window *cw, const struct rect *r)
 {
 	GRECT area;
+	struct gemtk_wm_scroll_info_s * slid;
+	struct atari_treeview_window * tv = (cw);
 
 	RECT_TO_GRECT(r, &area)
 
+	slid = gemtk_wm_get_scroll_info(tv->window);
+
+	//dbg_rect("redraw rect request", r);
+
+	// treeview redraw is always full window width:
+	area.g_x = 0;
+	area.g_w = area.g_w;
+	// but vertical redraw region is clipped:
+	area.g_y = r->y0 - (slid->y_pos*slid->y_unit_px);
+	area.g_h = r->y1 - r->y0;
 	atari_treeview_redraw_grect_request(cw, &area);
 }
 
@@ -528,7 +718,40 @@ void atari_treeview_redraw_request(struct core_window *cw, const struct rect *r)
  */
 void atari_treeview_update_size(struct core_window *cw, int width, int height)
 {
+	GRECT area;
+	struct gemtk_wm_scroll_info_s *slid;
+	struct atari_treeview_window *tv = (struct atari_treeview_window *)cw;
 
+	if (tv != NULL) {
+
+		if (tv->disposing)
+			return;
+
+		/* Get acces to the gemtk window slider settings: */
+		slid = gemtk_wm_get_scroll_info(tv->window);
+
+		/* recalculate and refresh sliders: */
+		atari_treeview_get_grect(tv, TREEVIEW_AREA_CONTENT, &area);
+		if (width > -1) {
+			slid->x_units = (width/slid->x_unit_px);
+		} else {
+			slid->x_units = 1;
+		}
+
+		if (height > -1) {
+			slid->y_units = (height/slid->y_unit_px);
+		} else {
+			slid->y_units = 1;
+		}
+
+		tv->extent.x = width;
+		tv->extent.y = height;
+
+
+		/*printf("units content: %d, units viewport: %d\n", (height/slid->y_unit_px),
+					(area.g_h/slid->y_unit_px));*/
+		gemtk_wm_update_slider(tv->window, GEMTK_WM_VH_SLIDER);
+	}
 }
 
 
@@ -540,7 +763,8 @@ void atari_treeview_update_size(struct core_window *cw, int width, int height)
  */
 void atari_treeview_scroll_visible(struct core_window *cw, const struct rect *r)
 {
-
+	/* atari frontend doesn't support dragging outside the treeview */
+	/* so there is no need to implement this? 						*/
 }
 
 
@@ -554,7 +778,13 @@ void atari_treeview_scroll_visible(struct core_window *cw, const struct rect *r)
 void atari_treeview_get_window_dimensions(struct core_window *cw,
 		int *width, int *height)
 {
-
+	if (cw != NULL && (width != NULL || height != NULL)) {
+		GRECT work;
+		struct atari_treeview_window *tv = (struct atari_treeview_window *)cw;
+		atari_treeview_get_grect(tv, TREEVIEW_AREA_CONTENT, &work);
+		*width = work.g_w;
+		*height = work.g_h;
+	}
 }
 
 
diff --git a/atari/treeview.h b/atari/treeview.h
index ee01bf265..bab20c435 100644
--- a/atari/treeview.h
+++ b/atari/treeview.h
@@ -27,25 +27,33 @@
 								SMALLER | VSLIDE | HSLIDE | UPARROW | DNARROW \
 								| LFARROW | RTARROW)
 
+enum treeview_area_e {
+	TREEVIEW_AREA_WORK = 0,
+	TREEVIEW_AREA_TOOLBAR,
+	TREEVIEW_AREA_CONTENT
+};
 
 struct core_window;
 struct atari_treeview_window;
+
 typedef struct atari_treeview_window *ATARI_TREEVIEW_PTR;
 
+// TODO: add drag_status callback!!
+typedef nserror (*atari_treeview_init2_callback)(struct core_window *cw,
+				struct core_window_callback_table * default_callbacks);
+typedef void (*atari_treeview_finish_callback)(struct core_window *cw);
 typedef void (*atari_treeview_keypress_callback)(struct core_window *cw,
-												long ucs4);
+												uint32_t ucs4);
 typedef void (*atari_treeview_mouse_action_callback)(struct core_window *cw,
 												browser_mouse_state mouse,
 												int x, int y);
 typedef void (*atari_treeview_draw_callback)(struct core_window *cw, int x,
-											int y, int clip_x, int clip_y,
-											int clip_width, int clip_height,
+											int y, struct rect *clip,
 											const struct redraw_context *ctx);
 
 struct atari_treeview_callbacks {
-	nserror (*init)(struct core_window *cw,
-				struct core_window_callback_table * default_callbacks);
-	void (*fini)(struct core_window *cw);
+	atari_treeview_init2_callback init_phase2;
+	atari_treeview_finish_callback finish;
 	atari_treeview_draw_callback draw;
 	atari_treeview_keypress_callback keypress;
 	atari_treeview_mouse_action_callback mouse_action;
@@ -56,6 +64,12 @@ struct atari_treeview_window *
 atari_treeview_create(GUIWIN *win, struct atari_treeview_callbacks * callbacks,
 					uint32_t flags);
 void atari_treeview_delete(struct atari_treeview_window * cw);
-
+void atari_treeview_open(struct atari_treeview_window * cw, GRECT *pos);
+bool atari_treeview_is_open(struct atari_treeview_window *cw);
+void atari_treeview_close(struct atari_treeview_window * cw);
+GUIWIN * atari_treeview_get_gemtk_window(struct atari_treeview_window *tv);
+void atari_treeview_get_grect(ATARI_TREEVIEW_PTR tptr, enum treeview_area_e mode,
+									GRECT *dest);
+void atari_treeview_redraw(struct atari_treeview_window *tv);
 #endif //NSATARI_TREEVIEW_H