summaryrefslogtreecommitdiff
path: root/desktop
diff options
context:
space:
mode:
Diffstat (limited to 'desktop')
-rw-r--r--desktop/Makefile6
-rw-r--r--desktop/browser.c607
-rw-r--r--desktop/browser.h205
-rw-r--r--desktop/browser_history.c (renamed from desktop/local_history.c)845
-rw-r--r--desktop/browser_history.h141
-rw-r--r--desktop/browser_private.h17
-rw-r--r--desktop/cookie_manager.c10
-rw-r--r--desktop/cookie_manager.h4
-rw-r--r--desktop/download.c34
-rw-r--r--desktop/download.h11
-rw-r--r--desktop/frames.c14
-rw-r--r--desktop/global_history.c40
-rw-r--r--desktop/global_history.h4
-rw-r--r--desktop/gui.h604
-rw-r--r--desktop/gui_factory.c705
-rw-r--r--desktop/gui_factory.h39
-rw-r--r--desktop/hotlist.c33
-rw-r--r--desktop/hotlist.h4
-rw-r--r--desktop/knockout.c7
-rw-r--r--desktop/local_history.h131
-rw-r--r--desktop/mouse.h17
-rw-r--r--desktop/netsurf.c143
-rw-r--r--desktop/netsurf.h30
-rw-r--r--desktop/options.h2
-rw-r--r--desktop/plotters.h5
-rw-r--r--desktop/save_complete.c109
-rw-r--r--desktop/save_text.c16
-rw-r--r--desktop/scrollbar.c7
-rw-r--r--desktop/search.c64
-rw-r--r--desktop/search.h56
-rw-r--r--desktop/searchweb.c703
-rw-r--r--desktop/searchweb.h112
-rw-r--r--desktop/selection.c10
-rw-r--r--desktop/sslcert_viewer.c27
-rw-r--r--desktop/sslcert_viewer.h1
-rw-r--r--desktop/system_colour.c36
-rw-r--r--desktop/system_colour.h (renamed from desktop/401login.h)25
-rw-r--r--desktop/textarea.c85
-rw-r--r--desktop/textarea.h7
-rw-r--r--desktop/textinput.c9
-rw-r--r--desktop/tree.c16
-rw-r--r--desktop/tree.h13
-rw-r--r--desktop/treeview.c209
-rw-r--r--desktop/treeview.h12
-rw-r--r--desktop/version.c6
45 files changed, 3517 insertions, 1664 deletions
diff --git a/desktop/Makefile b/desktop/Makefile
index f7020074e..218f60e67 100644
--- a/desktop/Makefile
+++ b/desktop/Makefile
@@ -8,12 +8,12 @@ S_DESKTOP := cookie_manager.c knockout.c hotlist.c mouse.c \
S_DESKTOP := $(addprefix desktop/,$(S_DESKTOP))
# version.c needs the testament
-desktop/version.c: testament utils/testament.h
+desktop/version.c: testament $(OBJROOT)/testament.h
# S_BROWSER are sources related to full browsers but are common
# between RISC OS, GTK, BeOS and AmigaOS builds
-S_BROWSER := browser.c download.c frames.c local_history.c netsurf.c \
- save_complete.c save_text.c selection.c textinput.c
+S_BROWSER := browser.c browser_history.c download.c frames.c netsurf.c \
+ save_complete.c save_text.c selection.c textinput.c gui_factory.c
S_BROWSER := $(addprefix desktop/,$(S_BROWSER))
diff --git a/desktop/browser.c b/desktop/browser.c
index d159a5599..1fa9de648 100644
--- a/desktop/browser.c
+++ b/desktop/browser.c
@@ -41,15 +41,14 @@
#include "content/fetch.h"
#include "content/hlcache.h"
#include "content/urldb.h"
-#include "desktop/401login.h"
+#include "desktop/browser_history.h"
#include "desktop/browser_private.h"
#include "desktop/download.h"
#include "desktop/frames.h"
#include "desktop/global_history.h"
-#include "desktop/gui.h"
+#include "desktop/gui_factory.h"
#include "desktop/hotlist.h"
#include "desktop/knockout.h"
-#include "desktop/local_history.h"
#include "utils/nsoption.h"
#include "desktop/scrollbar.h"
#include "desktop/selection.h"
@@ -60,22 +59,18 @@
#include "render/form.h"
#include "render/html.h"
#include "render/box.h"
+#include "utils/corestrings.h"
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/nsurl.h"
-#include "utils/schedule.h"
-#include "utils/url.h"
#include "utils/utils.h"
#include "utils/utf8.h"
-/** one or more windows require a reformat */
-bool browser_reformat_pending;
/** maximum frame depth */
#define FRAME_DEPTH 8
-
/**
* Get position of scrollbar widget within browser window.
*
@@ -295,12 +290,12 @@ bool browser_window_redraw_ready(struct browser_window *bw)
return true;
}
-/* exported interface, documented in browser.h */
+/* exported interface, documented in browser_private.h */
void browser_window_update_extent(struct browser_window *bw)
{
if (bw->window != NULL)
/* Front end window */
- gui_window_update_extent(bw->window);
+ guit->window->update_extent(bw->window);
else
/* Core-managed browser window */
browser_window_handle_scrollbars(bw);
@@ -391,7 +386,7 @@ void browser_window_set_drag_type(struct browser_window *bw,
break;
}
- gui_window_drag_start(top_bw->window, gtype, rect);
+ guit->window->drag_start(top_bw->window, gtype, rect);
}
}
@@ -484,7 +479,7 @@ void browser_window_scroll_visible(struct browser_window *bw,
if (bw->window != NULL) {
/* Front end window */
- gui_window_scroll_visible(bw->window,
+ guit->window->scroll_visible(bw->window,
rect->x0, rect->y0, rect->x1, rect->y1);
} else {
/* Core managed browser window */
@@ -499,7 +494,7 @@ void browser_window_scroll_visible(struct browser_window *bw,
void browser_window_set_scroll(struct browser_window *bw, int x, int y)
{
if (bw->window != NULL) {
- gui_window_set_scroll(bw->window, x, y);
+ guit->window->set_scroll(bw->window, x, y);
} else {
if (bw->scroll_x != NULL)
scrollbar_set(bw->scroll_x, x, false);
@@ -661,11 +656,21 @@ bool browser_window_drop_file_at_point(struct browser_window *bw,
return false;
}
+void browser_window_set_gadget_filename(struct browser_window *bw,
+ struct form_control *gadget, const char *fn)
+{
+ html_set_file_gadget_filename(bw->current_content,
+ gadget, fn);
+}
+
/* exported interface, documented in browser.h */
-void browser_window_debug_dump(struct browser_window *bw, FILE *f)
+nserror browser_window_debug_dump(struct browser_window *bw, FILE *f, enum content_debug op)
{
- if (bw->current_content != NULL)
- content_debug_dump(bw->current_content, f);
+ if (bw->current_content == NULL) {
+ return NSERROR_OK;
+ }
+
+ return content_debug_dump(bw->current_content, f, op);
}
/** slow script handler
@@ -683,64 +688,81 @@ static bool slow_script(void *ctx)
}
/* exported interface, documented in desktop/browser.h */
-
-nserror
-browser_window_create(enum browser_window_nav_flags flags,
- nsurl *url,
- nsurl *referrer,
- struct browser_window *clone,
- struct browser_window **ret_bw)
+nserror browser_window_create(enum browser_window_create_flags flags,
+ nsurl *url, nsurl *referrer,
+ struct browser_window *existing,
+ struct browser_window **bw)
{
- struct browser_window *bw;
- struct browser_window *top;
+ gui_window_create_flags gw_flags = GW_CREATE_NONE;
+ struct browser_window *ret;
- /* caller must provide window to clone or be adding to history */
- assert(clone ||
- ((flags & BROWSER_WINDOW_HISTORY) != 0));
+ /* Check parameters */
+ if (flags & BW_CREATE_CLONE) {
+ if (existing == NULL) {
+ assert(0 && "Failed: No existing window provided.");
+ return NSERROR_BAD_PARAMETER;
+ }
+ }
+ if (!(flags & BW_CREATE_HISTORY)) {
+ if (!(flags & BW_CREATE_CLONE) || existing == NULL) {
+ assert(0 && "Failed: Must have existing for history.");
+ return NSERROR_BAD_PARAMETER;
+ }
+ }
- if ((bw = calloc(1, sizeof(struct browser_window))) == NULL) {
+ if ((ret = calloc(1, sizeof(struct browser_window))) == NULL) {
warn_user("NoMemory", 0);
return NSERROR_NOMEM;
}
/* new javascript context for window */
- bw->jsctx = js_newcontext(nsoption_int(script_timeout),
+ ret->jsctx = js_newcontext(nsoption_int(script_timeout),
slow_script,
NULL);
/* Initialise common parts */
- browser_window_initialise_common(bw, clone);
+ browser_window_initialise_common(flags, ret, existing);
/* window characteristics */
- bw->browser_window_type = BROWSER_WINDOW_NORMAL;
- bw->scrolling = SCROLLING_YES;
- bw->border = true;
- bw->no_resize = true;
- bw->last_action = wallclock();
- bw->focus = bw;
-
- /* gui window */
- /* from the front end's pov, it clones the top level browser window,
- * so find that. */
- top = browser_window_get_root(clone);
-
- bw->window = gui_create_browser_window(bw,
- top,
- ((flags & BROWSER_WINDOW_TAB) != 0));
-
- if (bw->window == NULL) {
- browser_window_destroy(bw);
+ ret->browser_window_type = BROWSER_WINDOW_NORMAL;
+ ret->scrolling = SCROLLING_YES;
+ ret->border = true;
+ ret->no_resize = true;
+ ret->last_action = wallclock();
+ ret->focus = ret;
+
+ /* The existing gui_window is on the top-level existing
+ * browser_window. */
+ existing = browser_window_get_root(existing);
+
+ /* Set up gui_window creation flags */
+ if (flags & BW_CREATE_TAB)
+ gw_flags |= GW_CREATE_TAB;
+ if (flags & BW_CREATE_CLONE)
+ gw_flags |= GW_CREATE_CLONE;
+
+ ret->window = guit->window->create(ret,
+ (existing != NULL) ? existing->window : NULL,
+ gw_flags);
+
+ if (ret->window == NULL) {
+ browser_window_destroy(ret);
return NSERROR_BAD_PARAMETER;
}
if (url != NULL) {
- flags |= BROWSER_WINDOW_VERIFIABLE;
- browser_window_navigate(bw, url, referrer, flags, NULL, NULL, NULL);
+ enum browser_window_nav_flags nav_flags = BW_NAVIGATE_NONE;
+ if (flags & BW_CREATE_UNVERIFIABLE)
+ nav_flags |= BW_NAVIGATE_UNVERIFIABLE;
+ if (flags & BW_CREATE_HISTORY)
+ nav_flags |= BW_NAVIGATE_HISTORY;
+ browser_window_navigate(ret, url, referrer, nav_flags, NULL,
+ NULL, NULL);
}
- if (ret_bw != NULL) {
- *ret_bw = bw;
+ if (bw != NULL) {
+ *bw = ret;
}
return NSERROR_OK;
@@ -750,25 +772,39 @@ browser_window_create(enum browser_window_nav_flags flags,
/**
* Initialise common parts of a browser window
*
- * \param bw The window to initialise
- * \param clone The window to clone, or NULL if none
+ * \param flags Flags to control operation
+ * \param bw The window to initialise
+ * \param existing The existing window if cloning, else NULL
*/
-void browser_window_initialise_common(struct browser_window *bw,
- struct browser_window *clone)
+nserror browser_window_initialise_common(enum browser_window_create_flags flags,
+ struct browser_window *bw, struct browser_window *existing)
{
+ nserror err;
assert(bw);
- if (!clone)
- bw->history = history_create();
- else
- bw->history = history_clone(clone->history);
+ if (flags & BW_CREATE_CLONE) {
+ assert(existing != NULL);
+
+ /* clone history */
+ err = browser_window_history_clone(existing, bw);
+
+ /* copy the scale */
+ bw->scale = existing->scale;
+ } else {
+ /* create history */
+ err = browser_window_history_create(bw);
+
+ /* default scale */
+ bw->scale = (float) nsoption_int(scale) / 100.0;
+ }
+
+ if (err != NSERROR_OK)
+ return err;
/* window characteristics */
bw->refresh_interval = -1;
- bw->reformat_pending = false;
bw->drag_type = DRAGGING_NONE;
- bw->scale = (float) nsoption_int(scale) / 100.0;
bw->scroll_x = NULL;
bw->scroll_y = NULL;
@@ -780,6 +816,8 @@ void browser_window_initialise_common(struct browser_window *bw,
bw->status_text_len = 0;
bw->status_match = 0;
bw->status_miss = 0;
+
+ return NSERROR_OK;
}
/**
@@ -808,7 +846,7 @@ browser_window_download(struct browser_window *bw,
NULL, NULL, &l);
if (error == NSERROR_NO_FETCH_HANDLER) {
/* no internal handler for this type, call out to frontend */
- gui_launch_url(nsurl_access(url));
+ error = guit->browser->launch_url(url);
} else if (error != NSERROR_OK) {
LOG(("Failed to fetch download: %d", error));
} else {
@@ -861,7 +899,7 @@ static void browser_window_start_throbber(struct browser_window *bw)
while (bw->parent)
bw = bw->parent;
- gui_window_start_throbber(bw->window);
+ guit->window->start_throbber(bw->window);
}
@@ -878,8 +916,9 @@ static void browser_window_stop_throbber(struct browser_window *bw)
while (bw->parent)
bw = bw->parent;
- if (!browser_window_check_throbber(bw))
- gui_window_stop_throbber(bw->window);
+ if (!browser_window_check_throbber(bw)) {
+ guit->window->stop_throbber(bw->window);
+ }
}
@@ -912,7 +951,7 @@ static nserror browser_window_favicon_callback(hlcache_handle *c,
/* content_get_bitmap on the hlcache_handle should give
* us the favicon bitmap at this point
*/
- gui_window_set_icon(bw->window, c);
+ guit->window->set_icon(bw->window, c);
break;
case CONTENT_MSG_ERROR:
@@ -960,7 +999,6 @@ static nserror browser_window_favicon_callback(hlcache_handle *c,
static void browser_window_update_favicon(hlcache_handle *c,
struct browser_window *bw, struct content_rfc5988_link *link)
{
- lwc_string *icon_str;
nsurl *nsref = NULL;
nsurl *nsurl;
nserror error;
@@ -979,25 +1017,20 @@ static void browser_window_update_favicon(hlcache_handle *c,
bw->failed_favicon = false;
if (link == NULL) {
- /* look for favicon metadata link */
- if (lwc_intern_string("icon", SLEN("icon"),
- &icon_str) == lwc_error_ok) {
- link = content_find_rfc5988_link(c, icon_str);
- lwc_string_unref(icon_str);
- }
+ /* Look for "icon" */
+ link = content_find_rfc5988_link(c, corestring_lwc_icon);
}
if (link == NULL) {
- if (lwc_intern_string("shortcut icon", SLEN("shortcut icon"),
- &icon_str) == lwc_error_ok) {
- link = content_find_rfc5988_link(c, icon_str);
- lwc_string_unref(icon_str);
- }
+ /* Look for "shortcut icon" */
+ link = content_find_rfc5988_link(c,
+ corestring_lwc_shortcut_icon);
}
if (link == NULL) {
lwc_string *scheme;
bool speculative_default = false;
+ bool match;
nsurl = hlcache_handle_get_url(c);
@@ -1005,12 +1038,10 @@ static void browser_window_update_favicon(hlcache_handle *c,
/* If the document was fetched over http(s), then speculate
* that there's a favicon living at /favicon.ico */
- if ((lwc_string_length(scheme) == SLEN("HTTP") &&
- strcasecmp(lwc_string_data(scheme),
- "http") == 0) ||
- (lwc_string_length(scheme) == SLEN("HTTPS") &&
- strcasecmp(lwc_string_data(scheme),
- "https") == 0)) {
+ if ((lwc_string_caseless_isequal(scheme, corestring_lwc_http,
+ &match) == lwc_error_ok && match) ||
+ (lwc_string_caseless_isequal(scheme, corestring_lwc_https,
+ &match) == lwc_error_ok && match)) {
speculative_default = true;
}
@@ -1089,7 +1120,7 @@ static void browser_window_refresh(void *p)
nsurl *url;
nsurl *refresh;
hlcache_handle *parent = NULL;
- enum browser_window_nav_flags flags = BROWSER_WINDOW_NONE;
+ enum browser_window_nav_flags flags = BW_NAVIGATE_UNVERIFIABLE;
assert(bw->current_content != NULL &&
(content_get_status(bw->current_content) ==
@@ -1108,7 +1139,7 @@ static void browser_window_refresh(void *p)
url = hlcache_handle_get_url(bw->current_content);
if ((url == NULL) || (nsurl_compare(url, refresh, NSURL_COMPLETE))) {
- flags |= BROWSER_WINDOW_HISTORY;
+ flags |= BW_NAVIGATE_HISTORY;
}
/* Treat an (almost) immediate refresh in a top-level browser window as
@@ -1119,7 +1150,7 @@ static void browser_window_refresh(void *p)
* all.
*/
if (bw->refresh_interval <= 100 && bw->parent == NULL) {
- flags |= BROWSER_WINDOW_VERIFIABLE;
+ flags &= ~BW_NAVIGATE_UNVERIFIABLE;
} else {
parent = bw->current_content;
}
@@ -1162,7 +1193,7 @@ static void browser_window_convert_to_download(struct browser_window *bw,
/**
- * Callback for fetchcache() for browser window fetches.
+ * Callback handler for content event messages.
*/
static nserror browser_window_callback(hlcache_handle *c,
@@ -1177,9 +1208,7 @@ static nserror browser_window_callback(hlcache_handle *c,
browser_window_convert_to_download(bw, event->data.download);
if (bw->current_content != NULL) {
- browser_window_refresh_url_bar(bw,
- hlcache_handle_get_url(bw->current_content),
- bw->frag_id);
+ browser_window_refresh_url_bar(bw);
}
break;
@@ -1227,11 +1256,9 @@ static nserror browser_window_callback(hlcache_handle *c,
browser_window_remove_caret(bw, false);
if (bw->window != NULL) {
- gui_window_new_content(bw->window);
+ guit->window->new_content(bw->window);
- browser_window_refresh_url_bar(bw,
- hlcache_handle_get_url(bw->current_content),
- bw->frag_id);
+ browser_window_refresh_url_bar(bw);
}
/* new content; set scroll_to_top */
@@ -1272,7 +1299,7 @@ static nserror browser_window_callback(hlcache_handle *c,
* after, we only leak the thumbnails when urldb does
* not add the URL.
*/
- history_add(bw->history, c, bw->frag_id);
+ browser_window_history_add(bw, c, bw->frag_id);
}
/* frames */
@@ -1302,12 +1329,13 @@ static nserror browser_window_callback(hlcache_handle *c,
browser_window_stop_throbber(bw);
browser_window_update_favicon(c, bw, NULL);
- history_update(bw->history, c);
+ browser_window_history_update(bw, c);
hotlist_update_url(hlcache_handle_get_url(c));
- if (bw->refresh_interval != -1)
- schedule(bw->refresh_interval,
+ if (bw->refresh_interval != -1) {
+ guit->browser->schedule(bw->refresh_interval * 10,
browser_window_refresh, bw);
+ }
break;
case CONTENT_MSG_ERRORCODE:
@@ -1398,34 +1426,17 @@ static nserror browser_window_callback(hlcache_handle *c,
case CONTENT_MSG_LINK: /* content has an rfc5988 link element */
{
- lwc_string *icon_str;
- lwc_string *shortcut_icon_str;
- bool icon_match = false;
- bool shortcut_icon_match = false;
-
- if (lwc_intern_string("icon", SLEN("icon"),
- &icon_str) == lwc_error_ok) {
- if (lwc_string_caseless_isequal(
- event->data.rfc5988_link->rel,
- icon_str,
- &icon_match) != lwc_error_ok) {
- icon_match = false;
- }
- lwc_string_unref(icon_str);
- }
-
- if (lwc_intern_string("shortcut icon", SLEN("shortcut icon"),
- &shortcut_icon_str) == lwc_error_ok) {
- if (lwc_string_caseless_isequal(
- event->data.rfc5988_link->rel,
- shortcut_icon_str,
- &shortcut_icon_match) != lwc_error_ok) {
- shortcut_icon_match = false;
- }
- lwc_string_unref(shortcut_icon_str);
- }
-
- if (icon_match || shortcut_icon_match) {
+ bool match;
+
+ /* Handle "icon" and "shortcut icon" */
+ if ((lwc_string_caseless_isequal(
+ event->data.rfc5988_link->rel,
+ corestring_lwc_icon,
+ &match) == lwc_error_ok && match) ||
+ (lwc_string_caseless_isequal(
+ event->data.rfc5988_link->rel,
+ corestring_lwc_shortcut_icon,
+ &match) == lwc_error_ok && match)) {
/* it's a favicon perhaps start a fetch for it */
browser_window_update_favicon(c, bw,
event->data.rfc5988_link);
@@ -1478,20 +1489,23 @@ static nserror browser_window_callback(hlcache_handle *c,
switch(event->data.dragsave.type) {
case CONTENT_SAVE_ORIG:
- gui_drag_save_object(GUI_SAVE_OBJECT_ORIG, save,
- root->window);
+ guit->window->drag_save_object(root->window, save,
+ GUI_SAVE_OBJECT_ORIG);
break;
+
case CONTENT_SAVE_NATIVE:
- gui_drag_save_object(GUI_SAVE_OBJECT_NATIVE, save,
- root->window);
+ guit->window->drag_save_object(root->window, save,
+ GUI_SAVE_OBJECT_NATIVE);
break;
+
case CONTENT_SAVE_COMPLETE:
- gui_drag_save_object(GUI_SAVE_COMPLETE, save,
- root->window);
+ guit->window->drag_save_object(root->window, save,
+ GUI_SAVE_COMPLETE);
break;
+
case CONTENT_SAVE_SOURCE:
- gui_drag_save_object(GUI_SAVE_SOURCE, save,
- root->window);
+ guit->window->drag_save_object(root->window, save,
+ GUI_SAVE_SOURCE);
break;
}
}
@@ -1501,7 +1515,7 @@ static nserror browser_window_callback(hlcache_handle *c,
{
/* Content wants a link to be saved */
struct browser_window *root = browser_window_get_root(bw);
- gui_window_save_link(root->window,
+ guit->window->save_link(root->window,
event->data.savelink.url,
event->data.savelink.title);
}
@@ -1555,8 +1569,16 @@ static nserror browser_window_callback(hlcache_handle *c,
event->data.selection.read_only);
break;
+ case CONTENT_MSG_GADGETCLICK:
+ if (event->data.gadget_click.gadget->type == GADGET_FILE) {
+ guit->window->file_gadget_open(bw->window, c,
+ event->data.gadget_click.gadget);
+ }
+
+ break;
+
default:
- assert(0);
+ break;
}
return NSERROR_OK;
@@ -1604,10 +1626,17 @@ void browser_window_destroy_internal(struct browser_window *bw)
LOG(("Destroying window"));
- if (bw->children != NULL || bw->iframes != NULL)
+ if (bw->children != NULL || bw->iframes != NULL) {
browser_window_destroy_children(bw);
+ }
- schedule_remove(browser_window_refresh, bw);
+ /* clear any pending callbacks */
+ guit->browser->schedule(-1, browser_window_refresh, bw);
+ /* The ugly cast here is so the reformat function can be
+ * passed a gui window pointer in its API rather than void*
+ */
+ LOG(("Clearing schedule %p(%p)", guit->window->reformat, bw->window));
+ guit->browser->schedule(-1, (void(*)(void*))guit->window->reformat, bw->window);
/* If this brower window is not the root window, and has focus, unset
* the root browser window's focus pointer. */
@@ -1629,7 +1658,7 @@ void browser_window_destroy_internal(struct browser_window *bw)
if (bw->window) {
/* Only the root window has a GUI window */
- gui_window_destroy(bw->window);
+ guit->window->destroy(bw->window);
}
if (bw->loading_content != NULL) {
@@ -1679,7 +1708,7 @@ void browser_window_destroy_internal(struct browser_window *bw)
if (bw->frag_id != NULL)
lwc_string_unref(bw->frag_id);
- history_destroy(bw->history);
+ browser_window_history_destroy(bw);
free(bw->name);
free(bw->status_text);
@@ -1705,6 +1734,70 @@ void browser_window_destroy(struct browser_window *bw)
}
+/**
+ * Update URL bar for a given browser window to given URL
+ *
+ * \param bw Browser window to update URL bar for.
+ * \param url URL for content displayed by bw including any fragment.
+ */
+
+static inline void browser_window_refresh_url_bar_internal(
+ struct browser_window *bw, nsurl *url)
+{
+ assert(bw);
+ assert(url);
+
+ if (bw->parent != NULL) {
+ /* Not root window; don't set a URL in GUI URL bar */
+ return;
+ }
+
+ guit->window->set_url(bw->window, nsurl_access(url));
+}
+
+
+/**
+ * Update URL bar for a given browser window to bw's content's URL
+ *
+ * \param bw Browser window to update URL bar for.
+ */
+
+void browser_window_refresh_url_bar(struct browser_window *bw)
+{
+ assert(bw);
+
+ if (bw->parent != NULL) {
+ /* Not root window; don't set a URL in GUI URL bar */
+ return;
+ }
+
+ if (bw->current_content == NULL) {
+ /* TODO: set "about:blank"? */
+ return;
+ }
+
+ if (bw->frag_id == NULL) {
+ browser_window_refresh_url_bar_internal(bw,
+ hlcache_handle_get_url(bw->current_content));
+ } else {
+ nsurl *display_url;
+ nserror error;
+
+ /* Combine URL and Fragment */
+ error = nsurl_refragment(
+ hlcache_handle_get_url(bw->current_content),
+ bw->frag_id, &display_url);
+ if (error != NSERROR_OK) {
+ warn_user("NoMemory", 0);
+ return;
+ }
+
+ browser_window_refresh_url_bar_internal(bw, display_url);
+ nsurl_unref(display_url);
+ }
+}
+
+
/* exported interface documented in desktop/browser.h */
nserror browser_window_navigate(struct browser_window *bw,
nsurl *url,
@@ -1738,7 +1831,7 @@ nserror browser_window_navigate(struct browser_window *bw,
}
/* Set up retrieval parameters */
- if ((flags & BROWSER_WINDOW_VERIFIABLE) != 0) {
+ if (!(flags & BW_NAVIGATE_UNVERIFIABLE)) {
fetch_flags |= LLCACHE_RETRIEVE_VERIFIABLE;
}
@@ -1762,7 +1855,7 @@ nserror browser_window_navigate(struct browser_window *bw,
}
/* Get download out of the way */
- if ((flags & BROWSER_WINDOW_DOWNLOAD) != 0) {
+ if ((flags & BW_NAVIGATE_DOWNLOAD) != 0) {
error = browser_window_download(bw,
url,
referrer,
@@ -1807,18 +1900,15 @@ nserror browser_window_navigate(struct browser_window *bw,
nsurl_unref(referrer);
}
- if ((flags & BROWSER_WINDOW_HISTORY) != 0) {
- history_add(bw->history,
+ if ((flags & BW_NAVIGATE_HISTORY) != 0) {
+ browser_window_history_add(bw,
bw->current_content, bw->frag_id);
}
browser_window_update(bw, false);
if (bw->current_content != NULL) {
- browser_window_refresh_url_bar(bw,
- hlcache_handle_get_url(
- bw->current_content),
- bw->frag_id);
+ browser_window_refresh_url_bar(bw);
}
return NSERROR_OK;
}
@@ -1831,10 +1921,10 @@ nserror browser_window_navigate(struct browser_window *bw,
LOG(("Loading '%s'", nsurl_access(url)));
browser_window_set_status(bw, messages_get("Loading"));
- bw->history_add = (flags & BROWSER_WINDOW_HISTORY);
+ bw->history_add = (flags & BW_NAVIGATE_HISTORY);
/* Verifiable fetches may trigger a download */
- if ((flags & BROWSER_WINDOW_VERIFIABLE) != 0) {
+ if (!(flags & BW_NAVIGATE_UNVERIFIABLE)) {
fetch_flags |= HLCACHE_RETRIEVE_MAY_DOWNLOAD;
}
@@ -1850,12 +1940,12 @@ nserror browser_window_navigate(struct browser_window *bw,
case NSERROR_OK:
bw->loading_content = c;
browser_window_start_throbber(bw);
- browser_window_refresh_url_bar(bw, url, NULL);
+ browser_window_refresh_url_bar_internal(bw, url);
break;
case NSERROR_NO_FETCH_HANDLER: /* no handler for this type */
/** @todo does this always try and download even unverifiable content? */
- gui_launch_url(nsurl_access(url));
+ error = guit->browser->launch_url(url);
break;
default: /* report error to user */
@@ -1878,6 +1968,85 @@ nserror browser_window_navigate(struct browser_window *bw,
}
+/* Exported interface, documented in browser.h */
+nsurl* browser_window_get_url(struct browser_window *bw)
+{
+ assert(bw != NULL);
+
+ if (bw->current_content != NULL) {
+ return hlcache_handle_get_url(bw->current_content);
+
+ } else if (bw->loading_content != NULL) {
+ /* TODO: should we return this? */
+ return hlcache_handle_get_url(bw->loading_content);
+ }
+
+ return corestring_nsurl_about_blank;
+}
+
+/* Exported interface, documented in browser.h */
+const char* browser_window_get_title(struct browser_window *bw)
+{
+ assert(bw != NULL);
+
+ if (bw->current_content != NULL) {
+ return content_get_title(bw->current_content);
+ }
+
+ return NULL;
+}
+
+/* Exported interface, documented in browser.h */
+struct history * browser_window_get_history(struct browser_window *bw)
+{
+ assert(bw != NULL);
+
+ return bw->history;
+}
+
+
+/* Exported interface, documented in browser.h */
+bool browser_window_has_content(struct browser_window *bw)
+{
+ assert(bw != NULL);
+
+ if (bw->current_content == NULL) {
+ return false;
+ }
+
+ return true;
+}
+
+/* Exported interface, documented in browser.h */
+struct hlcache_handle *browser_window_get_content(struct browser_window *bw)
+{
+ return bw->current_content;
+}
+
+/* Exported interface, documented in browser.h */
+nserror browser_window_get_extents(struct browser_window *bw, bool scaled,
+ int *width, int *height)
+{
+ assert(bw != NULL);
+
+ if (bw->current_content == NULL) {
+ *width = 0;
+ *height = 0;
+ return NSERROR_BAD_CONTENT;
+ }
+
+ *width = content_get_width(bw->current_content);
+ *height = content_get_height(bw->current_content);
+
+ if (scaled) {
+ *width *= bw->scale;
+ *height *= bw->scale;
+ }
+
+ return NSERROR_OK;
+}
+
+
/*
* Get the dimensions of the area a browser window occupies
*
@@ -1898,7 +2067,7 @@ void browser_window_get_dimensions(struct browser_window *bw,
*height = bw->height;
} else {
/* Front end window */
- gui_window_get_dimensions(bw->window, width, height, scaled);
+ guit->window->get_dimensions(bw->window, width, height, scaled);
}
}
@@ -1945,7 +2114,7 @@ void browser_window_update(struct browser_window *bw, bool scroll_to_top)
case BROWSER_WINDOW_NORMAL:
/* Root browser window, constituting a front end window/tab */
- gui_window_set_title(bw->window,
+ guit->window->set_title(bw->window,
content_get_title(bw->current_content));
browser_window_update_extent(bw);
@@ -1960,7 +2129,7 @@ void browser_window_update(struct browser_window *bw, bool scroll_to_top)
browser_window_set_scroll(bw, x, y);
}
- gui_window_redraw_window(bw->window);
+ guit->window->redraw(bw->window);
break;
@@ -2026,7 +2195,7 @@ void browser_window_update_box(struct browser_window *bw, struct rect *rect)
if (bw->window != NULL) {
/* Front end window */
- gui_window_update_box(bw->window, rect);
+ guit->window->update(bw->window, rect);
} else {
/* Core managed browser window */
browser_window_get_position(bw, true, &pos_x, &pos_y);
@@ -2038,7 +2207,7 @@ void browser_window_update_box(struct browser_window *bw, struct rect *rect)
rect->x1 += pos_x / bw->scale;
rect->y1 += pos_y / bw->scale;
- gui_window_update_box(top->window, rect);
+ guit->window->update(top->window, rect);
}
}
@@ -2068,7 +2237,7 @@ void browser_window_stop(struct browser_window *bw)
assert(error == NSERROR_OK);
}
- schedule_remove(browser_window_refresh, bw);
+ guit->browser->schedule(-1, browser_window_refresh, bw);
if (bw->children) {
children = bw->rows * bw->cols;
@@ -2082,9 +2251,7 @@ void browser_window_stop(struct browser_window *bw)
}
if (bw->current_content != NULL) {
- browser_window_refresh_url_bar(bw,
- hlcache_handle_get_url(bw->current_content),
- bw->frag_id);
+ browser_window_refresh_url_bar(bw);
}
browser_window_stop_throbber(bw);
@@ -2136,7 +2303,7 @@ void browser_window_reload(struct browser_window *bw, bool all)
browser_window_navigate(bw,
hlcache_handle_get_url(bw->current_content),
NULL,
- BROWSER_WINDOW_VERIFIABLE,
+ BW_NAVIGATE_NONE,
NULL,
NULL,
NULL);
@@ -2179,7 +2346,7 @@ void browser_window_set_status(struct browser_window *bw, const char *text)
}
bw->status_miss++;
- gui_window_set_status(bw->window, bw->status_text);
+ guit->window->set_status(bw->window, bw->status_text);
}
@@ -2221,9 +2388,19 @@ void browser_window_set_pointer(struct browser_window *bw,
gui_shape = (gui_pointer_shape)shape;
}
- gui_window_set_pointer(root->window, gui_shape);
+ guit->window->set_pointer(root->window, gui_shape);
}
+/* exported function documented in desktop/browser.h */
+nserror browser_window_schedule_reformat(struct browser_window *bw)
+{
+ /* The ugly cast here is so the reformat function can be
+ * passed a gui window pointer in its API rather than void*
+ */
+ LOG(("Scheduleing %p(%p)", guit->window->reformat, bw->window));
+ guit->browser->schedule(0, (void(*)(void*))guit->window->reformat, bw->window);
+ return NSERROR_OK;
+}
/**
* Reformat a browser window contents to a new width or height.
@@ -2275,8 +2452,7 @@ static void browser_window_set_scale_internal(struct browser_window *bw,
if (content_can_reformat(c) == false) {
browser_window_update(bw, false);
} else {
- bw->reformat_pending = true;
- browser_reformat_pending = true;
+ browser_window_schedule_reformat(bw);
}
}
@@ -2287,14 +2463,7 @@ static void browser_window_set_scale_internal(struct browser_window *bw,
}
-/**
- * Sets the scale of a browser window
- *
- * \param bw The browser window to scale
- * \param scale The new scale
- * \param all Scale all windows in the tree (ie work up aswell as down)
- */
-
+/* exported interface documented in desktop/browser.h */
void browser_window_set_scale(struct browser_window *bw, float scale, bool all)
{
while (bw->parent && all)
@@ -2309,59 +2478,13 @@ void browser_window_set_scale(struct browser_window *bw, float scale, bool all)
}
-/**
- * Gets the scale of a browser window
- *
- * \param bw The browser window to scale
- * \return
- */
-
+/* exported interface documented in desktop/browser.h */
float browser_window_get_scale(struct browser_window *bw)
{
return bw->scale;
}
-/**
- * Update URL bar for a given browser window to given URL
- *
- * \param bw Browser window to update URL bar for.
- * \param url URL for content displayed by bw, excluding any fragment.
- * \param frag Additional fragment. May be NULL if none.
- */
-
-void browser_window_refresh_url_bar(struct browser_window *bw, nsurl *url,
- lwc_string *frag)
-{
- assert(bw);
- assert(url);
-
- if (bw->parent != NULL) {
- /* Not root window; don't set a URL in GUI URL bar */
- return;
- }
-
- if (frag == NULL) {
- /* With no fragment, we may as well pass url straight through
- * saving a malloc, copy, free cycle.
- */
- gui_window_set_url(bw->window, nsurl_access(url));
- } else {
- nsurl *display_url;
- nserror error;
-
- error = nsurl_refragment(url, frag, &display_url);
- if (error != NSERROR_OK) {
- warn_user("NoMemory", 0);
- return;
- }
-
- gui_window_set_url(bw->window, nsurl_access(display_url));
- nsurl_unref(display_url);
- }
-}
-
-
static void browser_window_find_target_internal(struct browser_window *bw,
const char *target, int depth, struct browser_window *page,
int *rdepth, struct browser_window **bw_target)
@@ -2462,8 +2585,9 @@ struct browser_window *browser_window_find_target(struct browser_window *bw,
* OR
* - button_2 opens in new tab and the link target is "_blank"
*/
- error = browser_window_create(BROWSER_WINDOW_VERIFIABLE |
- BROWSER_WINDOW_TAB,
+ error = browser_window_create(BW_CREATE_TAB |
+ BW_CREATE_HISTORY |
+ BW_CREATE_CLONE,
NULL,
NULL,
bw,
@@ -2489,7 +2613,8 @@ struct browser_window *browser_window_find_target(struct browser_window *bw,
* - button_2 doesn't open in new tabs and the link target is
* "_blank"
*/
- error = browser_window_create(BROWSER_WINDOW_VERIFIABLE,
+ error = browser_window_create(BW_CREATE_HISTORY |
+ BW_CREATE_CLONE,
NULL,
NULL,
bw,
@@ -2528,7 +2653,7 @@ struct browser_window *browser_window_find_target(struct browser_window *bw,
if (!nsoption_bool(target_blank))
return bw;
- error = browser_window_create(BROWSER_WINDOW_VERIFIABLE,
+ error = browser_window_create(BW_CREATE_CLONE | BW_CREATE_HISTORY,
NULL,
NULL,
bw,
@@ -2879,14 +3004,14 @@ void browser_window_mouse_click(struct browser_window *bw,
break;
default:
if (mouse & BROWSER_MOUSE_MOD_2) {
- if (mouse & BROWSER_MOUSE_DRAG_2)
- gui_drag_save_object(GUI_SAVE_OBJECT_NATIVE, c,
- bw->window);
- else if (mouse & BROWSER_MOUSE_DRAG_1)
- gui_drag_save_object(GUI_SAVE_OBJECT_ORIG, c,
- bw->window);
- }
- else if (mouse & (BROWSER_MOUSE_DRAG_1 |
+ if (mouse & BROWSER_MOUSE_DRAG_2) {
+ guit->window->drag_save_object(bw->window, c,
+ GUI_SAVE_OBJECT_NATIVE);
+ } else if (mouse & BROWSER_MOUSE_DRAG_1) {
+ guit->window->drag_save_object(bw->window, c,
+ GUI_SAVE_OBJECT_ORIG);
+ }
+ } else if (mouse & (BROWSER_MOUSE_DRAG_1 |
BROWSER_MOUSE_DRAG_2)) {
browser_window_page_drag_start(bw, x, y);
browser_window_set_pointer(bw, BROWSER_POINTER_MOVE);
@@ -2932,10 +3057,10 @@ void browser_window_page_drag_start(struct browser_window *bw, int x, int y)
if (bw->window != NULL) {
/* Front end window */
- gui_window_get_scroll(bw->window, &bw->drag_start_scroll_x,
+ guit->window->get_scroll(bw->window, &bw->drag_start_scroll_x,
&bw->drag_start_scroll_y);
- gui_window_scroll_start(bw->window);
+ guit->window->scroll_start(bw->window);
} else {
/* Core managed browser window */
bw->drag_start_scroll_x = scrollbar_get_offset(bw->scroll_x);
@@ -2953,7 +3078,8 @@ void browser_window_page_drag_start(struct browser_window *bw, int x, int y)
bool browser_window_back_available(struct browser_window *bw)
{
- return (bw && bw->history && history_back_available(bw->history));
+ return (bw && bw->history &&
+ browser_window_history_back_available(bw));
}
@@ -2966,7 +3092,8 @@ bool browser_window_back_available(struct browser_window *bw)
bool browser_window_forward_available(struct browser_window *bw)
{
- return (bw && bw->history && history_forward_available(bw->history));
+ return (bw && bw->history &&
+ browser_window_history_forward_available(bw));
}
diff --git a/desktop/browser.h b/desktop/browser.h
index ee55e72c4..c7d8b7e79 100644
--- a/desktop/browser.h
+++ b/desktop/browser.h
@@ -25,12 +25,13 @@
#define _NETSURF_DESKTOP_BROWSER_H_
#include <stdbool.h>
+#include <stdio.h>
-#include "content/content.h"
+#include "utils/types.h"
+#include "utils/errors.h"
+#include "desktop/plot_style.h"
#include "desktop/frame_types.h"
-#include "desktop/gui.h"
#include "desktop/mouse.h"
-#include "utils/types.h"
struct browser_window;
@@ -39,7 +40,9 @@ struct gui_window;
struct history;
struct selection;
struct fetch_multipart_data;
-
+struct form_control;
+struct nsurl;
+enum content_debug;
typedef enum {
DRAGGING_NONE,
@@ -59,39 +62,69 @@ typedef enum {
BW_EDITOR_CAN_PASTE = (1 << 2) /**< Can paste, input */
} browser_editor_flags;
-extern bool browser_reformat_pending;
+/** flags to browser_window_create */
+enum browser_window_create_flags {
+ /** No flags set */
+ BW_CREATE_NONE = 0,
-/** flags to browser window go */
+ /** this will form a new history node (don't set for back/reload/etc) */
+ BW_CREATE_HISTORY = (1 << 0),
+
+ /** New gui_window to be tab in same window as "existing" gui_window */
+ BW_CREATE_TAB = (1 << 1),
+
+ /** New gui_window to be clone of "existing" gui_window */
+ BW_CREATE_CLONE = (1 << 2),
+
+ /** Window not opened by user interaction (e.g. JS popup)
+ *
+ * rfc2965:
+ * A transaction is verifiable if the user, or a
+ * user-designated agent, has the option to review
+ * the request-URI prior to its use in the transaction.
+ * A transaction is unverifiable if the user does not
+ * have that option.
+ */
+ BW_CREATE_UNVERIFIABLE = (1 << 3),
+};
+
+/** flags to browser_window_navigate */
enum browser_window_nav_flags {
- BROWSER_WINDOW_NONE = 0,
+ /** No flags set */
+ BW_NAVIGATE_NONE = 0,
+
/** this will form a new history node (don't set for back/reload/etc) */
- BROWSER_WINDOW_HISTORY = 1,
+ BW_NAVIGATE_HISTORY = (1 << 0),
+
/** download rather than render the uri */
- BROWSER_WINDOW_DOWNLOAD = 2,
- /** this transaction is verifiable */
- BROWSER_WINDOW_VERIFIABLE = 4,
- /** open a new tab rather than a new window */
- BROWSER_WINDOW_TAB = 8,
+ BW_NAVIGATE_DOWNLOAD = (1 << 1),
+
+ /** Transation not caused by user interaction (e.g. JS-caused)
+ *
+ * rfc2965:
+ * A transaction is verifiable if the user, or a
+ * user-designated agent, has the option to review
+ * the request-URI prior to its use in the transaction.
+ * A transaction is unverifiable if the user does not
+ * have that option.
+ */
+ BW_NAVIGATE_UNVERIFIABLE = (1 << 2)
};
-void browser_window_initialise_common(struct browser_window *bw,
- struct browser_window *clone);
-
/**
* Create and open a new root browser window with the given page.
*
- * \param flags Flags to control operation
- * \param url URL to start fetching in the new window or NULL for blank
- * \param referer The referring uri or NULL if none
- * \param clone The browser window to clone
- * \param bw pointer to created browser window or untouched on error.
- * \return error code
+ * \param flags Flags to control operation
+ * \param url URL to fetch in the new window or NULL for blank
+ * \param referer The referring uri or NULL if none
+ * \param existing The an existing bw or NULL, required for some flags.
+ * \param bw Updated to created browser window or untouched on error.
+ * \return NSERROR_OK, or appropriate error otherwise.
*/
-nserror browser_window_create(enum browser_window_nav_flags flags,
- nsurl *url,
- nsurl *referrer,
- struct browser_window *clone,
- struct browser_window **bw);
+nserror browser_window_create(enum browser_window_create_flags flags,
+ struct nsurl *url, struct nsurl *referrer,
+ struct browser_window *existing,
+ struct browser_window **bw);
/**
* Start fetching a page in a browser window.
@@ -111,12 +144,64 @@ nserror browser_window_create(enum browser_window_nav_flags flags,
*
*/
nserror browser_window_navigate(struct browser_window *bw,
- nsurl *url,
- nsurl *referrer,
+ struct nsurl *url,
+ struct nsurl *referrer,
enum browser_window_nav_flags flags,
char *post_urlenc,
struct fetch_multipart_data *post_multipart,
- hlcache_handle *parent);
+ struct hlcache_handle *parent);
+
+/**
+ * Get a browser window's URL.
+ *
+ * \param bw browser window
+ * \return pointer to nsurl. Doesn't create a ref for caller.
+ *
+ * Note: guaranteed to return a valid nsurl ptr, never returns NULL.
+ */
+struct nsurl* browser_window_get_url(struct browser_window *bw);
+
+/**
+ * Get the title of a browser_window.
+ *
+ * \param bw The browser window.
+ */
+const char* browser_window_get_title(struct browser_window *bw);
+
+/**
+ * Get a browser window's history object.
+ *
+ * \param bw browser window
+ * \return pointer browser window's history object
+ *
+ * Clients need history object to make use of the history_* functions.
+ */
+struct history * browser_window_get_history(struct browser_window *bw);
+
+/**
+ * Get a browser window's content extents.
+ *
+ * \param bw browser window
+ * \param scaled whether to apply current browser window scale
+ * \param width updated to content width extent in px
+ * \param width updated to content height extent in px
+ * \return NSERROR_OK, or appropriate error otherwise.
+ */
+nserror browser_window_get_extents(struct browser_window *bw, bool scaled,
+ int *width, int *height);
+
+/**
+ * Find out if a browser window is currently showing a content.
+ *
+ * \param bw browser window
+ * \return true iff browser window is showing a content, else false.
+ */
+bool browser_window_has_content(struct browser_window *bw);
+
+/**
+ * Get a cache handle for the content within a browser window.
+ */
+struct hlcache_handle *browser_window_get_content(struct browser_window *bw);
void browser_window_get_dimensions(struct browser_window *bw,
int *width, int *height, bool scaled);
@@ -129,7 +214,24 @@ void browser_window_reload(struct browser_window *bw, bool all);
void browser_window_destroy(struct browser_window *bw);
void browser_window_reformat(struct browser_window *bw, bool background,
int width, int height);
+
+
+/**
+ * Sets the scale of a browser window.
+ *
+ * \param bw The browser window to scale.
+ * \param scale The new scale.
+ * \param all Scale all windows in the tree (ie work up aswell as down)
+ */
void browser_window_set_scale(struct browser_window *bw, float scale, bool all);
+
+
+/**
+ * Gets the scale of a browser window
+ *
+ * \param bw The browser window to get the scale of.
+ * \return The scale of teh window.
+ */
float browser_window_get_scale(struct browser_window *bw);
/**
@@ -173,8 +275,10 @@ bool browser_window_scroll_at_point(struct browser_window *bw,
bool browser_window_drop_file_at_point(struct browser_window *bw,
int x, int y, char *file);
-void browser_window_refresh_url_bar(struct browser_window *bw, nsurl *url,
- lwc_string *frag);
+void browser_window_set_gadget_filename(struct browser_window *bw,
+ struct form_control *gadget, const char *fn);
+
+void browser_window_refresh_url_bar(struct browser_window *bw);
void browser_window_mouse_click(struct browser_window *bw,
browser_mouse_state mouse, int x, int y);
@@ -184,6 +288,21 @@ struct browser_window *browser_window_find_target(
struct browser_window *bw, const char *target,
browser_mouse_state mouse);
+/**
+ * Cause the frontends reformat entry to be called in safe context.
+ *
+ * The browser_window_reformat call cannot safely be called from some
+ * contexts, this call allows for the reformat to happen from a safe
+ * top level context.
+ *
+ * The callback is frontend provided as the context information (size
+ * etc.) about the windowing toolkit is only available to the
+ * frontend.
+ */
+nserror browser_window_schedule_reformat(struct browser_window *bw);
+
+
+
void browser_select_menu_callback(void *client_data,
int x, int y, int width, int height);
@@ -240,15 +359,7 @@ bool browser_window_redraw(struct browser_window *bw, int x, int y,
*/
bool browser_window_redraw_ready(struct browser_window *bw);
-/*
- * Update the extent of the inside of a browser window to that of the current
- * content
- *
- * \param bw browser_window to update the extent of
- */
-void browser_window_update_extent(struct browser_window *bw);
-
-/*
+/**
* Get the position of the current browser window with respect to the root or
* parent browser window
*
@@ -260,7 +371,7 @@ void browser_window_update_extent(struct browser_window *bw);
void browser_window_get_position(struct browser_window *bw, bool root,
int *pos_x, int *pos_y);
-/*
+/**
* Set the position of the current browser window with respect to the parent
* browser window
*
@@ -270,7 +381,7 @@ void browser_window_get_position(struct browser_window *bw, bool root,
*/
void browser_window_set_position(struct browser_window *bw, int x, int y);
-/*
+/**
* Scroll the browser window to display the passed area
*
* \param bw browser window to scroll
@@ -291,7 +402,7 @@ void browser_window_scroll_visible(struct browser_window *bw,
*/
void browser_window_set_scroll(struct browser_window *bw, int x, int y);
-/*
+/**
* Set drag type for a browser window, and inform front end
*
* \param bw browser window to set the type of the current drag for
@@ -301,7 +412,7 @@ void browser_window_set_scroll(struct browser_window *bw, int x, int y);
void browser_window_set_drag_type(struct browser_window *bw,
browser_drag_type type, const struct rect *rect);
-/*
+/**
* Get type of any current drag for a browser window
*
* \param bw browser window to set the type of the current drag for
@@ -309,7 +420,7 @@ void browser_window_set_drag_type(struct browser_window *bw,
*/
browser_drag_type browser_window_get_drag_type(struct browser_window *bw);
-/*
+/**
* Get the root level browser window
*
* \param bw browser window to set the type of the current drag for
@@ -342,7 +453,7 @@ char * browser_window_get_selection(struct browser_window *bw);
* \param bw The browser window
* \param f The file to dump to
*/
-void browser_window_debug_dump(struct browser_window *bw, FILE *f);
+nserror browser_window_debug_dump(struct browser_window *bw, FILE *f, enum content_debug op);
/* In platform specific theme_install.c. */
#ifdef WITH_THEME_INSTALL
diff --git a/desktop/local_history.c b/desktop/browser_history.c
index d4ecfd3bb..8c21eed8e 100644
--- a/desktop/local_history.c
+++ b/desktop/browser_history.c
@@ -26,13 +26,13 @@
#include <stdlib.h>
#include <string.h>
#include <time.h>
+
#include "content/content.h"
#include "content/hlcache.h"
#include "content/urldb.h"
#include "css/css.h"
-#include "desktop/browser.h"
-#include "desktop/gui.h"
-#include "desktop/local_history.h"
+#include "desktop/browser_history.h"
+#include "desktop/browser_private.h"
#include "desktop/plotters.h"
#include "desktop/thumbnail.h"
#include "image/bitmap.h"
@@ -80,75 +80,6 @@ struct history {
int height;
};
-static struct history_entry *history_clone_entry(struct history *history,
- struct history_entry *entry);
-static void history_free_entry(struct history_entry *entry);
-static void history_layout(struct history *history);
-static int history_layout_subtree(struct history *history,
- struct history_entry *entry, int x, int y, bool shuffle);
-static bool history_redraw_entry(struct history *history,
- struct history_entry *entry,
- int x0, int y0, int x1, int y1,
- int x, int y, bool clip, const struct redraw_context *ctx);
-static struct history_entry *history_find_position(struct history_entry *entry,
- int x, int y);
-static bool history_enumerate_entry(const struct history *history,
- const struct history_entry *entry, history_enumerate_cb cb, void *ud);
-
-
-/**
- * Create a new history tree for a window.
- *
- * \return pointer to an opaque history structure, 0 on failure.
- */
-
-struct history *history_create(void)
-{
- struct history *history;
-
- history = calloc(1, sizeof *history);
- if (!history) {
- warn_user("NoMemory", 0);
- return 0;
- }
- history->width = RIGHT_MARGIN / 2;
- history->height = BOTTOM_MARGIN / 2;
- return history;
-}
-
-
-/**
- * Clone a history tree
- *
- * \param history opaque history structure, as returned by history_create()
- *
- * \return pointer to an opaque history structure, 0 on failure.
- */
-
-struct history *history_clone(struct history *history)
-{
- struct history *new_history;
-
- if (!history->start)
- return history_create();
-
- new_history = malloc(sizeof *history);
- if (!new_history)
- return 0;
- memcpy(new_history, history, sizeof *history);
-
- new_history->start = history_clone_entry(new_history,
- new_history->start);
- if (!history->start) {
- LOG(("Insufficient memory to clone history"));
- warn_user("NoMemory", 0);
- history_destroy(new_history);
- return 0;
- }
-
- return new_history;
-}
-
/**
* Clone a history entry
@@ -159,7 +90,8 @@ struct history *history_clone(struct history *history)
* \return a cloned history entry, or 0 on error
*/
-struct history_entry *history_clone_entry(struct history *history,
+static struct history_entry *browser_window_history__clone_entry(
+ struct history *history,
struct history_entry *entry)
{
struct history_entry *child;
@@ -197,7 +129,7 @@ struct history_entry *history_clone_entry(struct history *history,
/* recurse for all children */
for (child = new_entry->forward; child; child = child->next) {
- new_child = history_clone_entry(history, child);
+ new_child = browser_window_history__clone_entry(history, child);
if (new_child) {
new_child->back = new_entry;
} else {
@@ -223,26 +155,360 @@ struct history_entry *history_clone_entry(struct history *history,
/**
+ * Free an entry in the tree recursively.
+ */
+
+static void browser_window_history__free_entry(struct history_entry *entry)
+{
+ if (!entry)
+ return;
+ browser_window_history__free_entry(entry->forward);
+ browser_window_history__free_entry(entry->next);
+ nsurl_unref(entry->page.url);
+ if (entry->page.frag_id)
+ lwc_string_unref(entry->page.frag_id);
+ free(entry->page.title);
+ free(entry);
+}
+
+
+/**
+ * Recursively position a subtree.
+ *
+ * \param history history being laid out
+ * \param entry subtree to position
+ * \param x x position for entry
+ * \param y smallest available y
+ * \param shuffle shuffle layout
+ * \return greatest y used by subtree
+ */
+
+static int browser_window_history__layout_subtree(struct history *history,
+ struct history_entry *entry, int x, int y, bool shuffle)
+{
+ struct history_entry *child;
+ int y1 = y;
+
+ if (history->width < x + WIDTH)
+ history->width = x + WIDTH;
+
+ if (!entry->forward) {
+ entry->x = x;
+ entry->y = y;
+ if (shuffle) {
+ entry->x = rand() % 600;
+ entry->y = rand() % 400;
+ }
+ return y + HEIGHT;
+ }
+
+ /* layout child subtrees below each other */
+ for (child = entry->forward; child; child = child->next) {
+ y1 = browser_window_history__layout_subtree(history, child,
+ x + WIDTH + RIGHT_MARGIN, y1, shuffle);
+ if (child->next)
+ y1 += BOTTOM_MARGIN;
+ }
+
+ /* place ourselves in the middle */
+ entry->x = x;
+ entry->y = (y + y1) / 2 - HEIGHT / 2;
+ if (shuffle) {
+ entry->x = rand() % 600;
+ entry->y = rand() % 400;
+ }
+
+ return y1;
+}
+
+
+/**
+ * Compute node positions.
+ *
+ * \param history history to layout
+ *
+ * Each node's x and y are filled in.
+ */
+
+static void browser_window_history__layout(struct history *history)
+{
+ time_t t = time(0);
+ struct tm *tp = localtime(&t);
+ bool shuffle = tp->tm_mon == 3 && tp->tm_mday == 1;
+
+ if (!history)
+ return;
+
+ history->width = 0;
+ if (history->start)
+ history->height = browser_window_history__layout_subtree(
+ history, history->start,
+ RIGHT_MARGIN / 2, BOTTOM_MARGIN / 2,
+ shuffle);
+ else
+ history->height = 0;
+ if (shuffle) {
+ history->width = 600 + WIDTH;
+ history->height = 400 + HEIGHT;
+ }
+ history->width += RIGHT_MARGIN / 2;
+ history->height += BOTTOM_MARGIN / 2;
+}
+
+/**
+ * Recursively redraw a history_entry.
+ *
+ * \param history history containing the entry
+ * \param history_entry entry to render
+ * \param ctx current redraw context
+ */
+
+static bool browser_window_history__redraw_entry(struct history *history,
+ struct history_entry *entry,
+ int x0, int y0, int x1, int y1,
+ int x, int y, bool clip,
+ const struct redraw_context *ctx)
+{
+ const struct plotter_table *plot = ctx->plot;
+ size_t char_offset;
+ int actual_x;
+ struct history_entry *child;
+ colour c = entry == history->current ?
+ HISTORY_COLOUR_SELECTED : HISTORY_COLOUR_FOREGROUND;
+ int tailsize = 5;
+ int xoffset = x - x0;
+ int yoffset = y - y0;
+ plot_style_t pstyle_history_rect = {
+ .stroke_type = PLOT_OP_TYPE_SOLID,
+ .stroke_colour = c,
+ .stroke_width = entry == history->current ? 3 : 1,
+ };
+ plot_font_style_t fstyle = *plot_style_font;
+
+ if (clip) {
+ struct rect rect;
+ rect.x0 = x0 + xoffset;
+ rect.y0 = y0 + yoffset;
+ rect.x1 = x1 + xoffset;
+ rect.y1 = y1 + yoffset;
+ if(!plot->clip(&rect))
+ return false;
+ }
+
+ if (!plot->bitmap(entry->x + xoffset, entry->y + yoffset, WIDTH, HEIGHT,
+ entry->bitmap, 0xffffff, 0))
+ return false;
+ if (!plot->rectangle(entry->x - 1 + xoffset,
+ entry->y - 1 + yoffset,
+ entry->x + xoffset + WIDTH,
+ entry->y + yoffset + HEIGHT,
+ &pstyle_history_rect))
+ return false;
+
+ if (!nsfont.font_position_in_string(plot_style_font, entry->page.title,
+ strlen(entry->page.title), WIDTH,
+ &char_offset, &actual_x))
+ return false;
+
+ fstyle.background = HISTORY_COLOUR_BACKGROUND;
+ fstyle.foreground = c;
+ fstyle.weight = entry == history->current ? 900 : 400;
+
+ if (!plot->text(entry->x + xoffset, entry->y + HEIGHT + 12 + yoffset,
+ entry->page.title, char_offset, &fstyle))
+ return false;
+
+ for (child = entry->forward; child; child = child->next) {
+ if (!plot->line(entry->x + WIDTH + xoffset,
+ entry->y + HEIGHT / 2 + yoffset,
+ entry->x + WIDTH + tailsize + xoffset,
+ entry->y + HEIGHT / 2 + yoffset,
+ plot_style_stroke_history))
+ return false;
+ if (!plot->line(entry->x + WIDTH + tailsize + xoffset,
+ entry->y + HEIGHT / 2 + yoffset,
+ child->x - tailsize +xoffset,
+ child->y + HEIGHT / 2 + yoffset,
+ plot_style_stroke_history))
+ return false;
+ if (!plot->line(child->x - tailsize + xoffset,
+ child->y + HEIGHT / 2 + yoffset,
+ child->x + xoffset, child->y +
+ HEIGHT / 2 + yoffset,
+ plot_style_stroke_history))
+ return false;
+ if (!browser_window_history__redraw_entry(history, child,
+ x0, y0, x1, y1, x, y, clip, ctx))
+ return false;
+ }
+
+ return true;
+}
+
+
+/**
+ * Find the history entry at a position.
+ *
+ * \param entry entry to search from
+ * \param x coordinate
+ * \param y coordinate
+ * \return an entry if found, 0 if none
+ */
+
+static struct history_entry *browser_window_history__find_position(
+ struct history_entry *entry, int x, int y)
+{
+ struct history_entry *child;
+ struct history_entry *found;
+
+ if (!entry)
+ return 0;
+
+ if (entry->x <= x && x <= entry->x + WIDTH &&
+ entry->y <= y && y <= entry->y + HEIGHT)
+ return entry;
+
+ for (child = entry->forward; child; child = child->next) {
+ found = browser_window_history__find_position(child, x, y);
+ if (found)
+ return found;
+ }
+
+ return 0;
+}
+
+/**
+ * Enumerate subentries in history
+ * See also history_enumerate()
+ *
+ * \param bw The browser window to enumerate history of
+ * \param entry entry to start enumeration at
+ * \param cb callback function
+ * \param ud context pointer passed to cb
+ * \return true to continue enumeration, false to cancel
+ */
+static bool browser_window_history__enumerate_entry(
+ const struct browser_window *bw,
+ const struct history_entry *entry,
+ browser_window_history_enumerate_cb cb,
+ void *ud)
+{
+ const struct history_entry *child;
+
+ if (!cb(bw, entry->x, entry->y,
+ entry->x + WIDTH, entry->y + HEIGHT,
+ entry, ud))
+ return false;
+
+ for (child = entry->forward; child; child = child->next) {
+ if (!browser_window_history__enumerate_entry(bw, child,
+ cb, ud))
+ return false;
+ }
+
+ return true;
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+/**
+ * Create a new history tree for a browser window window.
+ *
+ * \param bw browser window to create history for.
+ *
+ * \return NSERROR_OK or appropriate error otherwise
+ */
+
+nserror browser_window_history_create(struct browser_window *bw)
+{
+ struct history *history;
+
+ bw->history = NULL;
+
+ history = calloc(1, sizeof *history);
+ if (!history) {
+ warn_user("NoMemory", 0);
+ return NSERROR_NOMEM;
+ }
+ history->width = RIGHT_MARGIN / 2;
+ history->height = BOTTOM_MARGIN / 2;
+
+ bw->history = history;
+ return NSERROR_OK;
+}
+
+
+/**
+ * Clone a bw's history tree for new bw
+ *
+ * \param existing browser window with history to clone.
+ * \param clone browser window to make cloned history for.
+ *
+ * \return NSERROR_OK or appropriate error otherwise
+ */
+
+nserror browser_window_history_clone(const struct browser_window *existing,
+ struct browser_window *clone)
+{
+ struct history *new_history;
+
+ clone->history = NULL;
+
+ if (existing == NULL || existing->history == NULL ||
+ existing->history->start == NULL)
+ /* Nothing to clone, create new history for clone window */
+ return browser_window_history_create(clone);
+
+ /* Make cloned history */
+ new_history = malloc(sizeof *new_history);
+ if (!new_history)
+ return NSERROR_NOMEM;
+
+ clone->history = new_history;
+ memcpy(new_history, existing->history, sizeof *new_history);
+
+ new_history->start = browser_window_history__clone_entry(new_history,
+ new_history->start);
+ if (!new_history->start) {
+ LOG(("Insufficient memory to clone history"));
+ warn_user("NoMemory", 0);
+ browser_window_history_destroy(clone);
+ clone->history = NULL;
+ return NSERROR_NOMEM;
+ }
+
+ return NSERROR_OK;
+}
+
+
+/**
* Insert a url into the history tree.
*
- * \param history opaque history structure, as returned by history_create()
+ * \param bw browser window with history object
* \param content content to add to history
* \param frag_id fragment identifier, or NULL.
*
* The page is added after the current entry and becomes current.
*/
-void history_add(struct history *history, hlcache_handle *content,
- lwc_string *frag_id)
+
+void browser_window_history_add(struct browser_window *bw,
+ struct hlcache_handle *content, lwc_string *frag_id)
{
+ struct history *history;
struct history_entry *entry;
nsurl *nsurl = hlcache_handle_get_url(content);
char *title;
struct bitmap *bitmap;
- assert(history);
+ assert(bw);
+ assert(bw->history);
assert(content);
+ history = bw->history;
+
/* allocate space */
entry = malloc(sizeof *entry);
if (entry == NULL)
@@ -297,7 +563,7 @@ void history_add(struct history *history, hlcache_handle *content,
}
entry->bitmap = bitmap;
- history_layout(history);
+ browser_window_history__layout(history);
}
@@ -308,10 +574,16 @@ void history_add(struct history *history, hlcache_handle *content,
* \param content content for current entry
*/
-void history_update(struct history *history, hlcache_handle *content)
+void browser_window_history_update(struct browser_window *bw,
+ struct hlcache_handle *content)
{
+ struct history *history;
char *title;
+ assert(bw != NULL);
+
+ history = bw->history;
+
if (!history || !history->current || !history->current->bitmap)
return;
@@ -338,30 +610,17 @@ void history_update(struct history *history, hlcache_handle *content)
* \param history opaque history structure, as returned by history_create()
*/
-void history_destroy(struct history *history)
+void browser_window_history_destroy(struct browser_window *bw)
{
- if (!history)
+ assert(bw != NULL);
+
+ if (bw->history == NULL)
return;
- history_free_entry(history->start);
- free(history);
-}
+ browser_window_history__free_entry(bw->history->start);
+ free(bw->history);
-/**
- * Free an entry in the tree recursively.
- */
-
-void history_free_entry(struct history_entry *entry)
-{
- if (!entry)
- return;
- history_free_entry(entry->forward);
- history_free_entry(entry->next);
- nsurl_unref(entry->page.url);
- if (entry->page.frag_id)
- lwc_string_unref(entry->page.frag_id);
- free(entry->page.title);
- free(entry);
+ bw->history = NULL;
}
@@ -370,13 +629,15 @@ void history_free_entry(struct history_entry *entry)
*
* \param bw browser window
* \param history history of the window
+ * \param new_window whether to open in new window
*/
-void history_back(struct browser_window *bw, struct history *history)
+void browser_window_history_back(struct browser_window *bw, bool new_window)
{
- if (!history || !history->current || !history->current->back)
+ if (!bw || !bw->history || !bw->history->current ||
+ !bw->history->current->back)
return;
- history_go(bw, history, history->current->back, false);
+ browser_window_history_go(bw, bw->history->current->back, new_window);
}
@@ -385,13 +646,16 @@ void history_back(struct browser_window *bw, struct history *history)
*
* \param bw browser window
* \param history history of the window
+ * \param new_window whether to open in new window
*/
-void history_forward(struct browser_window *bw, struct history *history)
+void browser_window_history_forward(struct browser_window *bw, bool new_window)
{
- if (!history || !history->current || !history->current->forward_pref)
+ if (!bw || !bw->history || !bw->history->current ||
+ !bw->history->current->forward_pref)
return;
- history_go(bw, history, history->current->forward_pref, false);
+ browser_window_history_go(bw, bw->history->current->forward_pref,
+ new_window);
}
@@ -402,9 +666,10 @@ void history_forward(struct browser_window *bw, struct history *history)
* \return true if the history can go back, false otherwise
*/
-bool history_back_available(struct history *history)
+bool browser_window_history_back_available(struct browser_window *bw)
{
- return (history && history->current && history->current->back);
+ return (bw && bw->history && bw->history->current &&
+ bw->history->current->back);
}
@@ -415,25 +680,24 @@ bool history_back_available(struct history *history)
* \return true if the history can go forwards, false otherwise
*/
-bool history_forward_available(struct history *history)
+bool browser_window_history_forward_available(struct browser_window *bw)
{
- return (history && history->current && history->current->forward_pref);
+ return (bw && bw->history && bw->history->current &&
+ bw->history->current->forward_pref);
}
/* Documented in local_history.h */
-void history_go(struct browser_window *bw,
- struct history *history,
- struct history_entry *entry,
- bool new_window)
+void browser_window_history_go(struct browser_window *bw,
+ struct history_entry *entry, bool new_window)
{
+ struct history *history;
nsurl *url;
struct history_entry *current;
nserror error;
-// LOG(("%p %p %p", bw, history, entry));
-// LOG(("%s %s %s",
-// entry->page.url, entry->page.title, entry->page.frag_id));
+ assert(bw != NULL);
+ history = bw->history;
if (entry->page.frag_id) {
error = nsurl_refragment(entry->page.url,
@@ -451,16 +715,17 @@ void history_go(struct browser_window *bw,
current = history->current;
history->current = entry;
- browser_window_create(BROWSER_WINDOW_VERIFIABLE,
- url,
- NULL,
- bw,
- NULL);
+ error = browser_window_create(BW_CREATE_CLONE,
+ url, NULL, bw, NULL);
history->current = current;
+ if (error != NSERROR_OK) {
+ nsurl_unref(url);
+ return;
+ }
} else {
history->current = entry;
browser_window_navigate(bw, url, NULL,
- BROWSER_WINDOW_VERIFIABLE, NULL, NULL, NULL);
+ BW_NAVIGATE_NONE, NULL, NULL, NULL);
}
nsurl_unref(url);
@@ -468,89 +733,6 @@ void history_go(struct browser_window *bw,
/**
- * Compute node positions.
- *
- * \param history history to layout
- *
- * Each node's x and y are filled in.
- */
-
-void history_layout(struct history *history)
-{
- time_t t = time(0);
- struct tm *tp = localtime(&t);
- bool shuffle = tp->tm_mon == 3 && tp->tm_mday == 1;
-
- if (!history)
- return;
-
- history->width = 0;
- if (history->start)
- history->height = history_layout_subtree(history,
- history->start, RIGHT_MARGIN / 2, BOTTOM_MARGIN / 2,
- shuffle);
- else
- history->height = 0;
- if (shuffle) {
- history->width = 600 + WIDTH;
- history->height = 400 + HEIGHT;
- }
- history->width += RIGHT_MARGIN / 2;
- history->height += BOTTOM_MARGIN / 2;
-}
-
-
-/**
- * Recursively position a subtree.
- *
- * \param history history being laid out
- * \param entry subtree to position
- * \param x x position for entry
- * \param y smallest available y
- * \param shuffle shuffle layout
- * \return greatest y used by subtree
- */
-
-int history_layout_subtree(struct history *history,
- struct history_entry *entry, int x, int y, bool shuffle)
-{
- struct history_entry *child;
- int y1 = y;
-
- if (history->width < x + WIDTH)
- history->width = x + WIDTH;
-
- if (!entry->forward) {
- entry->x = x;
- entry->y = y;
- if (shuffle) {
- entry->x = rand() % 600;
- entry->y = rand() % 400;
- }
- return y + HEIGHT;
- }
-
- /* layout child subtrees below each other */
- for (child = entry->forward; child; child = child->next) {
- y1 = history_layout_subtree(history, child,
- x + WIDTH + RIGHT_MARGIN, y1, shuffle);
- if (child->next)
- y1 += BOTTOM_MARGIN;
- }
-
- /* place ourselves in the middle */
- entry->x = x;
- entry->y = (y + y1) / 2 - HEIGHT / 2;
- if (shuffle) {
- entry->x = rand() % 600;
- entry->y = rand() % 400;
- }
-
- return y1;
-}
-
-
-/**
* Get the dimensions of a history.
*
* \param history history to measure
@@ -558,10 +740,14 @@ int history_layout_subtree(struct history *history,
* \param height updated to height
*/
-void history_size(struct history *history, int *width, int *height)
+void browser_window_history_size(struct browser_window *bw,
+ int *width, int *height)
{
- *width = history->width;
- *height = history->height;
+ assert(bw != NULL);
+ assert(bw->history != NULL);
+
+ *width = bw->history->width;
+ *height = bw->history->height;
}
@@ -572,12 +758,18 @@ void history_size(struct history *history, int *width, int *height)
* \param ctx current redraw context
*/
-bool history_redraw(struct history *history, const struct redraw_context *ctx)
+bool browser_window_history_redraw(struct browser_window *bw,
+ const struct redraw_context *ctx)
{
+ struct history *history;
+
+ assert(bw != NULL);
+ history = bw->history;
+
if (!history->start)
return true;
- return history_redraw_entry(history, history->start, 0, 0, 0, 0, 0, 0,
- false, ctx);
+ return browser_window_history__redraw_entry(history, history->start,
+ 0, 0, 0, 0, 0, 0, false, ctx);
}
/**
@@ -593,127 +785,48 @@ bool history_redraw(struct history *history, const struct redraw_context *ctx)
* \param ctx current redraw context
*/
-bool history_redraw_rectangle(struct history *history,
+bool browser_window_history_redraw_rectangle(struct browser_window *bw,
int x0, int y0, int x1, int y1,
int x, int y, const struct redraw_context *ctx)
{
+ struct history *history;
+
+ assert(bw != NULL);
+ history = bw->history;
+
if (!history->start)
return true;
- return history_redraw_entry(history, history->start,
+ return browser_window_history__redraw_entry(history, history->start,
x0, y0, x1, y1, x, y, true, ctx);
}
-/**
- * Recursively redraw a history_entry.
- *
- * \param history history containing the entry
- * \param history_entry entry to render
- * \param ctx current redraw context
- */
-
-bool history_redraw_entry(struct history *history,
- struct history_entry *entry,
- int x0, int y0, int x1, int y1,
- int x, int y, bool clip, const struct redraw_context *ctx)
-{
- const struct plotter_table *plot = ctx->plot;
- size_t char_offset;
- int actual_x;
- struct history_entry *child;
- colour c = entry == history->current ? HISTORY_COLOUR_SELECTED : HISTORY_COLOUR_FOREGROUND;
- int tailsize = 5;
- int xoffset = x - x0;
- int yoffset = y - y0;
- plot_style_t pstyle_history_rect = {
- .stroke_type = PLOT_OP_TYPE_SOLID,
- .stroke_colour = c,
- .stroke_width = entry == history->current ? 3 : 1,
- };
- plot_font_style_t fstyle = *plot_style_font;
-
- if (clip) {
- struct rect rect;
- rect.x0 = x0 + xoffset;
- rect.y0 = y0 + yoffset;
- rect.x1 = x1 + xoffset;
- rect.y1 = y1 + yoffset;
- if(!plot->clip(&rect))
- return false;
- }
-
- if (!plot->bitmap(entry->x + xoffset, entry->y + yoffset, WIDTH, HEIGHT,
- entry->bitmap, 0xffffff, 0))
- return false;
- if (!plot->rectangle(entry->x - 1 + xoffset,
- entry->y - 1 + yoffset,
- entry->x + xoffset + WIDTH,
- entry->y + yoffset + HEIGHT,
- &pstyle_history_rect))
- return false;
-
- if (!nsfont.font_position_in_string(plot_style_font, entry->page.title,
- strlen(entry->page.title), WIDTH,
- &char_offset, &actual_x))
- return false;
-
- fstyle.background = HISTORY_COLOUR_BACKGROUND;
- fstyle.foreground = c;
- fstyle.weight = entry == history->current ? 900 : 400;
-
- if (!plot->text(entry->x + xoffset, entry->y + HEIGHT + 12 + yoffset,
- entry->page.title, char_offset, &fstyle))
- return false;
-
- for (child = entry->forward; child; child = child->next) {
- if (!plot->line(entry->x + WIDTH + xoffset,
- entry->y + HEIGHT / 2 + yoffset,
- entry->x + WIDTH + tailsize + xoffset,
- entry->y + HEIGHT / 2 + yoffset,
- plot_style_stroke_history))
- return false;
- if (!plot->line(entry->x + WIDTH + tailsize + xoffset,
- entry->y + HEIGHT / 2 + yoffset,
- child->x - tailsize +xoffset,
- child->y + HEIGHT / 2 + yoffset,
- plot_style_stroke_history))
- return false;
- if (!plot->line(child->x - tailsize + xoffset,
- child->y + HEIGHT / 2 + yoffset,
- child->x + xoffset, child->y + HEIGHT / 2 + yoffset,
- plot_style_stroke_history))
- return false;
- if (!history_redraw_entry(history, child, x0, y0, x1, y1, x, y,
- clip, ctx))
- return false;
- }
-
- return true;
-}
-
/**
* Handle a mouse click in a history.
*
* \param bw browser window containing history
- * \param history history that was clicked in
* \param x click coordinate
* \param y click coordinate
* \param new_window open a new window instead of using bw
* \return true if action was taken, false if click was not on an entry
*/
-bool history_click(struct browser_window *bw, struct history *history,
+bool browser_window_history_click(struct browser_window *bw,
int x, int y, bool new_window)
{
struct history_entry *entry;
+ struct history *history;
- entry = history_find_position(history->start, x, y);
+ assert(bw != NULL);
+ history = bw->history;
+
+ entry = browser_window_history__find_position(history->start, x, y);
if (!entry)
return false;
if (entry == history->current)
return false;
- history_go(bw, history, entry, new_window);
+ browser_window_history_go(bw, entry, new_window);
return true;
}
@@ -728,126 +841,82 @@ bool history_click(struct browser_window *bw, struct history *history,
* \return URL, or 0 if no entry at (x, y)
*/
-const char *history_position_url(struct history *history, int x, int y)
+const char *browser_window_history_position_url(struct browser_window *bw,
+ int x, int y)
{
struct history_entry *entry;
+ struct history *history;
+
+ assert(bw != NULL);
+ history = bw->history;
- entry = history_find_position(history->start, x, y);
+ entry = browser_window_history__find_position(history->start, x, y);
if (!entry)
return 0;
return nsurl_access(entry->page.url);
}
-
-/**
- * Find the history entry at a position.
- *
- * \param entry entry to search from
- * \param x coordinate
- * \param y coordinate
- * \return an entry if found, 0 if none
- */
-
-struct history_entry *history_find_position(struct history_entry *entry,
- int x, int y)
+/* Documented in local_history.h */
+void browser_window_history_enumerate_forward(const struct browser_window *bw,
+ browser_window_history_enumerate_cb cb, void *user_data)
{
- struct history_entry *child;
- struct history_entry *found;
-
- if (!entry)
- return 0;
-
- if (entry->x <= x && x <= entry->x + WIDTH &&
- entry->y <= y && y <= entry->y + HEIGHT)
- return entry;
+ struct history_entry *e;
- for (child = entry->forward; child; child = child->next) {
- found = history_find_position(child, x, y);
- if (found)
- return found;
- }
-
- return 0;
-}
+ if (bw == NULL || bw->history == NULL || bw->history->current == NULL)
+ return;
-/* Documented in local_history.h */
-void history_enumerate_forward(struct history *history,
- history_enumerate_cb cb, void *user_data)
-{
- struct history_entry *entry;
-
- if (history == NULL || history->current == NULL) return;
-
- for (entry = history->current->forward_pref; entry != NULL; entry = entry->forward_pref) {
- if (!cb(history, entry->x, entry->y, entry->x + WIDTH,
- entry->y + HEIGHT, entry, user_data))
+ e = bw->history->current->forward_pref;
+ for (; e != NULL; e = e->forward_pref) {
+ if (!cb(bw, e->x, e->y, e->x + WIDTH, e->y + HEIGHT,
+ e, user_data))
break;
}
}
/* Documented in local_history.h */
-void history_enumerate_back(struct history *history,
- history_enumerate_cb cb, void *user_data)
+void browser_window_history_enumerate_back(const struct browser_window *bw,
+ browser_window_history_enumerate_cb cb, void *user_data)
{
- struct history_entry *entry;
-
- if (history == NULL || history->current == NULL) return;
-
- for (entry = history->current->back; entry != NULL; entry = entry->back) {
- if (!cb(history, entry->x, entry->y, entry->x + WIDTH,
- entry->y + HEIGHT, entry, user_data))
+ struct history_entry *e;
+
+ if (bw == NULL || bw->history == NULL || bw->history->current == NULL)
+ return;
+
+ for (e = bw->history->current->back; e != NULL; e = e->back) {
+ if (!cb(bw, e->x, e->y, e->x + WIDTH, e->y + HEIGHT,
+ e, user_data))
break;
}
}
/* Documented in local_history.h */
-void history_enumerate(const struct history *history, history_enumerate_cb cb,
- void *user_data)
+void browser_window_history_enumerate(const struct browser_window *bw,
+ browser_window_history_enumerate_cb cb, void *user_data)
{
- history_enumerate_entry(history, history->start, cb, user_data);
-}
-
-/**
- * Enumerate subentries in history
- * See also history_enumerate()
- *
- * \param history history to enumerate
- * \param entry entry to start enumeration at
- * \param cb callback function
- * \param ud context pointer passed to cb
- * \return true to continue enumeration, false to cancel
- */
-static bool history_enumerate_entry(const struct history *history,
- const struct history_entry *entry, history_enumerate_cb cb, void *ud)
-{
- const struct history_entry *child;
-
- if (!cb(history, entry->x, entry->y, entry->x + WIDTH, entry->y + HEIGHT,
- entry, ud)) return false;
-
- for (child = entry->forward; child; child = child->next) {
- if (!history_enumerate_entry(history, child, cb, ud))
- return false;
- }
-
- return true;
+ if (bw == NULL || bw->history == NULL)
+ return;
+ browser_window_history__enumerate_entry(bw,
+ bw->history->start, cb, user_data);
}
/* Documented in local_history.h */
-const char *history_entry_get_url(const struct history_entry *entry)
+const char *browser_window_history_entry_get_url(
+ const struct history_entry *entry)
{
return nsurl_access(entry->page.url);
}
/* Documented in local_history.h */
-const char *history_entry_get_fragment_id(const struct history_entry *entry)
+const char *browser_window_history_entry_get_fragment_id(
+ const struct history_entry *entry)
{
return (entry->page.frag_id) ? lwc_string_data(entry->page.frag_id) : 0;
}
/* Documented in local_history.h */
-const char *history_entry_get_title(const struct history_entry *entry)
+const char *browser_window_history_entry_get_title(
+ const struct history_entry *entry)
{
return entry->page.title;
}
diff --git a/desktop/browser_history.h b/desktop/browser_history.h
new file mode 100644
index 000000000..f3e524baf
--- /dev/null
+++ b/desktop/browser_history.h
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2006 James Bursa <bursa@users.sourceforge.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Browser history tree (interface).
+ */
+
+#ifndef _NETSURF_DESKTOP_BROWSER_HISTORY_H_
+#define _NETSURF_DESKTOP_BROWSER_HISTORY_H_
+
+#include <stdbool.h>
+#include <libwapcaplet/libwapcaplet.h>
+
+#include "utils/errors.h"
+
+struct hlcache_handle;
+struct browser_window;
+struct history_entry;
+struct redraw_context;
+
+nserror browser_window_history_create(struct browser_window *bw);
+nserror browser_window_history_clone(const struct browser_window *existing,
+ struct browser_window *clone);
+void browser_window_history_add(struct browser_window *bw,
+ struct hlcache_handle *content, lwc_string *frag_id);
+void browser_window_history_update(struct browser_window *bw,
+ struct hlcache_handle *content);
+void browser_window_history_destroy(struct browser_window *bw);
+void browser_window_history_back(struct browser_window *bw, bool new_window);
+void browser_window_history_forward(struct browser_window *bw, bool new_window);
+bool browser_window_history_back_available(struct browser_window *bw);
+bool browser_window_history_forward_available(struct browser_window *bw);
+void browser_window_history_size(struct browser_window *bw,
+ int *width, int *height);
+bool browser_window_history_redraw(struct browser_window *bw,
+ const struct redraw_context *ctx);
+bool browser_window_history_redraw_rectangle(struct browser_window *bw,
+ int x0, int y0, int x1, int y1, int x, int y,
+ const struct redraw_context *ctx);
+bool browser_window_history_click(struct browser_window *bw,
+ int x, int y, bool new_window);
+const char *browser_window_history_position_url(struct browser_window *bw,
+ int x, int y);
+
+/**
+ * Callback function type for history enumeration
+ *
+ * \param bw The browser window with history being enumerated
+ * \param x0, y0, x1, y1 Coordinates of entry in history tree view
+ * \param entry Current history entry
+ * \return true to continue enumeration, false to cancel enumeration
+ */
+typedef bool (*browser_window_history_enumerate_cb)(
+ const struct browser_window *bw,
+ int x0, int y0, int x1, int y1,
+ const struct history_entry *entry, void *user_data);
+
+/**
+ * Enumerate all entries in the history.
+ * Do not change the history while it is being enumerated.
+ *
+ * \param bw The browser window to enumerate history of
+ * \param cb callback function
+ * \param user_data context pointer passed to cb
+ */
+void browser_window_history_enumerate(const struct browser_window *bw,
+ browser_window_history_enumerate_cb cb, void *user_data);
+
+/**
+ * Enumerate all entries that will be reached by the 'forward' button
+ *
+ * \param bw The browser window to enumerate history of
+ * \param cb The callback function
+ * \param user_data Data passed to the callback
+ */
+void browser_window_history_enumerate_forward(const struct browser_window *bw,
+ browser_window_history_enumerate_cb cb, void *user_data);
+
+/**
+ * Enumerate all entries that will be reached by the 'back' button
+ *
+ * \param bw The browser window to enumerate history of
+ * \param cb The callback function
+ * \param user_data Data passed to the callback
+ */
+void browser_window_history_enumerate_back(const struct browser_window *bw,
+ browser_window_history_enumerate_cb cb, void *user_data);
+
+/**
+ * Returns the URL to a history entry
+ *
+ * \param entry the history entry to retrieve the URL from
+ * \return the URL
+ */
+const char *browser_window_history_entry_get_url(
+ const struct history_entry *entry);
+
+/**
+ * Returns the URL to a history entry
+ *
+ * \param entry the history entry to retrieve the fragment id from
+ * \return the fragment id
+ */
+const char *browser_window_history_entry_get_fragment_id(
+ const struct history_entry *entry);
+
+/**
+ * Returns the title of a history entry
+ *
+ * \param entry the history entry to retrieve the title from
+ * \return the title
+ */
+const char *browser_window_history_entry_get_title(
+ const struct history_entry *entry);
+
+/**
+ * Navigate to specified history entry, optionally in new window
+ *
+ * \param bw browser window
+ * \param entry entry to open
+ * \param new_window open entry in new window
+ */
+void browser_window_history_go(struct browser_window *bw,
+ struct history_entry *entry, bool new_window);
+
+#endif
diff --git a/desktop/browser_private.h b/desktop/browser_private.h
index 4412f4bf4..d2c48d704 100644
--- a/desktop/browser_private.h
+++ b/desktop/browser_private.h
@@ -25,6 +25,7 @@
#define _NETSURF_DESKTOP_BROWSER_PRIVATE_H_
#include <stdbool.h>
+#include <libwapcaplet/libwapcaplet.h>
#include "desktop/browser.h"
@@ -87,9 +88,6 @@ struct browser_window {
/** Refresh interval (-1 if undefined) */
int refresh_interval;
- /** Window has been resized, and content needs reformatting. */
- bool reformat_pending;
-
/** Window dimensions */
int x;
int y;
@@ -163,4 +161,17 @@ struct browser_window {
int status_miss; /**< Number of times status was really updated. */
};
+
+
+nserror browser_window_initialise_common(enum browser_window_create_flags flags,
+ struct browser_window *bw, struct browser_window *existing);
+
+/**
+ * Update the extent of the inside of a browser window to that of the current
+ * content
+ *
+ * \param bw browser_window to update the extent of
+ */
+void browser_window_update_extent(struct browser_window *bw);
+
#endif
diff --git a/desktop/cookie_manager.c b/desktop/cookie_manager.c
index 13c6ac93b..c0ca16128 100644
--- a/desktop/cookie_manager.c
+++ b/desktop/cookie_manager.c
@@ -22,13 +22,15 @@
#include <stdlib.h>
+#include <string.h>
-#include "content/urldb.h"
-#include "desktop/cookie_manager.h"
-#include "desktop/treeview.h"
#include "utils/messages.h"
#include "utils/utils.h"
#include "utils/log.h"
+#include "content/urldb.h"
+
+#include "desktop/cookie_manager.h"
+#include "desktop/treeview.h"
enum cookie_manager_field {
COOKIE_M_NAME,
@@ -836,7 +838,7 @@ void cookie_manager_redraw(int x, int y, struct rect *clip,
/* Exported interface, documented in cookie_manager.h */
-void cookie_manager_mouse_action(browser_mouse_state mouse, int x, int y)
+void cookie_manager_mouse_action(enum browser_mouse_state mouse, int x, int y)
{
treeview_mouse_action(cm_ctx.tree, mouse, x, y);
}
diff --git a/desktop/cookie_manager.h b/desktop/cookie_manager.h
index aa61a3e65..3565caf63 100644
--- a/desktop/cookie_manager.h
+++ b/desktop/cookie_manager.h
@@ -26,12 +26,12 @@
#include <stdbool.h>
#include <stdint.h>
-#include "desktop/browser.h"
#include "desktop/core_window.h"
#include "desktop/textinput.h"
#include "utils/errors.h"
struct cookie_data;
+enum browser_mouse_state;
/**
* Initialise the cookie manager.
@@ -92,7 +92,7 @@ void cookie_manager_redraw(int x, int y, struct rect *clip,
* \param x X coordinate
* \param y Y coordinate
*/
-void cookie_manager_mouse_action(browser_mouse_state mouse, int x, int y);
+void cookie_manager_mouse_action(enum browser_mouse_state mouse, int x, int y);
/**
* Key press handling.
diff --git a/desktop/download.c b/desktop/download.c
index b775eb18e..0f3fcb6f5 100644
--- a/desktop/download.c
+++ b/desktop/download.c
@@ -23,10 +23,12 @@
#include <assert.h>
#include <stdlib.h>
+#include <string.h>
#include "content/llcache.h"
#include "desktop/download.h"
-#include "desktop/gui.h"
+#include "desktop/gui_factory.h"
+#include "utils/corestrings.h"
#include "utils/http.h"
#include "utils/url.h"
#include "utils/utils.h"
@@ -69,11 +71,11 @@ static char *download_parse_filename(const char *filename)
* \param url URL of item being fetched
* \return Default filename, or NULL on memory exhaustion
*/
-static char *download_default_filename(const char *url)
+static char *download_default_filename(nsurl *url)
{
char *nice;
- if (url_nice(url, &nice, false) == URL_FUNC_OK)
+ if (url_nice(nsurl_access(url), &nice, false) == NSERROR_OK)
return nice;
return NULL;
@@ -113,26 +115,18 @@ static nserror download_context_process_headers(download_context *ctx)
http_header = llcache_handle_get_header(ctx->llcache,
"Content-Disposition");
if (http_header != NULL) {
- lwc_string *filename;
lwc_string *filename_value;
http_content_disposition *disposition;
- if (lwc_intern_string("filename", SLEN("filename"),
- &filename) != lwc_error_ok) {
- http_content_type_destroy(content_type);
- return NSERROR_NOMEM;
- }
-
error = http_parse_content_disposition(http_header,
&disposition);
if (error != NSERROR_OK) {
- lwc_string_unref(filename);
http_content_type_destroy(content_type);
return error;
}
error = http_parameter_list_find_item(disposition->parameters,
- filename, &filename_value);
+ corestring_lwc_filename, &filename_value);
if (error == NSERROR_OK) {
ctx->filename = download_parse_filename(
lwc_string_data(filename_value));
@@ -140,15 +134,13 @@ static nserror download_context_process_headers(download_context *ctx)
}
http_content_disposition_destroy(disposition);
- lwc_string_unref(filename);
}
ctx->mime_type = lwc_string_ref(content_type->media_type);
ctx->total_length = length;
if (ctx->filename == NULL) {
ctx->filename = download_default_filename(
- nsurl_access(
- llcache_handle_get_url(ctx->llcache)));
+ llcache_handle_get_url(ctx->llcache));
}
http_content_type_destroy(content_type);
@@ -160,7 +152,7 @@ static nserror download_context_process_headers(download_context *ctx)
}
/* Create the frontend window */
- ctx->window = gui_download_window_create(ctx, ctx->parent);
+ ctx->window = guit->download->create(ctx, ctx->parent);
if (ctx->window == NULL) {
free(ctx->filename);
ctx->filename = NULL;
@@ -210,7 +202,7 @@ static nserror download_callback(llcache_handle *handle,
if (error == NSERROR_OK) {
/** \todo Lose ugly cast */
- error = gui_download_window_data(ctx->window,
+ error = guit->download->data(ctx->window,
(char *) event->data.data.buf,
event->data.data.len);
if (error != NSERROR_OK)
@@ -222,7 +214,7 @@ static nserror download_callback(llcache_handle *handle,
case LLCACHE_EVENT_DONE:
/* There may be no associated window if there was no data or headers */
if (ctx->window != NULL)
- gui_download_window_done(ctx->window);
+ guit->download->done(ctx->window);
else
download_context_destroy(ctx);
@@ -230,7 +222,7 @@ static nserror download_callback(llcache_handle *handle,
case LLCACHE_EVENT_ERROR:
if (ctx->window != NULL)
- gui_download_window_error(ctx->window, event->data.msg);
+ guit->download->error(ctx->window, event->data.msg);
else
download_context_destroy(ctx);
@@ -290,9 +282,9 @@ void download_context_abort(download_context *ctx)
}
/* See download.h for documentation */
-const char *download_context_get_url(const download_context *ctx)
+nsurl *download_context_get_url(const download_context *ctx)
{
- return nsurl_access(llcache_handle_get_url(ctx->llcache));
+ return llcache_handle_get_url(ctx->llcache);
}
/* See download.h for documentation */
diff --git a/desktop/download.h b/desktop/download.h
index f53f38b95..dc2befd90 100644
--- a/desktop/download.h
+++ b/desktop/download.h
@@ -28,6 +28,7 @@
struct gui_window;
struct llcache_handle;
+struct nsurl;
/** Type of a download context */
typedef struct download_context download_context;
@@ -67,10 +68,14 @@ void download_context_abort(download_context *ctx);
/**
* Retrieve the URL for a download
*
- * \param ctx Context to retrieve URL from
- * \return URL string
+ * The caller is borrowing the url reference from the underlying low
+ * level cache object. If it is used beyond the immediate scope of the
+ * caller an additional reference should be made.
+ *
+ * \param ctx Context to retrieve URL from
+ * \return URL object
*/
-const char *download_context_get_url(const download_context *ctx);
+struct nsurl *download_context_get_url(const download_context *ctx);
/**
* Retrieve the MIME type for a download
diff --git a/desktop/frames.c b/desktop/frames.c
index 3f7613f32..534cca4f7 100644
--- a/desktop/frames.c
+++ b/desktop/frames.c
@@ -28,12 +28,11 @@
#include <string.h>
#include <time.h>
#include <math.h>
+
#include "utils/config.h"
#include "content/hlcache.h"
#include "desktop/browser_private.h"
#include "desktop/frames.h"
-#include "desktop/local_history.h"
-#include "desktop/gui.h"
#include "desktop/scrollbar.h"
#include "desktop/selection.h"
#include "utils/log.h"
@@ -209,7 +208,8 @@ void browser_window_create_iframes(struct browser_window *bw,
window = &(bw->iframes[index++]);
/* Initialise common parts */
- browser_window_initialise_common(window, NULL);
+ browser_window_initialise_common(BW_CREATE_NONE,
+ window, NULL);
/* window characteristics */
window->browser_window_type = BROWSER_WINDOW_IFRAME;
@@ -251,7 +251,7 @@ void browser_window_create_iframes(struct browser_window *bw,
browser_window_navigate(window,
cur->url,
hlcache_handle_get_url(bw->current_content),
- BROWSER_WINDOW_NONE,
+ BW_NAVIGATE_UNVERIFIABLE,
NULL,
NULL,
bw->current_content);
@@ -314,7 +314,8 @@ void browser_window_create_frameset(struct browser_window *bw,
window = &bw->children[index];
/* Initialise common parts */
- browser_window_initialise_common(window, NULL);
+ browser_window_initialise_common(BW_CREATE_NONE,
+ window, NULL);
/* window characteristics */
if (frame->children)
@@ -387,7 +388,8 @@ void browser_window_create_frameset(struct browser_window *bw,
browser_window_navigate(window,
frame->url,
hlcache_handle_get_url(parent),
- BROWSER_WINDOW_HISTORY,
+ BW_NAVIGATE_HISTORY |
+ BW_NAVIGATE_UNVERIFIABLE,
NULL,
NULL,
parent);
diff --git a/desktop/global_history.c b/desktop/global_history.c
index e8d99efc2..7d679e5a2 100644
--- a/desktop/global_history.c
+++ b/desktop/global_history.c
@@ -18,15 +18,18 @@
#include <stdlib.h>
+#include <string.h>
-#include "content/urldb.h"
-#include "desktop/global_history.h"
-#include "desktop/treeview.h"
#include "utils/messages.h"
#include "utils/utils.h"
#include "utils/utf8.h"
#include "utils/libdom.h"
#include "utils/log.h"
+#include "content/urldb.h"
+
+#include "desktop/global_history.h"
+#include "desktop/treeview.h"
+#include "desktop/browser.h"
#define N_DAYS 28
#define N_SEC_PER_DAY (60 * 60 * 24)
@@ -676,23 +679,22 @@ static nserror global_history_tree_node_entry_cb(
case TREE_MSG_NODE_LAUNCH:
{
nserror error;
- struct browser_window *clone = NULL;
- enum browser_window_nav_flags flags =
- BROWSER_WINDOW_VERIFIABLE |
- BROWSER_WINDOW_HISTORY |
- BROWSER_WINDOW_TAB;
+ struct browser_window *existing = NULL;
+ enum browser_window_create_flags flags =
+ BW_CREATE_HISTORY;
- /* TODO: Set clone window, to window that new tab appears in */
+ /* TODO: Set existing to window that new tab appears in */
if (msg.data.node_launch.mouse &
(BROWSER_MOUSE_MOD_1 | BROWSER_MOUSE_MOD_2) ||
- clone == NULL) {
+ existing == NULL) {
/* Shift or Ctrl launch, open in new window rather
* than tab. */
- flags ^= BROWSER_WINDOW_TAB;
+ /* TODO: flags ^= BW_CREATE_TAB; */
}
- error = browser_window_create(flags, e->url, NULL, clone, NULL);
+ error = browser_window_create(flags, e->url, NULL,
+ existing, NULL);
if (error != NSERROR_OK) {
warn_user(messages_get_errorcode(error), 0);
}
@@ -828,21 +830,21 @@ static nserror global_history_export_enter_cb(void *ctx, void *node_data,
enum treeview_node_type type, bool *abort)
{
struct treeview_export_walk_ctx *tw = ctx;
+ nserror ret;
if (type == TREE_NODE_ENTRY) {
struct global_history_entry *e = node_data;
- utf8_convert_ret ret;
char *t_text;
char *u_text;
ret = utf8_to_html(e->data[GH_TITLE].value, "iso-8859-1",
e->data[GH_TITLE].value_len, &t_text);
- if (ret != UTF8_CONVERT_OK)
+ if (ret != NSERROR_OK)
return NSERROR_SAVE_FAILED;
ret = utf8_to_html(e->data[GH_URL].value, "iso-8859-1",
e->data[GH_URL].value_len, &u_text);
- if (ret != UTF8_CONVERT_OK) {
+ if (ret != NSERROR_OK) {
free(t_text);
return NSERROR_SAVE_FAILED;
}
@@ -855,12 +857,11 @@ static nserror global_history_export_enter_cb(void *ctx, void *node_data,
} else if (type == TREE_NODE_FOLDER) {
struct global_history_folder *f = node_data;
- utf8_convert_ret ret;
char *f_text;
ret = utf8_to_html(f->data.value, "iso-8859-1",
f->data.value_len, &f_text);
- if (ret != UTF8_CONVERT_OK)
+ if (ret != NSERROR_OK)
return NSERROR_SAVE_FAILED;
fprintf(tw->fp, "<li><h4>%s</h4>\n<ul>\n", f_text);
@@ -954,10 +955,11 @@ bool global_history_has_selection(void)
bool global_history_get_selection(nsurl **url, const char **title)
{
struct global_history_entry *e;
+ enum treeview_node_type type;
void *v;
- treeview_get_selection(gh_ctx.tree, &v);
- if (v == NULL) {
+ type = treeview_get_selection(gh_ctx.tree, &v);
+ if (type != TREE_NODE_ENTRY || v == NULL) {
*url = NULL;
*title = NULL;
return false;
diff --git a/desktop/global_history.h b/desktop/global_history.h
index 7c49cfcb7..463ab1b9c 100644
--- a/desktop/global_history.h
+++ b/desktop/global_history.h
@@ -22,12 +22,12 @@
#include <stdbool.h>
#include <stdint.h>
-#include "desktop/browser.h"
#include "desktop/core_window.h"
#include "desktop/textinput.h"
#include "utils/errors.h"
#include "utils/nsurl.h"
+enum browser_mouse_state;
/**
* Initialise the global history.
@@ -92,7 +92,7 @@ void global_history_redraw(int x, int y, struct rect *clip,
* \param x X coordinate
* \param y Y coordinate
*/
-void global_history_mouse_action(browser_mouse_state mouse, int x, int y);
+void global_history_mouse_action(enum browser_mouse_state mouse, int x, int y);
/**
* Key press handling.
diff --git a/desktop/gui.h b/desktop/gui.h
index 9d35e1727..21dd85e68 100644
--- a/desktop/gui.h
+++ b/desktop/gui.h
@@ -1,6 +1,5 @@
/*
- * Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
- * Copyright 2004 James Bursa <bursa@users.sourceforge.net>
+ * Copyright 2014 Vincent Sanders <vince@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -18,13 +17,20 @@
*/
/** \file
- * Interface to platform-specific gui functions.
+ * Interface to platform-specific gui operation tables.
*/
#ifndef _NETSURF_DESKTOP_GUI_H_
#define _NETSURF_DESKTOP_GUI_H_
-typedef enum {
+#include <stddef.h>
+
+#include "utils/types.h"
+#include "utils/errors.h"
+#include "desktop/plot_style.h"
+#include "desktop/mouse.h"
+
+typedef enum gui_save_type {
GUI_SAVE_SOURCE,
GUI_SAVE_DRAW,
GUI_SAVE_PDF,
@@ -48,133 +54,529 @@ typedef enum {
GDRAGGING_OTHER
} gui_drag_type;
+typedef enum {
+ GW_CREATE_NONE = 0, /* New window */
+ GW_CREATE_CLONE = (1 << 0), /* Clone existing window */
+ GW_CREATE_TAB = (1 << 1) /* In same window as existing */
+} gui_window_create_flags;
+
struct gui_window;
struct gui_download_window;
struct browser_window;
struct form_control;
+struct ssl_cert_info;
+struct hlcache_handle;
+struct download_context;
+struct nsurl;
+struct gui_file_table;
+struct gui_llcache_table;
+struct gui_search_web_table;
-#include <stdbool.h>
+typedef struct nsnsclipboard_styles {
+ size_t start; /**< Start of run */
-#include <libwapcaplet/libwapcaplet.h>
-#include <libcss/libcss.h>
+ plot_font_style_t style; /**< Style to give text run */
+} nsclipboard_styles;
-#include "utils/config.h"
-#include "content/hlcache.h"
-#include "desktop/download.h"
-#include "desktop/mouse.h"
-#include "desktop/search.h"
-#include "utils/errors.h"
+/**
+ * Graphical user interface window function table.
+ *
+ * function table implementing window operations
+ */
+struct gui_window_table {
+
+ /* Mandantory entries */
+
+ /**
+ * Create and open a gui window for a browsing context.
+ *
+ * \param bw bw to create gui_window for
+ * \param existing an existing gui_window, may be NULL
+ * \param flags flags for gui window creation
+ * \return gui window, or NULL on error
+ *
+ * If GW_CREATE_CLONE flag is set existing is non-NULL.
+ *
+ * Front end's gui_window must include a reference to the
+ * browser window passed in the bw param.
+ */
+ struct gui_window *(*create)(struct browser_window *bw,
+ struct gui_window *existing,
+ gui_window_create_flags flags);
+
+ /**
+ * Destroy previously created gui window
+ */
+ void (*destroy)(struct gui_window *g);
+
+ /**
+ * Force a redraw of the entire contents of a window.
+ *
+ * @todo this API should be merged with update.
+ *
+ * \param g gui_window to redraw
+ */
+ void (*redraw)(struct gui_window *g);
+
+ /**
+ * Redraw an area of a window.
+ *
+ * \param g gui_window
+ * \param rect area to redraw
+ */
+ void (*update)(struct gui_window *g, const struct rect *rect);
+
+ /**
+ * Get the scroll position of a browser window.
+ *
+ * \param g gui_window
+ * \param sx receives x ordinate of point at top-left of window
+ * \param sy receives y ordinate of point at top-left of window
+ * \return true iff successful
+ */
+ bool (*get_scroll)(struct gui_window *g, int *sx, int *sy);
-void gui_poll(bool active);
-void gui_quit(void);
-
-struct gui_window *gui_create_browser_window(struct browser_window *bw,
- struct browser_window *clone, bool new_tab);
-void gui_window_destroy(struct gui_window *g);
-void gui_window_set_title(struct gui_window *g, const char *title);
-void gui_window_redraw_window(struct gui_window *g);
-void gui_window_update_box(struct gui_window *g,
- const struct rect *rect);
-bool gui_window_get_scroll(struct gui_window *g, int *sx, int *sy);
-void gui_window_set_scroll(struct gui_window *g, int sx, int sy);
-void gui_window_scroll_visible(struct gui_window *g, int x0, int y0,
- int x1, int y1);
-void gui_window_get_dimensions(struct gui_window *g, int *width, int *height,
- bool scaled);
-void gui_window_update_extent(struct gui_window *g);
-void gui_window_set_status(struct gui_window *g, const char *text);
-void gui_window_set_pointer(struct gui_window *g, gui_pointer_shape shape);
-void gui_window_hide_pointer(struct gui_window *g);
-void gui_window_set_url(struct gui_window *g, const char *url);
-void gui_window_start_throbber(struct gui_window *g);
-void gui_window_stop_throbber(struct gui_window *g);
-void gui_window_set_icon(struct gui_window *g, hlcache_handle *icon);
-void gui_window_set_search_ico(hlcache_handle *ico);
-void gui_window_place_caret(struct gui_window *g, int x, int y, int height,
- const struct rect *clip);
-void gui_window_remove_caret(struct gui_window *g);
-void gui_window_new_content(struct gui_window *g);
-bool gui_window_scroll_start(struct gui_window *g);
-
-bool gui_window_drag_start(struct gui_window *g, gui_drag_type type,
- const struct rect *rect);
-
-void gui_window_save_link(struct gui_window *g, const char *url,
- const char *title);
-
-struct gui_download_window *gui_download_window_create(download_context *ctx,
- struct gui_window *parent);
-nserror gui_download_window_data(struct gui_download_window *dw,
- const char *data, unsigned int size);
-void gui_download_window_error(struct gui_download_window *dw,
- const char *error_msg);
-void gui_download_window_done(struct gui_download_window *dw);
-
-void gui_drag_save_object(gui_save_type type, hlcache_handle *c,
- struct gui_window *g);
-void gui_drag_save_selection(struct gui_window *g, const char *selection);
-void gui_start_selection(struct gui_window *g);
-void gui_clear_selection(struct gui_window *g);
+ /**
+ * Set the scroll position of a browser window.
+ *
+ * \param g gui_window to scroll
+ * \param sx point to place at top-left of window
+ * \param sy point to place at top-left of window
+ */
+ void (*set_scroll)(struct gui_window *g, int sx, int sy);
+ /**
+ * Find the current dimensions of a browser window's content area.
+ *
+ * @todo The implementations of this are buggy and its only
+ * used from frames code.
+ *
+ * \param g gui_window to measure
+ * \param width receives width of window
+ * \param height receives height of window
+ * \param scaled whether to return scaled values
+ */
+ void (*get_dimensions)(struct gui_window *g, int *width, int *height, bool scaled);
+
+ /**
+ * Update the extent of the inside of a browser window to that of the
+ * current content.
+ *
+ * @todo this is used to update scroll bars does it need
+ * renaming? some frontends (windows) do not even implement it.
+ *
+ * \param g gui_window to update the extent of
+ */
+ void (*update_extent)(struct gui_window *g);
+
+ /**
+ * Reformat a window.
+ *
+ * This is used to perform reformats when the page contents
+ * require reformating. The reformat is requested using
+ * browser_window_schedule_reformat and occours via a scheduled
+ * callback hence from top level context.
+ *
+ * \param g gui_window to reformat.
+ */
+ void (*reformat)(struct gui_window *g);
+
+
+ /* Optional entries */
+
+ /**
+ * Set the title of a window.
+ *
+ * \param g window to update
+ * \param title new window title
+ */
+ void (*set_title)(struct gui_window *g, const char *title);
+
+ /**
+ * set the navigation url.
+ */
+ void (*set_url)(struct gui_window *g, const char *url);
+
+ /** set favicon */
+ void (*set_icon)(struct gui_window *g, struct hlcache_handle *icon);
+
+ /**
+ * Set the status bar of a browser window.
+ *
+ * \param g gui_window to update
+ * \param text new status text
+ */
+ void (*set_status)(struct gui_window *g, const char *text);
+
+ /**
+ * Change mouse pointer shape
+ */
+ void (*set_pointer)(struct gui_window *g, gui_pointer_shape shape);
+
+ /**
+ * Place the caret in a browser window.
+ *
+ * \param g window with caret
+ * \param x coordinates of caret
+ * \param y coordinates of caret
+ * \param height height of caret
+ * \param clip clip rectangle, or NULL if none
+ */
+ void (*place_caret)(struct gui_window *g, int x, int y, int height, const struct rect *clip);
+
+ /**
+ * Remove the caret, if present.
+ *
+ * \param g window with caret
+ */
+ void (*remove_caret)(struct gui_window *g);
+
+ /** start the navigation throbber. */
+ void (*start_throbber)(struct gui_window *g);
+
+ /** stop the navigation throbber. */
+ void (*stop_throbber)(struct gui_window *g);
+
+ /** start a drag operation within a window */
+ bool (*drag_start)(struct gui_window *g, gui_drag_type type, const struct rect *rect);
+
+ /** save link operation */
+ void (*save_link)(struct gui_window *g, const char *url, const char *title);
+
+ /**
+ * Scrolls the specified area of a browser window into view.
+ *
+ * @todo investigate if this can be merged with set_scroll
+ * which is what the default implementation used by most
+ * toolkits uses.
+ *
+ * \param g gui_window to scroll
+ * \param x0 left point to ensure visible
+ * \param y0 bottom point to ensure visible
+ * \param x1 right point to ensure visible
+ * \param y1 top point to ensure visible
+ */
+ void (*scroll_visible)(struct gui_window *g, int x0, int y0, int x1, int y1);
+
+ /**
+ * Starts drag scrolling of a browser window
+ *
+ * \param g the window to scroll
+ */
+ bool (*scroll_start)(struct gui_window *g);
+
+ /**
+ * Called when the gui_window has new content.
+ *
+ * \param g the gui_window that has new content
+ */
+ void (*new_content)(struct gui_window *g);
+
+ /**
+ * Called when file chooser gadget is activated
+ */
+ void (*file_gadget_open)(struct gui_window *g, struct hlcache_handle *hl, struct form_control *gadget);
+
+ /** object dragged to window*/
+ void (*drag_save_object)(struct gui_window *g, struct hlcache_handle *c, gui_save_type type);
+
+ /** drag selection save */
+ void (*drag_save_selection)(struct gui_window *g, const char *selection);
+
+ /** selection started */
+ void (*start_selection)(struct gui_window *g);
+};
/**
- * Core asks front end for clipboard contents.
- *
- * \param buffer UTF-8 text, allocated by front end, ownership yeilded to core
- * \param length Byte length of UTF-8 text in buffer
+ * function table for download windows.
*/
-void gui_get_clipboard(char **buffer, size_t *length);
+struct gui_download_table {
+ struct gui_download_window *(*create)(struct download_context *ctx, struct gui_window *parent);
+
+ nserror (*data)(struct gui_download_window *dw, const char *data, unsigned int size);
+
+ void (*error)(struct gui_download_window *dw, const char *error_msg);
+
+ void (*done)(struct gui_download_window *dw);
+};
-typedef struct nsnsclipboard_styles {
- size_t start; /**< Start of run */
- plot_font_style_t style; /**< Style to give text run */
-} nsclipboard_styles;
/**
- * Core tells front end to put given text in clipboard
- *
- * \param buffer UTF-8 text, owned by core
- * \param length Byte length of UTF-8 text in buffer
- * \param styles Array of styles given to text runs, owned by core, or NULL
- * \param n_styles Number of text run styles in array
+ * function table for clipboard operations.
*/
-void gui_set_clipboard(const char *buffer, size_t length,
- nsclipboard_styles styles[], int n_styles);
+struct gui_clipboard_table {
+ /**
+ * Core asks front end for clipboard contents.
+ *
+ * \param buffer UTF-8 text, allocated by front end, ownership yeilded to core
+ * \param length Byte length of UTF-8 text in buffer
+ */
+ void (*get)(char **buffer, size_t *length);
+
+ /**
+ * Core tells front end to put given text in clipboard
+ *
+ * \param buffer UTF-8 text, owned by core
+ * \param length Byte length of UTF-8 text in buffer
+ * \param styles Array of styles given to text runs, owned by core, or NULL
+ * \param n_styles Number of text run styles in array
+ */
+ void (*set)(const char *buffer, size_t length, nsclipboard_styles styles[], int n_styles);
+};
+/**
+ * function table for fetcher operations
+ */
+struct gui_fetch_table {
+ /* Mandantory entries */
-void gui_create_form_select_menu(struct browser_window *bw,
- struct form_control *control);
+ /**
+ * Determine the MIME type of a local file.
+ *
+ * @note used in file fetcher
+ *
+ * \param unix_path Unix style path to file on disk
+ * \return Pointer to MIME type string (should not be freed) -
+ * invalidated on next call to fetch_filetype.
+ */
+ const char *(*filetype)(const char *unix_path);
-void gui_launch_url(const char *url);
+ /* Optional entries */
-struct ssl_cert_info;
+ /**
+ * Callback to translate resource to full url.
+ *
+ * @note used in resource fetcher
+ *
+ * Transforms a resource: path into a full URL. The returned URL
+ * is used as the target for a redirect. The caller takes ownership of
+ * the returned nsurl including unrefing it when finished with it.
+ *
+ * \param path The path of the resource to locate.
+ * \return A string containing the full URL of the target object or
+ * NULL if no suitable resource can be found.
+ */
+ struct nsurl* (*get_resource_url)(const char *path);
-void gui_cert_verify(nsurl *url, const struct ssl_cert_info *certs,
- unsigned long num, nserror (*cb)(bool proceed, void *pw),
- void *cbpw);
+ /**
+ * Find a MIME type for a local file
+ *
+ * @note only used in curl fetcher on RISC OS otherwise its a
+ * strdup of filetype.
+ *
+ * \param ro_path RISC OS style path to file on disk
+ * \return MIME type string (on heap, caller should free), or NULL
+ */
+ char *(*mimetype)(const char *ro_path);
+
+};
+
+
+/**
+ * User interface utf8 characterset conversion routines.
+ */
+struct gui_utf8_table {
+ /**
+ * Convert a UTF-8 encoded string into the system local encoding
+ *
+ * \param string The string to convert
+ * \param len The length (in bytes) of the string, or 0
+ * \param result Pointer to location in which to store result
+ * \return An nserror code
+ */
+ nserror (*utf8_to_local)(const char *string, size_t len, char **result);
+
+ /**
+ * Convert a string encoded in the system local encoding to UTF-8
+ *
+ * \param string The string to convert
+ * \param len The length (in bytes) of the string, or 0
+ * \param result Pointer to location in which to store result
+ * \return An nserror code
+ */
+ nserror (*local_to_utf8)(const char *string, size_t len, char **result);
+};
/**
- * Callback to translate resource to full url.
+ * function table for page text search.
+ */
+struct gui_search_table {
+ /**
+ * Change the displayed search status.
+ *
+ * \param found search pattern matched in text
+ * \param p gui private data pointer provided with search callbacks
+ */
+ void (*status)(bool found, void *p);
+
+ /**
+ * display hourglass while searching.
+ *
+ * \param active start/stop indicator
+ * \param p gui private data pointer provided with search callbacks
+ */
+ void (*hourglass)(bool active, void *p);
+
+ /**
+ * add search string to recent searches list
+ * front has full liberty how to implement the bare notification;
+ * core gives no guarantee of the integrity of the string
+ *
+ * \param string search pattern
+ * \param p gui private data pointer provided with search callbacks
+ */
+ void (*add_recent)(const char *string, void *p);
+
+ /**
+ * activate search forwards button in gui
+ *
+ * \param active activate/inactivate
+ * \param p gui private data pointer provided with search callbacks
+ */
+ void (*forward_state)(bool active, void *p);
+
+ /**
+ * activate search back button in gui
+ *
+ * \param active activate/inactivate
+ * \param p gui private data pointer provided with search callbacks
+ */
+ void (*back_state)(bool active, void *p);
+};
+
+/**
+ * Graphical user interface browser misc function table.
*
- * Transforms a resource: path into a full URL. The returned URL
- * is used as the target for a redirect. The caller takes ownership of
- * the returned nsurl including unrefing it when finished with it.
+ * function table implementing GUI interface to miscelaneous browser
+ * functionality
+ */
+struct gui_browser_table {
+ /* Mandantory entries */
+
+ /**
+ * called to let the frontend update its state and run any
+ * I/O operations.
+ */
+ void (*poll)(bool active);
+
+ /**
+ * Schedule a callback.
+ *
+ * \param t interval before the callback should be made in ms or
+ * negative value to remove any existing callback.
+ * \param callback callback function
+ * \param p user parameter passed to callback function
+ * \return NSERROR_OK on sucess or appropriate error on faliure
+ *
+ * The callback function will be called as soon as possible
+ * after the timeout has elapsed.
+ *
+ * Additional calls with the same callback and user parameter will
+ * reset the callback time to the newly specified value.
+ *
+ */
+ nserror (*schedule)(int t, void (*callback)(void *p), void *p);
+
+ /* Optional entries */
+
+ /** called to allow the gui to cleanup */
+ void (*quit)(void);
+
+ /**
+ * core has no fetcher for url
+ */
+ nserror (*launch_url)(struct nsurl *url);
+
+ /**
+ * create a form select menu
+ */
+ void (*create_form_select_menu)(struct browser_window *bw, struct form_control *control);
+
+ /**
+ * verify certificate
+ */
+ void (*cert_verify)(struct nsurl *url, const struct ssl_cert_info *certs, unsigned long num, nserror (*cb)(bool proceed, void *pw), void *cbpw);
+
+ /**
+ * Prompt user for login
+ */
+ void (*login)(struct nsurl *url, const char *realm,
+ nserror (*cb)(bool proceed, void *pw), void *cbpw);
+
+};
+
+/**
+ * NetSurf operation function table
*
- * \param path The path of the resource to locate.
- * \return A string containing the full URL of the target object or
- * NULL if no suitable resource can be found.
+ * Function table implementing interface operations for the browser core.
*/
-nsurl* gui_get_resource_url(const char *path);
+struct netsurf_table {
+
+ /**
+ * Browser table.
+ *
+ * Provides miscellaneous browser functionality. The table
+ * is mandantory and must be provided.
+ */
+ struct gui_browser_table *browser;
+
+ /** Window table */
+ struct gui_window_table *window;
+
+ /** Download table */
+ struct gui_download_table *download;
+
+ /** Clipboard table */
+ struct gui_clipboard_table *clipboard;
+
+ /** Fetcher table */
+ struct gui_fetch_table *fetch;
+
+ /**
+ * File table
+ *
+ * Provides file and filename operations to the core. The
+ * table is optional and may be NULL in which case the default
+ * posix compliant operations will be used.
+ */
+ struct gui_file_table *file;
+
+ /**
+ * UTF8 table.
+ *
+ * Provides for conversion between the gui local character
+ * encoding and utf8. The table optional and may be NULL which
+ * implies the local encoding is utf8.
+ */
+ struct gui_utf8_table *utf8;
+
+ /**
+ * Page search table.
+ *
+ * Provides routines for the interactive text search on a page.
+ */
+ struct gui_search_table *search;
-/** css callback to obtain named system colours from a frontend. */
-css_error gui_system_colour(void *pw, lwc_string *name, css_color *color);
+ /**
+ * Web search table.
+ *
+ * Used by the web search provider system. The table is
+ * optional and may be NULL which uses the default empty
+ * implementation.
+ */
+ struct gui_search_web_table *search_web;
-/** Obtain a named system colour from a frontend. */
-colour gui_system_colour_char(const char *name);
+ /**
+ * Low level cache table.
+ *
+ * Used by the low level cache to push objects to persistant
+ * storage. The table is optional and may be NULL which
+ * uses the default implementation.
+ */
+ struct gui_llcache_table *llcache;
+};
-bool gui_system_colour_init(void);
-void gui_system_colour_finalize(void);
#endif
diff --git a/desktop/gui_factory.c b/desktop/gui_factory.c
new file mode 100644
index 000000000..977805e9c
--- /dev/null
+++ b/desktop/gui_factory.c
@@ -0,0 +1,705 @@
+/*
+ * Copyright 2014 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "content/hlcache.h"
+#include "content/backing_store.h"
+
+#include "desktop/download.h"
+#include "desktop/searchweb.h"
+#include "desktop/gui_factory.h"
+#include "utils/file.h"
+
+/** The global interface table */
+struct netsurf_table *guit = NULL;
+
+
+static void gui_default_window_set_title(struct gui_window *g, const char *title)
+{
+}
+
+static void gui_default_window_set_url(struct gui_window *g, const char *url)
+{
+}
+
+static void gui_default_window_start_throbber(struct gui_window *g)
+{
+}
+
+static void gui_default_window_stop_throbber(struct gui_window *g)
+{
+}
+
+static bool gui_default_window_drag_start(struct gui_window *g,
+ gui_drag_type type,
+ const struct rect *rect)
+{
+ return true;
+}
+
+static void gui_default_window_save_link(struct gui_window *g,
+ const char *url,
+ const char *title)
+{
+}
+
+static void gui_default_window_set_icon(struct gui_window *g,
+ hlcache_handle *icon)
+{
+}
+
+static void gui_default_window_scroll_visible(struct gui_window *g,
+ int x0, int y0,
+ int x1, int y1)
+{
+ guit->window->set_scroll(g, x0, y0);
+}
+
+static void gui_default_window_new_content(struct gui_window *g)
+{
+}
+
+
+static bool gui_default_window_scroll_start(struct gui_window *g)
+{
+ return true;
+}
+
+static void gui_default_window_set_pointer(struct gui_window *g,
+ gui_pointer_shape shape)
+{
+}
+
+static void gui_default_window_set_status(struct gui_window *g,
+ const char *text)
+{
+}
+
+static void gui_default_window_place_caret(struct gui_window *g,
+ int x, int y, int height,
+ const struct rect *clip)
+{
+}
+
+static void gui_default_window_remove_caret(struct gui_window *g)
+{
+}
+
+static void gui_default_window_file_gadget_open(struct gui_window *g,
+ hlcache_handle *hl,
+ struct form_control *gadget)
+{
+}
+
+static void gui_default_window_drag_save_object(struct gui_window *g,
+ hlcache_handle *c,
+ gui_save_type type)
+{
+}
+
+static void gui_default_window_drag_save_selection(struct gui_window *g,
+ const char *selection)
+{
+}
+
+static void gui_default_window_start_selection(struct gui_window *g)
+{
+}
+
+
+/** verify window table is valid */
+static nserror verify_window_register(struct gui_window_table *gwt)
+{
+ /* check table is present */
+ if (gwt == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ /* check the mandantory fields are set */
+ if (gwt->create == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+ if (gwt->destroy == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+ if (gwt->redraw == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+ if (gwt->update == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+ if (gwt->get_scroll == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+ if (gwt->set_scroll == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+ if (gwt->get_dimensions == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+ if (gwt->update_extent == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+ if (gwt->reformat == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+
+ /* fill in the optional entries with defaults */
+ if (gwt->set_title == NULL) {
+ gwt->set_title = gui_default_window_set_title;
+ }
+ if (gwt->set_url == NULL) {
+ gwt->set_url = gui_default_window_set_url;
+ }
+ if (gwt->set_icon == NULL) {
+ gwt->set_icon = gui_default_window_set_icon;
+ }
+ if (gwt->set_status == NULL) {
+ gwt->set_status = gui_default_window_set_status;
+ }
+ if (gwt->set_pointer == NULL) {
+ gwt->set_pointer = gui_default_window_set_pointer;
+ }
+ if (gwt->place_caret == NULL) {
+ gwt->place_caret = gui_default_window_place_caret;
+ }
+ if (gwt->remove_caret == NULL) {
+ gwt->remove_caret = gui_default_window_remove_caret;
+ }
+ if (gwt->start_throbber == NULL) {
+ gwt->start_throbber = gui_default_window_start_throbber;
+ }
+ if (gwt->stop_throbber == NULL) {
+ gwt->stop_throbber = gui_default_window_stop_throbber;
+ }
+ if (gwt->drag_start == NULL) {
+ gwt->drag_start = gui_default_window_drag_start;
+ }
+ if (gwt->save_link == NULL) {
+ gwt->save_link = gui_default_window_save_link;
+ }
+ if (gwt->scroll_visible == NULL) {
+ gwt->scroll_visible = gui_default_window_scroll_visible;
+ }
+ if (gwt->new_content == NULL) {
+ gwt->new_content = gui_default_window_new_content;
+ }
+ if (gwt->scroll_start == NULL) {
+ gwt->scroll_start = gui_default_window_scroll_start;
+ }
+ if (gwt->file_gadget_open == NULL) {
+ gwt->file_gadget_open = gui_default_window_file_gadget_open;
+ }
+ if (gwt->drag_save_object == NULL) {
+ gwt->drag_save_object = gui_default_window_drag_save_object;
+ }
+ if (gwt->drag_save_selection == NULL) {
+ gwt->drag_save_selection = gui_default_window_drag_save_selection;
+ }
+ if (gwt->start_selection == NULL) {
+ gwt->start_selection = gui_default_window_start_selection;
+ }
+
+ return NSERROR_OK;
+}
+
+
+
+static struct gui_download_window *
+gui_default_download_create(download_context *ctx, struct gui_window *parent)
+{
+ return NULL;
+}
+
+static nserror gui_default_download_data(struct gui_download_window *dw,
+ const char *data, unsigned int size)
+{
+ return NSERROR_OK;
+}
+
+static void gui_default_download_error(struct gui_download_window *dw,
+ const char *error_msg)
+{
+}
+
+static void gui_default_download_done(struct gui_download_window *dw)
+{
+}
+
+
+/** verify download window table is valid */
+static nserror verify_download_register(struct gui_download_table *gdt)
+{
+ /* check table is present */
+ if (gdt == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ /* all enties are mandantory */
+ if (gdt->create == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+ if (gdt->data == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+ if (gdt->error == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+ if (gdt->done == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ return NSERROR_OK;
+}
+
+static void gui_default_get_clipboard(char **buffer, size_t *length)
+{
+ *buffer = NULL;
+ *length = 0;
+}
+
+static void gui_default_set_clipboard(const char *buffer, size_t length,
+ nsclipboard_styles styles[], int n_styles)
+{
+}
+
+static struct gui_clipboard_table default_clipboard_table = {
+ .get = gui_default_get_clipboard,
+ .set = gui_default_set_clipboard,
+};
+
+/** verify clipboard table is valid */
+static nserror verify_clipboard_register(struct gui_clipboard_table *gct)
+{
+ /* check table is present */
+ if (gct == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ /* optional operations */
+ if (gct->get == NULL) {
+ gct->get = gui_default_get_clipboard;
+ }
+ if (gct->set == NULL) {
+ gct->set = gui_default_set_clipboard;
+ }
+ return NSERROR_OK;
+}
+
+/**
+ * The default utf8 conversion implementation.
+ *
+ * The default implementation assumes the local encoding is utf8
+ * allowing the conversion to be a simple copy.
+ *
+ * @param [in] string The source string.
+ * @param [in] len The \a string length or 0 to compute it.
+ * @param [out] result A pointer to the converted string.
+ * @result NSERROR_OK or NSERROR_NOMEM if memory could not be allocated.
+ */
+static nserror gui_default_utf8(const char *string, size_t len, char **result)
+{
+ assert(string && result);
+
+ if (len == 0)
+ len = strlen(string);
+
+ *result = strndup(string, len);
+ if (!(*result))
+ return NSERROR_NOMEM;
+
+ return NSERROR_OK;
+}
+
+static struct gui_utf8_table default_utf8_table = {
+ .utf8_to_local = gui_default_utf8,
+ .local_to_utf8 = gui_default_utf8,
+};
+
+/** verify clipboard table is valid */
+static nserror verify_utf8_register(struct gui_utf8_table *gut)
+{
+ /* check table is present */
+ if (gut == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ /* mandantory operations */
+ if (gut->utf8_to_local == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+ if (gut->local_to_utf8 == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+ return NSERROR_OK;
+}
+
+static void gui_default_status(bool found, void *p)
+{
+}
+
+static void gui_default_hourglass(bool active, void *p)
+{
+}
+
+static void gui_default_add_recent(const char *string, void *p)
+{
+}
+
+static void gui_default_forward_state(bool active, void *p)
+{
+}
+
+static void gui_default_back_state(bool active, void *p)
+{
+}
+
+static struct gui_search_table default_search_table = {
+ .status = gui_default_status,
+ .hourglass = gui_default_hourglass,
+ .add_recent = gui_default_add_recent,
+ .forward_state = gui_default_forward_state,
+ .back_state = gui_default_back_state,
+};
+
+/** verify search table is valid */
+static nserror verify_search_register(struct gui_search_table *gst)
+{
+ /* check table is present */
+ if (gst == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ /* fill in the optional entries with defaults */
+ if (gst->status == NULL) {
+ gst->status = default_search_table.status;
+ }
+ if (gst->hourglass == NULL) {
+ gst->hourglass = default_search_table.hourglass;
+ }
+ if (gst->add_recent == NULL) {
+ gst->add_recent = default_search_table.add_recent;
+ }
+ if (gst->forward_state == NULL) {
+ gst->forward_state = default_search_table.forward_state;
+ }
+ if (gst->back_state == NULL) {
+ gst->back_state = default_search_table.back_state;
+ }
+
+ return NSERROR_OK;
+}
+
+static nserror
+gui_default_provider_update(const char *provider_name,
+ struct bitmap *provider_bitmap)
+{
+ return NSERROR_OK;
+}
+
+static struct gui_search_web_table default_search_web_table = {
+ .provider_update = gui_default_provider_update,
+};
+
+/** verify search table is valid */
+static nserror verify_search_web_register(struct gui_search_web_table *gswt)
+{
+ /* check table is present */
+ if (gswt == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ /* mandantory operations */
+ if (gswt->provider_update == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ return NSERROR_OK;
+}
+
+/** verify low level cache persistant backing store table is valid */
+static nserror verify_llcache_register(struct gui_llcache_table *glt)
+{
+ /* check table is present */
+ if (glt == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ /* mandantory operations */
+ if (glt->store == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+ if (glt->fetch == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+ if (glt->invalidate == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+ if (glt->initialise == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+ if (glt->finalise == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ return NSERROR_OK;
+}
+
+static nsurl *gui_default_get_resource_url(const char *path)
+{
+ return NULL;
+}
+
+static char *gui_default_mimetype(const char *path)
+{
+ return strdup(guit->fetch->filetype(path));
+}
+
+/** verify fetch table is valid */
+static nserror verify_fetch_register(struct gui_fetch_table *gft)
+{
+ /* check table is present */
+ if (gft == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ /* check the mandantory fields are set */
+ if (gft->filetype == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ /* fill in the optional entries with defaults */
+ if (gft->get_resource_url == NULL) {
+ gft->get_resource_url = gui_default_get_resource_url;
+ }
+ if (gft->mimetype == NULL) {
+ gft->mimetype = gui_default_mimetype;
+ }
+
+ return NSERROR_OK;
+}
+
+/** verify file table is valid */
+static nserror verify_file_register(struct gui_file_table *gft)
+{
+ /* check table is present */
+ if (gft == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ /* check the mandantory fields are set */
+ if (gft->mkpath == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+ if (gft->basename == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+ if (gft->nsurl_to_path == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+ if (gft->path_to_nsurl == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+ if (gft->mkdir_all == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ return NSERROR_OK;
+}
+
+static void gui_default_quit(void)
+{
+}
+
+
+static nserror gui_default_launch_url(struct nsurl *url)
+{
+ return NSERROR_NO_FETCH_HANDLER;
+}
+
+static void gui_default_create_form_select_menu(struct browser_window *bw,
+ struct form_control *control)
+{
+}
+
+
+static void gui_default_cert_verify(nsurl *url,
+ const struct ssl_cert_info *certs,
+ unsigned long num,
+ nserror (*cb)(bool proceed, void *pw),
+ void *cbpw)
+{
+ cb(false, cbpw);
+}
+
+static void gui_default_401login_open(nsurl *url, const char *realm,
+ nserror (*cb)(bool proceed, void *pw), void *cbpw)
+{
+ cb(false, cbpw);
+}
+
+static struct gui_download_table default_download_table = {
+ .create = gui_default_download_create,
+ .data = gui_default_download_data,
+ .error = gui_default_download_error,
+ .done = gui_default_download_done,
+};
+
+/** verify browser table is valid */
+static nserror verify_browser_register(struct gui_browser_table *gbt)
+{
+ /* check table is present */
+ if (gbt == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ /* check the mandantory fields are set */
+ if (gbt->poll == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ if (gbt->schedule == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ /* fill in the optional entries with defaults */
+ if (gbt->quit == NULL) {
+ gbt->quit = gui_default_quit;
+ }
+ if (gbt->launch_url == NULL) {
+ gbt->launch_url = gui_default_launch_url;
+ }
+ if (gbt->create_form_select_menu == NULL) {
+ gbt->create_form_select_menu = gui_default_create_form_select_menu;
+ }
+ if (gbt->cert_verify == NULL) {
+ gbt->cert_verify = gui_default_cert_verify;
+ }
+ if (gbt->login == NULL) {
+ gbt->login = gui_default_401login_open;
+ }
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in desktop/gui_factory.h */
+nserror gui_factory_register(struct netsurf_table *gt)
+{
+ nserror err;
+
+ /* ensure not already initialised */
+ if (guit != NULL) {
+ return NSERROR_INIT_FAILED;
+ }
+
+ /* check table is present */
+ if (gt == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ /* browser table */
+ err = verify_browser_register(gt->browser);
+ if (err != NSERROR_OK) {
+ return err;
+ }
+
+ /* window table */
+ err = verify_window_register(gt->window);
+ if (err != NSERROR_OK) {
+ return err;
+ }
+
+ /* fetch table */
+ err = verify_fetch_register(gt->fetch);
+ if (err != NSERROR_OK) {
+ return err;
+ }
+
+ /* file table */
+ if (gt->file == NULL) {
+ gt->file = default_file_table;
+ }
+ err = verify_file_register(gt->file);
+ if (err != NSERROR_OK) {
+ return err;
+ }
+
+ /* download table */
+ if (gt->download == NULL) {
+ /* set default download table */
+ gt->download = &default_download_table;
+ }
+ err = verify_download_register(gt->download);
+ if (err != NSERROR_OK) {
+ return err;
+ }
+
+ /* clipboard table */
+ if (gt->clipboard == NULL) {
+ /* set default clipboard table */
+ gt->clipboard = &default_clipboard_table;
+ }
+ err = verify_clipboard_register(gt->clipboard);
+ if (err != NSERROR_OK) {
+ return err;
+ }
+
+ /* utf8 table */
+ if (gt->utf8 == NULL) {
+ /* set default utf8 table */
+ gt->utf8 = &default_utf8_table;
+ }
+ err = verify_utf8_register(gt->utf8);
+ if (err != NSERROR_OK) {
+ return err;
+ }
+
+ /* search table */
+ if (gt->search == NULL) {
+ /* set default search table */
+ gt->search = &default_search_table;
+ }
+ err = verify_search_register(gt->search);
+ if (err != NSERROR_OK) {
+ return err;
+ }
+
+ /* web search table */
+ if (gt->search_web == NULL) {
+ /* set default search table */
+ gt->search_web = &default_search_web_table;
+ }
+ err = verify_search_web_register(gt->search_web);
+ if (err != NSERROR_OK) {
+ return err;
+ }
+
+ /* llcache table */
+ if (gt->llcache == NULL) {
+ /* set default backing store table */
+ gt->llcache = null_llcache_table;
+ }
+ err = verify_llcache_register(gt->llcache);
+ if (err != NSERROR_OK) {
+ return err;
+ }
+
+ guit = gt;
+
+ return NSERROR_OK;
+}
diff --git a/desktop/gui_factory.h b/desktop/gui_factory.h
new file mode 100644
index 000000000..3c8661577
--- /dev/null
+++ b/desktop/gui_factory.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2014 vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Interface to gui interface factory
+ */
+
+#ifndef _NETSURF_DESKTOP_GUI_FACTORY_H_
+#define _NETSURF_DESKTOP_GUI_FACTORY_H_
+
+#include "desktop/gui.h"
+
+/** The global operation table */
+extern struct netsurf_table *guit;
+
+/** register and verify global operation table
+ *
+ * @param gt The global table to register
+ * @return NSERROR_OK on success or error code on faliure. On faliure
+ * global table will not be initialised
+ */
+nserror gui_factory_register(struct netsurf_table *gt);
+
+#endif
diff --git a/desktop/hotlist.c b/desktop/hotlist.c
index 01fabc257..f0eda841b 100644
--- a/desktop/hotlist.c
+++ b/desktop/hotlist.c
@@ -19,6 +19,7 @@
#include <assert.h>
#include <stdlib.h>
+#include <string.h>
#include <dom/dom.h>
#include <dom/bindings/hubbub/parser.h>
@@ -26,6 +27,7 @@
#include "content/urldb.h"
#include "desktop/hotlist.h"
#include "desktop/treeview.h"
+#include "desktop/browser.h"
#include "utils/corestrings.h"
#include "utils/messages.h"
#include "utils/utils.h"
@@ -472,23 +474,22 @@ static nserror hotlist_tree_node_entry_cb(
case TREE_MSG_NODE_LAUNCH:
{
nserror error;
- struct browser_window *clone = NULL;
- enum browser_window_nav_flags flags =
- BROWSER_WINDOW_VERIFIABLE |
- BROWSER_WINDOW_HISTORY |
- BROWSER_WINDOW_TAB;
+ struct browser_window *existing = NULL;
+ enum browser_window_create_flags flags =
+ BW_CREATE_HISTORY;
- /* TODO: Set clone window, to window that new tab appears in */
+ /* TODO: Set existing to window that new tab appears in */
if (msg.data.node_launch.mouse &
(BROWSER_MOUSE_MOD_1 | BROWSER_MOUSE_MOD_2) ||
- clone == NULL) {
+ existing == NULL) {
/* Shift or Ctrl launch, open in new window rather
* than tab. */
- flags ^= BROWSER_WINDOW_TAB;
+ /* TODO: flags ^= BW_CREATE_TAB; */
}
- error = browser_window_create(flags, e->url, NULL, clone, NULL);
+ error = browser_window_create(flags, e->url, NULL,
+ existing, NULL);
if (error != NSERROR_OK) {
warn_user(messages_get_errorcode(error), 0);
}
@@ -879,21 +880,21 @@ static nserror hotlist_export_enter_cb(void *ctx, void *node_data,
enum treeview_node_type type, bool *abort)
{
struct treeview_export_walk_ctx *tw = ctx;
+ nserror ret;
if (type == TREE_NODE_ENTRY) {
struct hotlist_entry *e = node_data;
- utf8_convert_ret ret;
char *t_text;
char *u_text;
ret = utf8_to_html(e->data[HL_TITLE].value, "iso-8859-1",
e->data[HL_TITLE].value_len, &t_text);
- if (ret != UTF8_CONVERT_OK)
+ if (ret != NSERROR_OK)
return NSERROR_SAVE_FAILED;
ret = utf8_to_html(e->data[HL_URL].value, "iso-8859-1",
e->data[HL_URL].value_len, &u_text);
- if (ret != UTF8_CONVERT_OK) {
+ if (ret != NSERROR_OK) {
free(t_text);
return NSERROR_SAVE_FAILED;
}
@@ -906,12 +907,11 @@ static nserror hotlist_export_enter_cb(void *ctx, void *node_data,
} else if (type == TREE_NODE_FOLDER) {
struct hotlist_folder *f = node_data;
- utf8_convert_ret ret;
char *f_text;
ret = utf8_to_html(f->data.value, "iso-8859-1",
f->data.value_len, &f_text);
- if (ret != UTF8_CONVERT_OK)
+ if (ret != NSERROR_OK)
return NSERROR_SAVE_FAILED;
if (f == hl_ctx.default_folder) {
@@ -1502,10 +1502,11 @@ bool hotlist_has_selection(void)
bool hotlist_get_selection(nsurl **url, const char **title)
{
struct hotlist_entry *e;
+ enum treeview_node_type type;
void *v;
- treeview_get_selection(hl_ctx.tree, &v);
- if (v == NULL) {
+ type = treeview_get_selection(hl_ctx.tree, &v);
+ if (type != TREE_NODE_ENTRY || v == NULL) {
*url = NULL;
*title = NULL;
return false;
diff --git a/desktop/hotlist.h b/desktop/hotlist.h
index e5ae83499..7e2aa6955 100644
--- a/desktop/hotlist.h
+++ b/desktop/hotlist.h
@@ -22,12 +22,12 @@
#include <stdbool.h>
#include <stdint.h>
-#include "desktop/browser.h"
#include "desktop/core_window.h"
#include "desktop/textinput.h"
#include "utils/errors.h"
#include "utils/nsurl.h"
+enum browser_mouse_state;
/**
* Initialise the hotlist.
@@ -183,7 +183,7 @@ void hotlist_redraw(int x, int y, struct rect *clip,
* \param x X coordinate
* \param y Y coordinate
*/
-void hotlist_mouse_action(browser_mouse_state mouse, int x, int y);
+void hotlist_mouse_action(enum browser_mouse_state mouse, int x, int y);
/**
* Key press handling.
diff --git a/desktop/knockout.c b/desktop/knockout.c
index 0385ee80b..fa827cb39 100644
--- a/desktop/knockout.c
+++ b/desktop/knockout.c
@@ -64,10 +64,13 @@
#include <assert.h>
#include <string.h>
-#include "desktop/knockout.h"
-#include "desktop/plotters.h"
+#include <stdio.h>
+
#include "image/bitmap.h"
#include "utils/log.h"
+#include "content/content.h"
+#include "desktop/knockout.h"
+#include "desktop/plotters.h"
/* Define to enable knockout debug */
#undef KNOCKOUT_DEBUG
diff --git a/desktop/local_history.h b/desktop/local_history.h
deleted file mode 100644
index c4faa8532..000000000
--- a/desktop/local_history.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright 2006 James Bursa <bursa@users.sourceforge.net>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/** \file
- * Browser history tree (interface).
- */
-
-#ifndef _NETSURF_DESKTOP_HISTORY_H_
-#define _NETSURF_DESKTOP_HISTORY_H_
-
-#include <stdbool.h>
-#include <libwapcaplet/libwapcaplet.h>
-
-struct hlcache_handle;
-struct history;
-struct browser_window;
-struct history_entry;
-struct redraw_context;
-
-struct history *history_create(void);
-struct history *history_clone(struct history *history);
-void history_add(struct history *history, struct hlcache_handle *content,
- lwc_string *frag_id);
-void history_update(struct history *history, struct hlcache_handle *content);
-void history_destroy(struct history *history);
-void history_back(struct browser_window *bw, struct history *history);
-void history_forward(struct browser_window *bw, struct history *history);
-bool history_back_available(struct history *history);
-bool history_forward_available(struct history *history);
-void history_size(struct history *history, int *width, int *height);
-bool history_redraw(struct history *history, const struct redraw_context *ctx);
-bool history_redraw_rectangle(struct history *history,
- int x0, int y0, int x1, int y1, int x, int y,
- const struct redraw_context *ctx);
-bool history_click(struct browser_window *bw, struct history *history,
- int x, int y, bool new_window);
-const char *history_position_url(struct history *history, int x, int y);
-
-/**
- * Callback function type for history enumeration
- *
- * \param history history being enumerated
- * \param x0, y0, x1, y1 Coordinates of entry in history tree view
- * \param entry Current history entry
- * \return true to continue enumeration, false to cancel enumeration
- */
-typedef bool (*history_enumerate_cb)(const struct history *history, int x0, int y0,
- int x1, int y1,
- const struct history_entry *entry, void *user_data);
-
-/**
- * Enumerate all entries in the history.
- * Do not change the history while it is being enumerated.
- *
- * \param history history to enumerate
- * \param cb callback function
- * \param user_data context pointer passed to cb
- */
-void history_enumerate(const struct history *history, history_enumerate_cb cb, void *user_data);
-
-/**
- * Enumerate all entries that will be reached by the 'forward' button
- *
- * \param history The history object to enumerate in
- * \param cb The callback function
- * \param user_data Data passed to the callback
- */
-void history_enumerate_forward( struct history *history,
- history_enumerate_cb cb, void *user_data );
-
-/**
- * Enumerate all entries that will be reached by the 'back' button
- *
- * \param history The history object to enumerate in
- * \param cb The callback function
- * \param user_data Data passed to the callback
- */
-void history_enumerate_back( struct history *history,
- history_enumerate_cb cb, void *user_data );
-
-/**
- * Returns the URL to a history entry
- *
- * \param entry the history entry to retrieve the URL from
- * \return the URL
- */
-const char *history_entry_get_url(const struct history_entry *entry);
-
-/**
- * Returns the URL to a history entry
- *
- * \param entry the history entry to retrieve the fragment id from
- * \return the fragment id
- */
-const char *history_entry_get_fragment_id(const struct history_entry *entry);
-
-/**
- * Returns the title of a history entry
- *
- * \param entry the history entry to retrieve the title from
- * \return the title
- */
-const char *history_entry_get_title(const struct history_entry *entry);
-
-/**
- * Open a history entry in the specified browser window
- *
- * \param bw browser window
- * \param history history containing entry
- * \param entry entry to open
- * \param new_window open entry in new window
- */
-void history_go(struct browser_window *bw, struct history *history,
- struct history_entry *entry, bool new_window);
-
-#endif
diff --git a/desktop/mouse.h b/desktop/mouse.h
index 9a3a16702..083bd1731 100644
--- a/desktop/mouse.h
+++ b/desktop/mouse.h
@@ -27,7 +27,7 @@
/* Mouse state. 1 is primary mouse button (e.g. Select on RISC OS).
* 2 is secondary mouse button (e.g. Adjust on RISC OS). */
-typedef enum {
+typedef enum browser_mouse_state {
BROWSER_MOUSE_HOVER = 0, /* No mouse buttons pressed,
* May be used to indicate
* hover or end of drag. */
@@ -78,13 +78,14 @@ typedef enum {
} browser_mouse_state;
-typedef enum { GUI_POINTER_DEFAULT, GUI_POINTER_POINT, GUI_POINTER_CARET,
- GUI_POINTER_MENU, GUI_POINTER_UP, GUI_POINTER_DOWN,
- GUI_POINTER_LEFT, GUI_POINTER_RIGHT, GUI_POINTER_RU,
- GUI_POINTER_LD, GUI_POINTER_LU, GUI_POINTER_RD,
- GUI_POINTER_CROSS, GUI_POINTER_MOVE, GUI_POINTER_WAIT,
- GUI_POINTER_HELP, GUI_POINTER_NO_DROP, GUI_POINTER_NOT_ALLOWED,
- GUI_POINTER_PROGRESS } gui_pointer_shape;
+typedef enum gui_pointer_shape {
+ GUI_POINTER_DEFAULT, GUI_POINTER_POINT, GUI_POINTER_CARET,
+ GUI_POINTER_MENU, GUI_POINTER_UP, GUI_POINTER_DOWN,
+ GUI_POINTER_LEFT, GUI_POINTER_RIGHT, GUI_POINTER_RU,
+ GUI_POINTER_LD, GUI_POINTER_LU, GUI_POINTER_RD,
+ GUI_POINTER_CROSS, GUI_POINTER_MOVE, GUI_POINTER_WAIT,
+ GUI_POINTER_HELP, GUI_POINTER_NO_DROP, GUI_POINTER_NOT_ALLOWED,
+ GUI_POINTER_PROGRESS } gui_pointer_shape;
/** Mouse pointer type */
typedef enum {
diff --git a/desktop/netsurf.c b/desktop/netsurf.c
index fa026dc6a..579648bae 100644
--- a/desktop/netsurf.c
+++ b/desktop/netsurf.c
@@ -29,7 +29,7 @@
#include "utils/config.h"
#include "utils/utsname.h"
#include "content/content_factory.h"
-#include "content/fetch.h"
+#include "content/fetchers.h"
#include "content/hlcache.h"
#include "content/mimesniff.h"
#include "content/urldb.h"
@@ -37,9 +37,9 @@
#include "image/image.h"
#include "image/image_cache.h"
#include "desktop/netsurf.h"
-#include "desktop/401login.h"
#include "desktop/browser.h"
-#include "desktop/gui.h"
+#include "desktop/system_colour.h"
+#include "desktop/gui_factory.h"
#include "utils/nsoption.h"
#include "desktop/searchweb.h"
@@ -67,13 +67,24 @@
*/
#define SPECULATE_SMALL 4096
-/* the time between cache clean runs in ms */
+/** the time between image cache clean runs in ms. */
#define IMAGE_CACHE_CLEAN_TIME (10 * 1000)
+/** default time between content cache cleans. */
#define HL_CACHE_CLEAN_TIME (2 * IMAGE_CACHE_CLEAN_TIME)
+/** default minimum object time before object is pushed to backing store. */
+#define LLCACHE_MIN_DISC_LIFETIME (60 * 30)
+
+/** default maximum bandwidth for backing store writeout. */
+#define LLCACHE_MAX_DISC_BANDWIDTH (128 * 1024)
+
+/** ensure there is a minimal amount of memory for source objetcs and
+ * decoded bitmaps.
+ */
+#define MINIMUM_MEMORY_CACHE_SIZE (2 * 1024 * 1024)
+
bool netsurf_quit = false;
-bool verbose_log = false;
static void netsurf_lwc_iterator(lwc_string *str, void *pw)
{
@@ -94,14 +105,14 @@ static nserror netsurf_llcache_query_handler(const llcache_query *query,
{
switch (query->type) {
case LLCACHE_QUERY_AUTH:
- gui_401login_open(query->url, query->data.auth.realm, cb, cbpw);
+ guit->browser->login(query->url, query->data.auth.realm, cb, cbpw);
break;
case LLCACHE_QUERY_REDIRECT:
/** \todo Need redirect query dialog */
/* For now, do nothing, as this query type isn't emitted yet */
break;
case LLCACHE_QUERY_SSL:
- gui_cert_verify(query->url, query->data.ssl.certs,
+ guit->browser->cert_verify(query->url, query->data.ssl.certs,
query->data.ssl.num, cb, cbpw);
break;
}
@@ -109,20 +120,25 @@ static nserror netsurf_llcache_query_handler(const llcache_query *query,
return NSERROR_OK;
}
-#define MINIMUM_MEMORY_CACHE_SIZE (2 * 1024 * 1024)
-
-/**
- * Initialise components used by gui NetSurf.
- */
+/* exported interface documented in desktop/netsurf.h */
+nserror netsurf_register(struct netsurf_table *table)
+{
+ /* register the operation handlers */
+ return gui_factory_register(table);
+}
-nserror netsurf_init(const char *messages)
+/* exported interface documented in desktop/netsurf.h */
+nserror netsurf_init(const char *messages, const char *store_path)
{
- nserror error;
+ nserror ret;
struct utsname utsname;
- nserror ret = NSERROR_OK;
struct hlcache_parameters hlcache_parameters = {
.bg_clean_time = HL_CACHE_CLEAN_TIME,
- .cb = netsurf_llcache_query_handler,
+ .llcache = {
+ .cb = netsurf_llcache_query_handler,
+ .minimum_lifetime = LLCACHE_MIN_DISC_LIFETIME,
+ .bandwidth = LLCACHE_MAX_DISC_BANDWIDTH,
+ }
};
struct image_cache_parameters image_cache_parameters = {
.bg_clean_time = IMAGE_CACHE_CLEAN_TIME,
@@ -152,70 +168,86 @@ nserror netsurf_init(const char *messages)
messages_load(messages);
/* corestrings init */
- error = corestrings_init();
- if (error != NSERROR_OK)
- return error;
+ ret = corestrings_init();
+ if (ret != NSERROR_OK)
+ return ret;
/* set up cache limits based on the memory cache size option */
- hlcache_parameters.limit = nsoption_int(memory_cache_size);
+ hlcache_parameters.llcache.limit = nsoption_int(memory_cache_size);
- if (hlcache_parameters.limit < MINIMUM_MEMORY_CACHE_SIZE) {
- hlcache_parameters.limit = MINIMUM_MEMORY_CACHE_SIZE;
- LOG(("Setting minimum memory cache size to %d",
- hlcache_parameters.limit));
+ if (hlcache_parameters.llcache.limit < MINIMUM_MEMORY_CACHE_SIZE) {
+ hlcache_parameters.llcache.limit = MINIMUM_MEMORY_CACHE_SIZE;
+ LOG(("Setting minimum memory cache size %d",
+ hlcache_parameters.llcache.limit));
}
/* image cache is 25% of total memory cache size */
- image_cache_parameters.limit = (hlcache_parameters.limit * 25) / 100;
+ image_cache_parameters.limit = (hlcache_parameters.llcache.limit * 25) / 100;
/* image cache hysteresis is 20% of the image cache size */
image_cache_parameters.hysteresis = (image_cache_parameters.limit * 20) / 100;
/* account for image cache use from total */
- hlcache_parameters.limit -= image_cache_parameters.limit;
+ hlcache_parameters.llcache.limit -= image_cache_parameters.limit;
+
+ /* set backing store target limit */
+ hlcache_parameters.llcache.store.limit = nsoption_uint(disc_cache_size);
+
+ /* set backing store hysterissi to 20% */
+ hlcache_parameters.llcache.store.hysteresis = (hlcache_parameters.llcache.store.limit * 20) / 100;;
+
+ /* set the path to the backing store */
+ hlcache_parameters.llcache.store.path = store_path;
/* image handler bitmap cache */
- error = image_cache_init(&image_cache_parameters);
- if (error != NSERROR_OK)
- return error;
+ ret = image_cache_init(&image_cache_parameters);
+ if (ret != NSERROR_OK)
+ return ret;
/* content handler initialisation */
- error = nscss_init();
- if (error != NSERROR_OK)
- return error;
+ ret = nscss_init();
+ if (ret != NSERROR_OK)
+ return ret;
- error = html_init();
- if (error != NSERROR_OK)
- return error;
+ ret = html_init();
+ if (ret != NSERROR_OK)
+ return ret;
- error = image_init();
- if (error != NSERROR_OK)
- return error;
+ ret = image_init();
+ if (ret != NSERROR_OK)
+ return ret;
- error = textplain_init();
- if (error != NSERROR_OK)
- return error;
+ ret = textplain_init();
+ if (ret != NSERROR_OK)
+ return ret;
- error = mimesniff_init();
- if (error != NSERROR_OK)
- return error;
+ ret = mimesniff_init();
+ if (ret != NSERROR_OK)
+ return ret;
url_init();
setlocale(LC_ALL, "C");
- fetch_init();
+ /* initialise the fetchers */
+ ret = fetcher_init();
+ if (ret != NSERROR_OK)
+ return ret;
/* Initialise the hlcache and allow it to init the llcache for us */
- hlcache_initialise(&hlcache_parameters);
+ ret = hlcache_initialise(&hlcache_parameters);
+ if (ret != NSERROR_OK)
+ return ret;
/* Initialize system colours */
- gui_system_colour_init();
+ ret = ns_system_colour_init();
+ if (ret != NSERROR_OK)
+ return ret;
js_initialise();
- return ret;
+ return NSERROR_OK;
}
@@ -225,8 +257,7 @@ nserror netsurf_init(const char *messages)
int netsurf_main_loop(void)
{
while (!netsurf_quit) {
- gui_poll(fetch_active);
- hlcache_poll();
+ guit->browser->poll(false);
}
return 0;
@@ -241,19 +272,19 @@ void netsurf_exit(void)
hlcache_stop();
LOG(("Closing GUI"));
- gui_quit();
+ guit->browser->quit();
LOG(("Finalising JavaScript"));
js_finalise();
- LOG(("Closing search and related resources"));
- search_web_cleanup();
+ LOG(("Finalising Web Search"));
+ search_web_finalise();
LOG(("Finalising high-level cache"));
hlcache_finalise();
LOG(("Closing fetches"));
- fetch_quit();
+ fetcher_quit();
mimesniff_fini();
@@ -270,7 +301,7 @@ void netsurf_exit(void)
urldb_destroy();
LOG(("Destroying System colours"));
- gui_system_colour_finalize();
+ ns_system_colour_finalize();
corestrings_fini();
LOG(("Remaining lwc strings:"));
@@ -278,5 +309,3 @@ void netsurf_exit(void)
LOG(("Exited successfully"));
}
-
-
diff --git a/desktop/netsurf.h b/desktop/netsurf.h
index bfdb647ff..6c6a22a86 100644
--- a/desktop/netsurf.h
+++ b/desktop/netsurf.h
@@ -23,13 +23,37 @@
#include "utils/errors.h"
extern bool netsurf_quit;
-extern bool verbose_log;
extern const char * const netsurf_version;
extern const int netsurf_version_major;
extern const int netsurf_version_minor;
-nserror netsurf_init(const char *messages);
-extern void netsurf_exit(void);
+struct netsurf_table;
+
+/**
+ * Register operation table.
+ *
+ * @param table NetSurf operations table.
+ * @return NSERROR_OK on success or error code on faliure.
+ */
+nserror netsurf_register(struct netsurf_table *table);
+
+/**
+ * Initialise netsurf core.
+ *
+ * @param messages path to translation mesage file.
+ * @return NSERROR_OK on success or error code on faliure.
+ */
+nserror netsurf_init(const char *messages, const char *store_path);
+
+/**
+ * Run event loop.
+ */
extern int netsurf_main_loop(void);
+/**
+ * Finalise NetSurf core
+ */
+extern void netsurf_exit(void);
+
+
#endif
diff --git a/desktop/options.h b/desktop/options.h
index 391dfbc08..33ecb7554 100644
--- a/desktop/options.h
+++ b/desktop/options.h
@@ -89,7 +89,7 @@ NSOPTION_STRING(accept_charset, NULL)
NSOPTION_INTEGER(memory_cache_size, 12 * 1024 * 1024)
/** Preferred expiry size of disc cache / bytes. */
-NSOPTION_INTEGER(disc_cache_size, 1024 * 1024 * 1024)
+NSOPTION_UINT(disc_cache_size, 1024 * 1024 * 1024)
/** Preferred expiry age of disc cache / days. */
NSOPTION_INTEGER(disc_cache_age, 28)
diff --git a/desktop/plotters.h b/desktop/plotters.h
index 448cedef5..c34692433 100644
--- a/desktop/plotters.h
+++ b/desktop/plotters.h
@@ -24,8 +24,9 @@
#define _NETSURF_DESKTOP_PLOTTERS_H_
#include <stdbool.h>
-#include "css/css.h"
-#include "content/content.h"
+#include <stdio.h>
+
+#include "utils/types.h"
#include "desktop/plot_style.h"
struct bitmap;
diff --git a/desktop/save_complete.c b/desktop/save_complete.c
index 0c67654a6..71187eb10 100644
--- a/desktop/save_complete.c
+++ b/desktop/save_complete.c
@@ -21,8 +21,6 @@
* Save HTML document with dependencies (implementation).
*/
-#include "utils/config.h"
-
#include <assert.h>
#include <ctype.h>
#include <errno.h>
@@ -30,20 +28,24 @@
#include <string.h>
#include <sys/types.h>
#include <regex.h>
-
#include <dom/dom.h>
-#include "content/content.h"
-#include "content/hlcache.h"
-#include "css/css.h"
-#include "desktop/save_complete.h"
-#include "render/box.h"
-#include "render/html.h"
+#include "utils/config.h"
#include "utils/corestrings.h"
#include "utils/log.h"
#include "utils/nsurl.h"
#include "utils/utf8.h"
#include "utils/utils.h"
+#include "utils/file.h"
+#include "utils/messages.h"
+#include "content/content.h"
+#include "content/hlcache.h"
+#include "css/css.h"
+#include "render/box.h"
+#include "render/html.h"
+
+#include "desktop/gui_factory.h"
+#include "desktop/save_complete.h"
regex_t save_complete_import_re;
@@ -142,19 +144,19 @@ static bool save_complete_save_buffer(save_complete_ctx *ctx,
const char *leafname, const char *data, size_t data_len,
lwc_string *mime_type)
{
+ nserror ret;
FILE *fp;
- bool error;
- char fullpath[PATH_MAX];
+ char *fname = NULL;
- strncpy(fullpath, ctx->path, sizeof fullpath);
- error = path_add_part(fullpath, sizeof fullpath, leafname);
- if (error == false) {
- warn_user("NoMemory", NULL);
+ ret = netsurf_mkpath(&fname, NULL, 2, ctx->path, leafname);
+ if (ret != NSERROR_OK) {
+ warn_user(messages_get_errorcode(ret), 0);
return false;
}
- fp = fopen(fullpath, "wb");
+ fp = fopen(fname, "wb");
if (fp == NULL) {
+ free(fname);
LOG(("fopen(): errno = %i", errno));
warn_user("SaveError", strerror(errno));
return false;
@@ -164,8 +166,10 @@ static bool save_complete_save_buffer(save_complete_ctx *ctx,
fclose(fp);
- if (ctx->set_type != NULL)
- ctx->set_type(fullpath, mime_type);
+ if (ctx->set_type != NULL) {
+ ctx->set_type(fname, mime_type);
+ }
+ free(fname);
return true;
}
@@ -351,8 +355,11 @@ static bool save_complete_save_imported_sheets(save_complete_ctx *ctx,
uint32_t i;
for (i = 0; i < import_count; i++) {
- if (save_complete_save_stylesheet(ctx, imports[i].c) == false)
- return false;
+ /* treat a valid content as a stylesheet to save */
+ if ((imports[i].c != NULL) &&
+ (save_complete_save_stylesheet(ctx, imports[i].c) == false)) {
+ return false;
+ }
}
return true;
@@ -435,7 +442,7 @@ static bool save_complete_save_html_objects(save_complete_ctx *ctx,
object = html_get_objects(c, &count);
for (; object != NULL; object = object->next) {
- if (object->content != NULL) {
+ if ((object->content != NULL) && (object->box != NULL)) {
if (save_complete_save_html_object(ctx,
object->content) == false)
return false;
@@ -546,7 +553,6 @@ static bool save_complete_rewrite_url_value(save_complete_ctx *ctx,
hlcache_handle *content;
char *escaped;
nserror error;
- utf8_convert_ret ret;
error = nsurl_join(ctx->base, value, &url);
if (error == NSERROR_NOMEM)
@@ -561,11 +567,11 @@ static bool save_complete_rewrite_url_value(save_complete_ctx *ctx,
fprintf(ctx->fp, "\"%p\"", content);
} else {
/* no match found */
- ret = utf8_to_html(nsurl_access(url), "UTF-8",
+ error = utf8_to_html(nsurl_access(url), "UTF-8",
nsurl_length(url), &escaped);
nsurl_unref(url);
- if (ret != UTF8_CONVERT_OK)
+ if (error != NSERROR_OK)
return false;
fprintf(ctx->fp, "\"%s\"", escaped);
@@ -573,8 +579,8 @@ static bool save_complete_rewrite_url_value(save_complete_ctx *ctx,
free(escaped);
}
} else {
- ret = utf8_to_html(value, "UTF-8", value_len, &escaped);
- if (ret != UTF8_CONVERT_OK)
+ error = utf8_to_html(value, "UTF-8", value_len, &escaped);
+ if (error != NSERROR_OK)
return false;
fprintf(ctx->fp, "\"%s\"", escaped);
@@ -589,10 +595,10 @@ static bool save_complete_write_value(save_complete_ctx *ctx,
const char *value, size_t value_len)
{
char *escaped;
- utf8_convert_ret ret;
+ nserror ret;
ret = utf8_to_html(value, "UTF-8", value_len, &escaped);
- if (ret != UTF8_CONVERT_OK)
+ if (ret != NSERROR_OK)
return false;
fprintf(ctx->fp, "\"%s\"", escaped);
@@ -918,7 +924,7 @@ static bool save_complete_node_handler(dom_node *node,
save_complete_ctx *ctx = ctxin;
dom_node_type type;
dom_exception error;
- utf8_convert_ret ret;
+ nserror ret;
error = dom_node_get_node_type(node, &type);
if (error != DOM_NO_ERR)
@@ -952,7 +958,7 @@ static bool save_complete_node_handler(dom_node *node,
ret = utf8_to_html(text_data, "UTF-8",
text_len, &escaped);
- if (ret != UTF8_CONVERT_OK)
+ if (ret != NSERROR_OK)
return false;
fwrite(escaped, sizeof(*escaped),
@@ -1034,29 +1040,30 @@ static bool save_complete_node_handler(dom_node *node,
static bool save_complete_save_html_document(save_complete_ctx *ctx,
hlcache_handle *c, bool index)
{
- bool error;
+ nserror ret;
FILE *fp;
+ char *fname = NULL;
dom_document *doc;
lwc_string *mime_type;
char filename[32];
- char fullpath[PATH_MAX];
- strncpy(fullpath, ctx->path, sizeof fullpath);
-
- if (index)
+ if (index) {
snprintf(filename, sizeof filename, "index");
- else
+ } else {
snprintf(filename, sizeof filename, "%p", c);
+ }
- error = path_add_part(fullpath, sizeof fullpath, filename);
- if (error == false) {
- warn_user("NoMemory", NULL);
+ ret = netsurf_mkpath(&fname, NULL, 2, ctx->path, filename);
+ if (ret != NSERROR_OK) {
+ warn_user(messages_get_errorcode(ret), NULL);
return false;
}
- fp = fopen(fullpath, "wb");
+ fp = fopen(fname, "wb");
if (fp == NULL) {
- warn_user("NoMemory", NULL);
+ free(fname);
+ LOG(("fopen(): errno = %i", errno));
+ warn_user("SaveError", strerror(errno));
return false;
}
@@ -1068,6 +1075,7 @@ static bool save_complete_save_html_document(save_complete_ctx *ctx,
if (save_complete_libdom_treewalk((dom_node *) doc,
save_complete_node_handler, ctx) == false) {
+ free(fname);
warn_user("NoMemory", 0);
fclose(fp);
return false;
@@ -1078,10 +1086,11 @@ static bool save_complete_save_html_document(save_complete_ctx *ctx,
mime_type = content_get_mime_type(c);
if (mime_type != NULL) {
if (ctx->set_type != NULL)
- ctx->set_type(fullpath, mime_type);
+ ctx->set_type(fname, mime_type);
lwc_string_unref(mime_type);
}
+ free(fname);
return true;
}
@@ -1119,19 +1128,18 @@ static bool save_complete_save_html(save_complete_ctx *ctx, hlcache_handle *c,
static bool save_complete_inventory(save_complete_ctx *ctx)
{
+ nserror ret;
FILE *fp;
- bool error;
+ char *fname = NULL;
save_complete_entry *entry;
- char fullpath[PATH_MAX];
- strncpy(fullpath, ctx->path, sizeof fullpath);
- error = path_add_part(fullpath, sizeof fullpath, "Inventory");
- if (error == false) {
- warn_user("NoMemory", NULL);
+ ret = netsurf_mkpath(&fname, NULL, 2, ctx->path, "Inventory");
+ if (ret != NSERROR_OK) {
return false;
}
- fp = fopen(fullpath, "w");
+ fp = fopen(fname, "w");
+ free(fname);
if (fp == NULL) {
LOG(("fopen(): errno = %i", errno));
warn_user("SaveError", strerror(errno));
@@ -1193,8 +1201,9 @@ bool save_complete(hlcache_handle *c, const char *path,
result = save_complete_save_html(&ctx, c, true);
- if (result)
+ if (result) {
result = save_complete_inventory(&ctx);
+ }
save_complete_ctx_finalise(&ctx);
diff --git a/desktop/save_text.c b/desktop/save_text.c
index 92cf32a9f..bc4d4c57a 100644
--- a/desktop/save_text.c
+++ b/desktop/save_text.c
@@ -28,14 +28,16 @@
#include <dom/dom.h>
#include "utils/config.h"
+#include "utils/log.h"
+#include "utils/utf8.h"
+#include "utils/utils.h"
#include "content/content.h"
#include "content/hlcache.h"
-#include "desktop/save_text.h"
#include "render/box.h"
#include "render/html.h"
-#include "utils/log.h"
-#include "utils/utf8.h"
-#include "utils/utils.h"
+
+#include "desktop/gui_factory.h"
+#include "desktop/save_text.h"
static void extract_text(struct box *box, bool *first,
save_text_whitespace *before, struct save_text_state *save);
@@ -58,7 +60,7 @@ void save_as_text(hlcache_handle *c, char *path)
struct save_text_state save = { NULL, 0, 0 };
save_text_whitespace before = WHITESPACE_NONE;
bool first = true;
- utf8_convert_ret ret;
+ nserror ret;
char *result;
if (!c || content_get_type(c) != CONTENT_HTML) {
@@ -69,10 +71,10 @@ void save_as_text(hlcache_handle *c, char *path)
if (!save.block)
return;
- ret = utf8_to_local_encoding(save.block, save.length, &result);
+ ret = guit->utf8->utf8_to_local(save.block, save.length, &result);
free(save.block);
- if (ret != UTF8_CONVERT_OK) {
+ if (ret != NSERROR_OK) {
LOG(("failed to convert to local encoding, return %d", ret));
return;
}
diff --git a/desktop/scrollbar.c b/desktop/scrollbar.c
index d24ea727a..dadb82801 100644
--- a/desktop/scrollbar.c
+++ b/desktop/scrollbar.c
@@ -25,6 +25,7 @@
#include <stdbool.h>
#include <stdlib.h>
+#include "desktop/system_colour.h"
#include "desktop/mouse.h"
#include "desktop/scrollbar.h"
#include "utils/nsoption.h"
@@ -190,9 +191,9 @@ bool scrollbar_redraw(struct scrollbar *s, int x, int y,
int v[6]; /* array of triangle vertices */
int x0, y0, x1, y1;
- colour bg_fill_colour = gui_system_colour_char("Scrollbar");
- colour fg_fill_colour = gui_system_colour_char("ButtonFace");
- colour arrow_fill_colour = gui_system_colour_char("ButtonText");
+ colour bg_fill_colour = ns_system_colour_char("Scrollbar");
+ colour fg_fill_colour = ns_system_colour_char("ButtonFace");
+ colour arrow_fill_colour = ns_system_colour_char("ButtonText");
plot_style_t bg_fill_style = {
.fill_type = PLOT_OP_TYPE_SOLID,
diff --git a/desktop/search.c b/desktop/search.c
index 3a7c768a5..201d416dd 100644
--- a/desktop/search.c
+++ b/desktop/search.c
@@ -21,67 +21,27 @@
/** \file
* Free text search (core)
*/
-#include "utils/config.h"
-#include <ctype.h>
-#include <string.h>
-#include <dom/dom.h>
#include "content/content.h"
-#include "content/hlcache.h"
+
#include "desktop/browser_private.h"
-#include "desktop/gui.h"
-#include "utils/nsoption.h"
#include "desktop/search.h"
-#include "desktop/selection.h"
-#include "render/box.h"
-#include "render/html.h"
-#include "render/search.h"
-#include "render/textplain.h"
-#include "utils/config.h"
-#include "utils/log.h"
-#include "utils/messages.h"
-#include "utils/url.h"
-#include "utils/utils.h"
-
-
-
-/**
- * Starts or continues an existing search.
- *
- * \param bw the browser_window to search
- * \param callbacks callbacks vtable to update frontend according to results
- * \param gui_data a pointer returned to the callbacks
- * \param flags search flags
- * \param string string to search for
- */
-void browser_window_search(struct browser_window *bw,
- struct gui_search_callbacks *gui_callbacks, void *gui_data,
+/* exported function documented in desktop/search.h */
+void browser_window_search(struct browser_window *bw, void *context,
search_flags_t flags, const char *string)
{
- assert(gui_callbacks != NULL);
-
- if (bw == NULL || bw->current_content == NULL)
- return;
-
- content_search(bw->current_content, gui_callbacks, gui_data,
- flags, string);
+ if ((bw != NULL) &&
+ (bw->current_content != NULL)) {
+ content_search(bw->current_content, context, flags, string);
+ }
}
-
-/**
- * Clear up a search. Frees any memory used by the search
- *
- * \param bw the browser_window to search
- * \param callbacks callbacks vtable to update frontend according to results
- * \param gui_data a pointer returned to the callbacks
- * \param flags search flags
- * \param string string to search for
- */
+/* exported function documented in desktop/search.h */
void browser_window_search_clear(struct browser_window *bw)
{
- if (bw == NULL || bw->current_content == NULL)
- return;
-
- content_search_clear(bw->current_content);
+ if ((bw != NULL) &&
+ (bw->current_content != NULL)) {
+ content_search_clear(bw->current_content);
+ }
}
diff --git a/desktop/search.h b/desktop/search.h
index 8440ce982..254acde99 100644
--- a/desktop/search.h
+++ b/desktop/search.h
@@ -33,54 +33,24 @@ typedef enum {
} search_flags_t;
/**
- * Change the displayed search status.
- * \param found search pattern matched in text
- * \param p gui private data pointer provided with search callbacks
- */
-typedef void (*gui_search_status)(bool found, void *p);
-
-/**
- * display hourglass while searching
- * \param active start/stop indicator
- * \param p gui private data pointer provided with search callbacks
- */
-typedef void (*gui_search_hourglass)(bool active, void *p);
-
-/**
- * add search string to recent searches list
- * front has full liberty how to implement the bare notification;
- * core gives no guarantee of the integrity of the const char *
- * \param string search pattern
- * \param p gui private data pointer provided with search callbacks
- */
-typedef void (*gui_search_add_recent)(const char *string, void *p);
-
-/**
- * activate search forwards button in gui
- * \param active activate/inactivate
- * \param p gui private data pointer provided with search callbacks
+ * Starts or continues an existing search.
+ *
+ * \param bw The browser_window to search.
+ * \param context A context pointer passed to the callbacks.
+ * \param flags Flags controlling the search operation.
+ * \param string The string being searched for.
*/
-typedef void (*gui_search_forward_state)(bool active, void *p);
+void browser_window_search(struct browser_window *bw, void *context, search_flags_t flags, const char *string);
/**
- * activate search back button in gui
- * \param active activate/inactivate
- * \param p gui private data pointer provided with search callbacks
+ * Clear up a search.
+ *
+ * Frees any memory used by the search.
+ *
+ * \param bw The browser window to clean up the search for.
+ * \param context A context pointer passed to the callbacks.
*/
-typedef void (*gui_search_back_state)(bool active, void *p);
-
-struct gui_search_callbacks {
- gui_search_forward_state forward_state;
- gui_search_back_state back_state;
- gui_search_status status;
- gui_search_hourglass hourglass;
- gui_search_add_recent add_recent;
-};
-
-void browser_window_search(struct browser_window *bw,
- struct gui_search_callbacks *gui_callbacks, void *gui_data,
- search_flags_t flags, const char *string);
void browser_window_search_clear(struct browser_window *bw);
#endif
diff --git a/desktop/searchweb.c b/desktop/searchweb.c
index 87e3e21f1..dc12170c1 100644
--- a/desktop/searchweb.c
+++ b/desktop/searchweb.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
+ * Copyright 2014 Vincent Sanders <vince@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -15,320 +15,549 @@
* 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
- * web search (core)
+
+/**
+ * \file desktop/searchweb.c
+ * \brief core web search facilities implementation.
*/
-#include "utils/config.h"
-#include <ctype.h>
-#include <string.h>
-#include "content/content.h"
-#include "content/hlcache.h"
-#include "desktop/browser.h"
-#include "desktop/gui.h"
-#include "utils/nsoption.h"
-#include "desktop/searchweb.h"
-#include "utils/config.h"
#include "utils/log.h"
-#include "utils/messages.h"
#include "utils/url.h"
-#include "utils/utils.h"
+#include "utils/nsoption.h"
+#include "content/hlcache.h"
-static struct search_provider {
+#include "desktop/gui_factory.h"
+#include "desktop/searchweb.h"
+
+struct search_provider {
char *name; /**< readable name such as 'google', 'yahoo', etc */
char *hostname; /**< host address such as www.google.com */
char *searchstring; /** < such as "www.google.com?search=%s" */
char *ico; /** < location of domain's favicon */
-} current_search_provider;
+ hlcache_handle *ico_handle;
+};
-static hlcache_handle *search_ico = NULL;
-char *search_engines_file_location;
-char *search_default_ico_location;
+static struct search_web_ctx_s {
+ struct search_provider *providers; /* web search providers */
+ size_t providers_count; /* number of providers */
-#ifdef WITH_BMP
-static nserror search_web_ico_callback(hlcache_handle *ico,
- const hlcache_event *event, void *pw);
-#endif
+ size_t current; /* current provider */
-/**
- * creates a new browser window according to the search term
- * \param searchterm such as "my search term"
- */
+ hlcache_handle *default_ico_handle;
-bool search_web_new_window(struct browser_window *bw, const char *searchterm)
+} search_web_ctx;
+
+
+static const char *default_providers = "Google|www.google.com|http://www.google.com/search?q=%s|http://www.google.com/favicon.ico|\n";
+
+static const char *default_search_icon_url = "resource:icons/search.png";
+
+
+/**
+ * Read providers file.
+ *
+ * Allocates stoage of sufficient size for the providers file and
+ * reads the entire file in.
+ *
+ * \param fname The filename to read.
+ * \param providers_out A pointer to place the result buffer in.
+ * \param providers_size_out Size of buffer.
+ * \return NSERROR_OK and providers_out updated or appropriate error code.
+ */
+static nserror
+read_providers(const char *fname,
+ char **providers_out,
+ size_t *providers_size_out)
{
- char *encsearchterm;
- char *urltxt;
- nsurl *url;
- nserror error;
+ FILE *providersf;
+ long ftellsize;
+ size_t fsize;
+ char *providersd;
- if (url_escape(searchterm,0, true, NULL, &encsearchterm) != URL_FUNC_OK)
- return false;
+ if (fname == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
- urltxt = search_web_get_url(encsearchterm);
- free(encsearchterm);
+ providersf = fopen(fname, "r");
+ if (providersf == NULL) {
+ return NSERROR_NOT_FOUND;
+ }
- error = nsurl_create(urltxt, &url);
- if (error == NSERROR_OK) {
- error = browser_window_create(BROWSER_WINDOW_VERIFIABLE |
- BROWSER_WINDOW_HISTORY |
- BROWSER_WINDOW_TAB,
- url,
- NULL,
- bw,
- NULL);
- nsurl_unref(url);
+ if (fseek(providersf, 0, SEEK_END) != 0) {
+ fclose(providersf);
+ return NSERROR_INVALID;
}
- if (error != NSERROR_OK) {
- warn_user(messages_get_errorcode(error), 0);
+
+ ftellsize = ftell(providersf);
+ if (ftellsize < 0) {
+ fclose(providersf);
+ return NSERROR_INVALID;
}
+ fsize = ftellsize;
- free(urltxt);
- return true;
-}
+ if (fseek(providersf, 0, SEEK_SET) != 0) {
+ fclose(providersf);
+ return NSERROR_INVALID;
+ }
-/** simplistic way of checking whether an entry from the url bar is an
- * url / a search; could be improved to properly test terms
- */
+ providersd = malloc(fsize + 1);
+ if (providersd == NULL) {
+ fclose(providersf);
+ return NSERROR_NOMEM;
+ }
-bool search_is_url(const char *url)
-{
- /** \todo Implement this properly */
+ if (fread(providersd, 1, fsize, providersf) != fsize) {
+ fclose(providersf);
+ free(providersd);
+ return NSERROR_BAD_SIZE;
+ }
+ providersd[fsize] = 0; /* ensure null terminated */
- /* For now, everything is an URL */
- return true;
-}
+ fclose(providersf);
-/**
- * caches the details of the current web search provider
- * \param reference the enum value of the provider
- * browser init code [as well as changing preferences code] should call
- * search_web_provider_details(option_search_provider)
- */
+ *providers_out = providersd;
+ *providers_size_out = fsize;
-void search_web_provider_details(int reference)
-{
- char buf[300];
- int ref = 0;
- FILE *f;
- if (search_engines_file_location == NULL)
- return;
- f = fopen(search_engines_file_location, "r");
- if (f == NULL)
- return;
- while (fgets(buf, sizeof(buf), f) != NULL) {
- if (buf[0] == '\0')
- continue;
- buf[strlen(buf)-1] = '\0';
- if (ref++ == (int)reference)
- break;
- }
- fclose(f);
- if (current_search_provider.name != NULL)
- free(current_search_provider.name);
- current_search_provider.name = strdup(strtok(buf, "|"));
- if (current_search_provider.hostname != NULL)
- free(current_search_provider.hostname);
- current_search_provider.hostname = strdup(strtok(NULL, "|"));
- if (current_search_provider.searchstring != NULL)
- free(current_search_provider.searchstring);
- current_search_provider.searchstring = strdup(strtok(NULL, "|"));
- if (current_search_provider.ico != NULL)
- free(current_search_provider.ico);
- current_search_provider.ico = strdup(strtok(NULL, "|"));
- return;
+ return NSERROR_OK;
}
/**
- * escapes a search term then creates the appropriate url from it
+ * parse search providers from a memory block.
+ *
+ * \param providersd The provider info data.
+ * \param providers_size The size of the provider data.
+ * \param providers_out The resulting provider array.
+ * \param providers_count The number of providers in the output array.
+ * \return NSERROR_OK on success or error code on faliure.
*/
-
-char *search_web_from_term(const char *searchterm)
+static nserror
+parse_providers(char *providersd,
+ size_t providers_size,
+ struct search_provider **providers_out,
+ size_t *providers_count)
{
- char *encsearchterm, *url;
- if (url_escape(searchterm, 0, true, NULL, &encsearchterm)
- != URL_FUNC_OK)
- return strdup(searchterm);
- url = search_web_get_url(encsearchterm);
- free(encsearchterm);
- return url;
-}
+ size_t pcount = 0; /* number of providers */
+ size_t pidx;
+ char *nl = providersd;
+ struct search_provider *providers;
+
+ /* count newlines */
+ while (nl != NULL) {
+ nl = strchr(nl, '\n');
+ if (nl != NULL) {
+ nl++;
+ pcount+=1;
+ }
+ }
-/** accessor for global search provider name */
+ if (pcount == 0) {
+ return NSERROR_INVALID;
+ }
-char *search_web_provider_name(void)
-{
- if (current_search_provider.name)
- return strdup(current_search_provider.name);
- return strdup("google");
-}
+ providers = malloc(pcount * sizeof(*providers));
+ if (providers == NULL) {
+ return NSERROR_NOMEM;
+ }
-/** accessor for global search provider hostname */
+ nl = providersd;
+ for (pidx = 0; pidx < pcount; pidx++) {
+ providers[pidx].name = nl;
+ nl = strchr(nl, '|');
+ if (nl == NULL) {
+ free(providers);
+ return NSERROR_INVALID;
+ }
+ *nl = 0;
+ nl++;
+
+ providers[pidx].hostname = nl;
+ nl = strchr(nl, '|');
+ if (nl == NULL) {
+ free(providers);
+ return NSERROR_INVALID;
+ }
+ *nl = 0;
+ nl++;
+
+ providers[pidx].searchstring = nl;
+ nl = strchr(nl, '|');
+ if (nl == NULL) {
+ free(providers);
+ return NSERROR_INVALID;
+ }
+ *nl = 0;
+ nl++;
+
+ providers[pidx].ico = nl;
+ nl = strchr(nl, '|');
+ if (nl == NULL) {
+ free(providers);
+ return NSERROR_INVALID;
+ }
+ *nl = 0;
+ nl++;
+
+ /* skip newline */
+ nl = strchr(nl, '\n');
+ if (nl == NULL) {
+ free(providers);
+ return NSERROR_INVALID;
+ }
+ nl++;
-char *search_web_provider_host(void)
-{
- if (current_search_provider.hostname)
- return strdup(current_search_provider.hostname);
- return strdup("www.google.com");
-}
+ providers[pidx].ico_handle = NULL;
+ }
-/** accessor for global search provider ico name */
+ *providers_out = providers;
+ *providers_count = pcount;
-char *search_web_ico_name(void)
-{
- if (current_search_provider.ico)
- return strdup(current_search_provider.ico);
- return strdup("http://www.google.com/favicon.ico");
+ return NSERROR_OK;
}
/**
- * creates a full url from an encoded search term
+ * create a url for a search provider and a term
+ *
+ * \param The provider to use.
+ * \param term The term being searched for.
+ * \param url_out The resulting url.
+ * \return NSERROR_OK on sucess or appropriate error code.
*/
-
-char *search_web_get_url(const char *encsearchterm)
+static nserror
+make_search_nsurl(struct search_provider *provider,
+ const char *term,
+ nsurl **url_out)
{
- char *pref, *ret;
- int len;
- if (current_search_provider.searchstring)
- pref = strdup(current_search_provider.searchstring);
- else
- pref = strdup("http://www.google.com/search?q=%s");
- if (pref == NULL) {
- warn_user(messages_get("NoMemory"), 0);
- return NULL;
- }
- len = strlen(encsearchterm) + strlen(pref);
- ret = malloc(len -1); /* + '\0' - "%s" */
- if (ret == NULL) {
- warn_user(messages_get("NoMemory"), 0);
- free(pref);
- return NULL;
- }
- snprintf(ret, len-1, pref, encsearchterm);
- free(pref);
- return ret;
+ nserror ret;
+ nsurl *url;
+ char *eterm; /* escaped term */
+ char *searchstr; /* the providers search string */
+ char *urlstr; /* the escaped term substituted into the provider */
+ char *urlstro;
+ size_t urlstr_len;
+
+ /* escape the search term and join it to the search url */
+ ret = url_escape(term, 0, true, NULL, &eterm);
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+
+ searchstr = provider->searchstring;
+
+ urlstr_len = strlen(searchstr) + strlen(eterm) + 1;
+ urlstro = urlstr = malloc(urlstr_len);
+ if (urlstr == NULL) {
+ free(eterm);
+ return NSERROR_NOMEM;
+ }
+
+ /* composite search url */
+ for ( ; *searchstr != 0; searchstr++, urlstro++) {
+ *urlstro = *searchstr;
+ if ((*searchstr == '%') && (searchstr[1] == 's')) {
+ searchstr++; /* skip % */
+ memcpy(urlstro, eterm, strlen(eterm));
+ urlstro += strlen(eterm) - 1;
+ }
+ }
+ free(eterm);
+ *urlstro = '\0'; /* ensure string is NULL-terminated */
+
+ ret = nsurl_create(urlstr, &url);
+ free(urlstr);
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+
+ *url_out = url;
+ return NSERROR_OK;
}
/**
- * function to retrieve the search web ico, from cache / from local
- * filesystem / from the web
- * \param localdefault true when there is no appropriate favicon
- * update the search_ico cache else delay until fetcher callback
+ * callback for hlcache icon fetch events.
*/
+static nserror
+search_web_ico_callback(hlcache_handle *ico,
+ const hlcache_event *event,
+ void *pw)
+{
+ struct search_provider *provider = pw;
+
+ switch (event->type) {
+
+ case CONTENT_MSG_DONE:
+ LOG(("icon '%s' retrived",
+ nsurl_access(hlcache_handle_get_url(ico))));
+ guit->search_web->provider_update(provider->name,
+ content_get_bitmap(ico));
+ break;
+
+ case CONTENT_MSG_ERROR:
+ LOG(("icon %s error: %s",
+ nsurl_access(hlcache_handle_get_url(ico)),
+ event->data.error));
+ hlcache_handle_release(ico);
+ /* clear reference to released handle */
+ provider->ico_handle = NULL;
+ break;
+
+ default:
+ break;
+ }
-void search_web_retrieve_ico(bool localdefault)
+ return NSERROR_OK;
+}
+
+/* exported interface documented in desktop/searchweb.h */
+nserror
+search_web_omni(const char *term,
+ enum search_web_omni_flags flags,
+ struct nsurl **url_out)
{
-#if !defined(WITH_BMP)
- /* This function is of limited use when no BMP support
- * is enabled, given the icons it is fetching are BMPs
- * more often than not. This also avoids an issue where
- * all this code goes mad if BMP support is not enabled.
- */
- return;
-#else
- content_type accept = CONTENT_IMAGE;
- char *url;
- nserror error;
- nsurl *icon_nsurl;
+ nserror ret;
+ nsurl *url;
+ char *eterm; /* encoded/altered search term */
+
+ if ((flags & SEARCH_WEB_OMNI_SEARCHONLY) == 0) {
+
+ /* first check to see if the term is a url */
+ ret = nsurl_create(term, &url);
+ if (ret == NSERROR_OK) {
+ *url_out = url;
+ return NSERROR_OK;
+ }
+
+ /* try with adding default scheme */
+ eterm = malloc(strlen(term) + SLEN("http://") + 1);
+ if (eterm == NULL) {
+ return NSERROR_NOMEM;
+ }
+ sprintf(eterm, "http://%s", term);
+ ret = nsurl_create(eterm, &url);
+ free(eterm);
+ if (ret == NSERROR_OK) {
+ *url_out = url;
+ return NSERROR_OK;
+ }
- if (localdefault) {
- if (search_default_ico_location == NULL)
- return;
- url = malloc(SLEN("file://") + strlen(
- search_default_ico_location) + 1);
- if (url == NULL) {
- warn_user(messages_get("NoMemory"), 0);
- return;
+ /* do not pass to search if user has disabled the option */
+ if (nsoption_bool(search_url_bar) == false) {
+ return NSERROR_BAD_URL;
}
- strcpy(url, "file://");
- strcat(url, search_default_ico_location);
- } else {
- url = search_web_ico_name();
}
- if (url == NULL) {
- warn_user(messages_get("NoMemory"), 0);
- return;
+ /* must be initialised */
+ if (search_web_ctx.providers == NULL) {
+ return NSERROR_INIT_FAILED;
}
- error = nsurl_create(url, &icon_nsurl);
- if (error != NSERROR_OK) {
- free(url);
- search_ico = NULL;
- return;
+ /* turn search into a nsurl */
+ ret = make_search_nsurl(&search_web_ctx.providers[search_web_ctx.current], term, &url);
+ if (ret != NSERROR_OK) {
+ return ret;
}
- error = hlcache_handle_retrieve(icon_nsurl, 0, NULL, NULL,
- search_web_ico_callback, NULL, NULL, accept,
- &search_ico);
+ *url_out = url;
+ return NSERROR_OK;
+}
- nsurl_unref(icon_nsurl);
+/* exported interface documented in desktop/searchweb.h */
+nserror search_web_select_provider(int selection)
+{
+ struct search_provider *provider;
+ struct bitmap *ico_bitmap = NULL;
- if (error != NSERROR_OK)
- search_ico = NULL;
+ /* must be initialised */
+ if (search_web_ctx.providers == NULL) {
+ return NSERROR_INIT_FAILED;
+ }
- free(url);
-#endif /* WITH_BMP */
-}
+ /* negative value just selects whatevers current */
+ if (selection >= 0) {
+ /* ensure selection lies within acceptable range */
+ if ((size_t)selection < search_web_ctx.providers_count) {
+ search_web_ctx.current = selection;
+ } else {
+ /* out of range */
+ search_web_ctx.current = 0;
+ }
+ }
-/**
- * returns a reference to the static global search_ico [ / NULL]
- * caller may adjust ico's settings; clearing / free()ing is the core's
- * responsibility
- */
+ provider = &search_web_ctx.providers[search_web_ctx.current];
-hlcache_handle *search_web_ico(void)
-{
- return search_ico;
-}
+ /* set the icon now (if we can) at least to the default */
+ if (provider->ico_handle != NULL) {
+ ico_bitmap = content_get_bitmap(provider->ico_handle);
+ }
+ if ((ico_bitmap == NULL) &&
+ (search_web_ctx.default_ico_handle != NULL)) {
+ ico_bitmap = content_get_bitmap(search_web_ctx.default_ico_handle);
+ }
+ /* update the callback with the provider change. Bitmap may
+ * be NULL at this point.
+ */
+ guit->search_web->provider_update(provider->name, ico_bitmap);
-/**
- * Cleans up any remaining resources during shutdown.
- */
-void search_web_cleanup(void)
-{
- if (search_ico != NULL) {
- hlcache_handle_release(search_ico);
- search_ico = NULL;
+
+ /* if the providers icon has not been retrived get it now */
+ if (provider->ico_handle == NULL) {
+ nsurl *icon_nsurl;
+ nserror ret;
+
+ /* create search icon url */
+ ret = nsurl_create(provider->ico, &icon_nsurl);
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+
+ ret = hlcache_handle_retrieve(icon_nsurl, 0, NULL, NULL,
+ search_web_ico_callback,
+ provider,
+ NULL, CONTENT_IMAGE,
+ &provider->ico_handle);
+ nsurl_unref(icon_nsurl);
+ if (ret != NSERROR_OK) {
+ provider->ico_handle = NULL;
+ return ret;
+ }
}
+
+ return NSERROR_OK;
}
/**
- * callback function to cache ico then notify front when successful
- * else retry default from local file system
+ * callback for hlcache icon fetch events.
*/
-
-#ifdef WITH_BMP
-nserror search_web_ico_callback(hlcache_handle *ico,
- const hlcache_event *event, void *pw)
+static nserror
+default_ico_callback(hlcache_handle *ico,
+ const hlcache_event *event,
+ void *pw)
{
+ struct search_web_ctx_s *ctx = pw;
+
switch (event->type) {
- case CONTENT_MSG_LOADING:
- case CONTENT_MSG_READY:
- break;
case CONTENT_MSG_DONE:
- LOG(("got favicon '%s'", nsurl_access(hlcache_handle_get_url(ico))));
- gui_window_set_search_ico(search_ico);
+ LOG(("default icon '%s' retrived",
+ nsurl_access(hlcache_handle_get_url(ico))));
+
+ /* only set to default icon if providers icon has no handle */
+ if (ctx->providers[search_web_ctx.current].ico_handle == NULL) {
+ guit->search_web->provider_update(
+ ctx->providers[search_web_ctx.current].name,
+ content_get_bitmap(ico));
+ }
break;
case CONTENT_MSG_ERROR:
- LOG(("favicon %s error: %s",
- nsurl_access(hlcache_handle_get_url(ico)),
- event->data.error));
- hlcache_handle_release(search_ico);
- search_ico = NULL;
- search_web_retrieve_ico(true);
+ LOG(("icon %s error: %s",
+ nsurl_access(hlcache_handle_get_url(ico)),
+ event->data.error));
+ hlcache_handle_release(ico);
+ /* clear reference to released handle */
+ ctx->default_ico_handle = NULL;
break;
- case CONTENT_MSG_STATUS:
+ default:
break;
+ }
- default:
- assert(0);
+ return NSERROR_OK;
+}
+
+/* exported interface documented in desktop/searchweb.h */
+ssize_t search_web_iterate_providers(ssize_t from, const char **name)
+{
+ if (from < 0)
+ return -1;
+
+ if ((size_t)from >= search_web_ctx.providers_count)
+ return -1;
+
+ *name = search_web_ctx.providers[from].name;
+
+ return from + 1;
+}
+
+
+/* exported interface documented in desktop/searchweb.h */
+nserror search_web_init(const char *provider_fname)
+{
+ nserror ret;
+ char *providers;
+ size_t providers_size;
+ nsurl *icon_nsurl;
+
+ /* create search icon url */
+ ret = nsurl_create(default_search_icon_url, &icon_nsurl);
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+
+ /* get a list of providers */
+ ret = read_providers(provider_fname, &providers, &providers_size);
+ if (ret != NSERROR_OK) {
+ providers = strdup(default_providers);
+ if (providers == NULL) {
+ return NSERROR_NOMEM;
+ }
+ providers_size = strlen(providers);
}
+ /* parse list of providers */
+ ret = parse_providers(providers,
+ providers_size,
+ &search_web_ctx.providers,
+ &search_web_ctx.providers_count);
+ if (ret != NSERROR_OK) {
+ free(providers);
+ return ret;
+ }
+
+ /* get default search icon */
+ ret = hlcache_handle_retrieve(icon_nsurl, 0, NULL, NULL,
+ default_ico_callback,
+ &search_web_ctx,
+ NULL, CONTENT_IMAGE,
+ &search_web_ctx.default_ico_handle);
+ nsurl_unref(icon_nsurl);
+ if (ret != NSERROR_OK) {
+ search_web_ctx.default_ico_handle = NULL;
+ free(search_web_ctx.providers);
+ search_web_ctx.providers = NULL;
+ free(providers);
+ return ret;
+ }
+
+
+ return NSERROR_OK;
+}
+
+/* exported interface documented in desktop/searchweb.h */
+nserror search_web_finalise(void)
+{
+ size_t pidx;
+
+ /* must be initialised */
+ if (search_web_ctx.providers == NULL) {
+ return NSERROR_INIT_FAILED;
+ }
+
+ if (search_web_ctx.default_ico_handle != NULL) {
+ hlcache_handle_release(search_web_ctx.default_ico_handle);
+ }
+ for (pidx = 0; pidx < search_web_ctx.providers_count; pidx++) {
+ if (search_web_ctx.providers[pidx].ico_handle != NULL) {
+ hlcache_handle_release(search_web_ctx.providers[pidx].ico_handle);
+ }
+ }
+
+ /* All the search provider data is held in a single block for
+ * efficiency.
+ */
+ free(search_web_ctx.providers[0].name);
+
+ free(search_web_ctx.providers);
+ search_web_ctx.providers = NULL;
+
return NSERROR_OK;
}
-#endif /* WITH_BMP */
diff --git a/desktop/searchweb.h b/desktop/searchweb.h
index 3920f3c6e..b3b3902cf 100644
--- a/desktop/searchweb.h
+++ b/desktop/searchweb.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
+ * Copyright 2014 Vincent Sanders <vince@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -16,65 +16,105 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+/**
+ * \file desktop/searchweb.h
+ * \brief core web search facilities interface.
+ */
+
#ifndef _NETSURF_DESKTOP_SEARCH_WEB_H_
#define _NETSURF_DESKTOP_SEARCH_WEB_H_
-#include <ctype.h>
-#include <stdbool.h>
-#include <string.h>
-
-struct browser_window;
-struct hlcache_handle;
-
-extern char *search_engines_file_location;
-extern char *search_default_ico_location;
+struct bitmap;
/**
- * open new tab/window for web search term
+ * Graphical user interface browser web search function table.
+ *
*/
-bool search_web_new_window(struct browser_window *bw, const char *searchterm);
+struct gui_search_web_table {
+ /**
+ * called when the search provider details are updated.
+ *
+ * \param provider_name The name of the provider.
+ * \param ico_bitmap The bitmap of the search icon may be NULL
+ * if no icon is yet available.
+ */
+ nserror (*provider_update)(const char *provider_name, struct bitmap *ico_bitmap);
+};
/**
- * retrieve full search url from unencoded search term
+ * Flags which alter the behaviour of the omin search.
*/
-char *search_web_from_term(const char *searchterm);
+enum search_web_omni_flags {
+ SEARCH_WEB_OMNI_NONE = 0, /**< no changes to default operation */
+ SEARCH_WEB_OMNI_SEARCHONLY = 1, /**< The search does not attempt to
+ * interpret the url as a url before
+ * using it as a search term.
+ */
+};
/**
- * retrieve full search url from encoded web search term
+ * Generate a nsurl from a search term.
+ *
+ * This interface obtains a url appropriate for the given search
+ * term. The flags allow control over the operation. By default the
+ * operations are:
+ * - interpret the \a term as a url
+ * - if missing a scheme as a http: url
+ * - combined with the search providers url into a url for that provider.
+ *
+ * \param term The search term.
+ * \param flags Flags to control operation.
+ * \param url_out The ourput url on success.
+ * \return NSERROR_OK on success or appropriate error code.
*/
-char *search_web_get_url(const char *encsearchterm);
+nserror search_web_omni(const char *term, enum search_web_omni_flags flags, struct nsurl **url_out);
/**
- * cache details of web search provider from file
+ * Change the currently selected web search provider.
+ *
+ * \param selection Index of the search provider to select or -1 to
+ * reselect the current provider
+ * \return NSERROR_OK on success or appropriate error code.
*/
-void search_web_provider_details(int reference);
+nserror search_web_select_provider(int selection);
-/**
- * retrieve name of web search provider
- */
-char *search_web_provider_name(void);
/**
- * retrieve hostname of web search provider
+ * Iterate the search providers, returning their names.
+ *
+ * \param from Index to start iteration from. Use 0 to begin iteration.
+ * Use the value returned from search_web_iterate_providers to
+ * continue an iteration.
+ * \param name Pointer to fill in with the search provider name requested.
+ * \return -1 if there are no more, otherwise the iterator for the next item.
+ *
+ * \verb
+ * ssize_t iter;
+ * const char *name;
+ * ...
+ * for (iter = search_web_iterate_providers(0, &name);
+ * iter != -1;
+ * iter = search_web_iterate_providers(iter, &name)) {
+ * do_something_with(name);
+ * }
+ * \endverb
*/
-char *search_web_provider_host(void);
+ssize_t search_web_iterate_providers(ssize_t from, const char **name);
+
/**
- * retrieve name of .ico for search bar
+ * Initialise the web search operations.
+ *
+ * \param provider_fname Path to web search providers file.
+ * \return NSERROR_OK on successful initialisation or appropriate error code.
*/
-char *search_web_ico_name(void);
+nserror search_web_init(const char *provider_fname);
/**
- * check whether an URL is in fact a search term
- * \param url the url being checked
- * \return true for url, false for search
+ * Finalise the web search operations freeing all resources.
+ *
+ * \return NSERROR_OK on success or appropriate error code.
*/
-bool search_is_url(const char *url);
-
-void search_web_retrieve_ico(bool localdefault);
-
-struct hlcache_handle *search_web_ico(void);
-
-void search_web_cleanup(void);
+nserror search_web_finalise(void);
#endif
diff --git a/desktop/selection.c b/desktop/selection.c
index 13a1293e3..34292fdce 100644
--- a/desktop/selection.c
+++ b/desktop/selection.c
@@ -29,7 +29,7 @@
#include <dom/dom.h>
#include "desktop/browser_private.h"
-#include "desktop/gui.h"
+#include "desktop/gui_factory.h"
#include "desktop/mouse.h"
#include "desktop/plotters.h"
#include "desktop/save_text.h"
@@ -274,7 +274,7 @@ bool selection_click(struct selection *s, browser_mouse_state mouse,
(modkeys && (mouse & BROWSER_MOUSE_DRAG_2)))) {
/* drag-saving selection */
char *sel = selection_get_copy(s);
- gui_drag_save_selection(top->window, sel);
+ guit->window->drag_save_selection(top->window, sel);
free(sel);
}
else if (!modkeys) {
@@ -293,7 +293,7 @@ bool selection_click(struct selection *s, browser_mouse_state mouse,
s->drag_state = DRAG_END;
- gui_start_selection(top->window);
+ guit->window->start_selection(top->window);
}
else if (mouse & BROWSER_MOUSE_DRAG_2) {
@@ -312,7 +312,7 @@ bool selection_click(struct selection *s, browser_mouse_state mouse,
s->drag_state = DRAG_START;
}
- gui_start_selection(top->window);
+ guit->window->start_selection(top->window);
}
else if (mouse & BROWSER_MOUSE_CLICK_2) {
@@ -844,7 +844,7 @@ bool selection_copy_to_clipboard(struct selection *s)
return false;
}
- gui_set_clipboard(sel_string.buffer, sel_string.length,
+ guit->clipboard->set(sel_string.buffer, sel_string.length,
sel_string.styles, sel_string.n_styles);
free(sel_string.buffer);
diff --git a/desktop/sslcert_viewer.c b/desktop/sslcert_viewer.c
index e0e87fbbe..5280e094a 100644
--- a/desktop/sslcert_viewer.c
+++ b/desktop/sslcert_viewer.c
@@ -24,9 +24,9 @@
#include <assert.h>
#include <stdlib.h>
-
#include "content/fetch.h"
#include "content/urldb.h"
+#include "content/hlcache.h"
#include "desktop/sslcert_viewer.h"
#include "desktop/treeview.h"
#include "utils/messages.h"
@@ -47,7 +47,7 @@ enum sslcert_viewer_field {
/** ssl certificate verification context. */
struct sslcert_session_data {
- const struct ssl_cert_info *certs; /**< Certificates */
+ struct ssl_cert_info *certs; /**< Certificates */
unsigned long num; /**< Number of certificates in chain */
nsurl *url; /**< The url of the certificate */
llcache_query_response cb; /**< Cert accept/reject callback */
@@ -394,8 +394,15 @@ static void sslcert_cleanup_session(struct sslcert_session_data *ssl_d)
{
assert(ssl_d != NULL);
- if (ssl_d->url)
+ if (ssl_d->url) {
nsurl_unref(ssl_d->url);
+ ssl_d->url = NULL;
+ }
+
+ if (ssl_d->certs) {
+ free(ssl_d->certs);
+ ssl_d->certs = NULL;
+ }
free(ssl_d);
}
@@ -439,12 +446,19 @@ nserror sslcert_viewer_create_session_data(unsigned long num, nsurl *url,
data = malloc(sizeof(struct sslcert_session_data));
if (data == NULL) {
- warn_user("NoMemory", 0);
*ssl_d = NULL;
return NSERROR_NOMEM;
}
- data->certs = certs;
+ /* copy certificate data */
+ data->certs = malloc(num * sizeof(struct ssl_cert_info));
+ if (data->certs == NULL) {
+ free(data);
+ *ssl_d = NULL;
+ return NSERROR_NOMEM;
+ }
+ memcpy(data->certs, certs, num * sizeof(struct ssl_cert_info));
+
data->url = nsurl_ref(url);
data->num = num;
data->cb = cb;
@@ -486,6 +500,9 @@ void sslcert_viewer_redraw(struct sslcert_session_data *ssl_d,
int x, int y, struct rect *clip,
const struct redraw_context *ctx)
{
+ assert(ssl_d != NULL &&
+ "sslcert_viewer_redraw() given bad session data");
+
treeview_redraw(ssl_d->tree, x, y, clip, ctx);
}
diff --git a/desktop/sslcert_viewer.h b/desktop/sslcert_viewer.h
index e02f095f5..d6b0c1b8b 100644
--- a/desktop/sslcert_viewer.h
+++ b/desktop/sslcert_viewer.h
@@ -24,7 +24,6 @@
#include <stdbool.h>
#include <stdint.h>
-#include "desktop/browser.h"
#include "desktop/core_window.h"
#include "desktop/textinput.h"
#include "utils/errors.h"
diff --git a/desktop/system_colour.c b/desktop/system_colour.c
index 4ef170981..178c03536 100644
--- a/desktop/system_colour.c
+++ b/desktop/system_colour.c
@@ -21,45 +21,47 @@
*
*/
+#include <string.h>
+
+#include "utils/config.h"
#include "utils/utils.h"
#include "utils/log.h"
#include "css/utils.h"
-#include "desktop/gui.h"
+#include "desktop/system_colour.h"
#include "utils/nsoption.h"
-
#define colour_list_len ((NSOPTION_SYS_COLOUR_END - NSOPTION_SYS_COLOUR_START) + 1)
static lwc_string *colour_list[colour_list_len];
-static lwc_string **gui_system_colour_pw = NULL;
+static lwc_string **ns_system_colour_pw = NULL;
-bool gui_system_colour_init(void)
+nserror ns_system_colour_init(void)
{
unsigned int ccount;
- if (gui_system_colour_pw != NULL)
- return false;
+ if (ns_system_colour_pw != NULL)
+ return NSERROR_INIT_FAILED;
/* Intern colour strings */
for (ccount = 0; ccount < colour_list_len; ccount++) {
struct nsoption_s *opt;
opt = &nsoptions[ccount + NSOPTION_SYS_COLOUR_START];
- if (lwc_intern_string(opt->key + SLEN("sys_colour_"),
- opt->key_len - SLEN("sys_colour_"),
+ if (lwc_intern_string(opt->key + SLEN("sys_colour_"),
+ opt->key_len - SLEN("sys_colour_"),
&(colour_list[ccount])) != lwc_error_ok) {
- return false;
+ return NSERROR_NOMEM;
}
}
- gui_system_colour_pw = colour_list;
-
- return true;
+ ns_system_colour_pw = colour_list;
+
+ return NSERROR_OK;
}
-void gui_system_colour_finalize(void)
+void ns_system_colour_finalize(void)
{
unsigned int ccount;
@@ -68,7 +70,7 @@ void gui_system_colour_finalize(void)
}
}
-colour gui_system_colour_char(const char *name)
+colour ns_system_colour_char(const char *name)
{
colour ret = 0;
unsigned int ccount;
@@ -83,19 +85,19 @@ colour gui_system_colour_char(const char *name)
return ret;
}
-css_error gui_system_colour(void *pw, lwc_string *name, css_color *colour)
+css_error ns_system_colour(void *pw, lwc_string *name, css_color *colour)
{
unsigned int ccount;
bool match;
for (ccount = 0; ccount < colour_list_len; ccount++) {
- if (lwc_string_caseless_isequal(name,
+ if (lwc_string_caseless_isequal(name,
colour_list[ccount],
&match) == lwc_error_ok && match) {
*colour = ns_color_to_nscss(nsoptions[ccount + NSOPTION_SYS_COLOUR_START].value.c);
return CSS_OK;
}
- }
+ }
return CSS_INVALID;
}
diff --git a/desktop/401login.h b/desktop/system_colour.h
index 1c8140bae..b5d4baad4 100644
--- a/desktop/401login.h
+++ b/desktop/system_colour.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2003 John M Bell <jmb202@ecs.soton.ac.uk>
+ * Copyright 2014 vincent Sanders <vince@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -16,16 +16,25 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef NETSURF_DESKTOP_401LOGIN_H
-#define NETSURF_DESKTOP_401LOGIN_H
+/** \file
+ * Interface to system colour values.
+ */
+
+#ifndef _NETSURF_DESKTOP_SYSTEM_COLOUR_H_
+#define _NETSURF_DESKTOP_SYSTEM_COLOUR_H_
-#include <stdbool.h>
+#include <libcss/libcss.h>
-#include "utils/config.h"
-#include "utils/nsurl.h"
#include "utils/errors.h"
+#include "desktop/plot_style.h"
+
+/** css callback to obtain named system colours. */
+css_error ns_system_colour(void *pw, lwc_string *name, css_color *color);
+
+/** Obtain a named system colour from a frontend. */
+colour ns_system_colour_char(const char *name);
-void gui_401login_open(nsurl *url, const char *realm,
- nserror (*cb)(bool proceed, void *pw), void *cbpw);
+nserror ns_system_colour_init(void);
+void ns_system_colour_finalize(void);
#endif
diff --git a/desktop/textarea.c b/desktop/textarea.c
index bfa07ad4f..2ba09824d 100644
--- a/desktop/textarea.c
+++ b/desktop/textarea.c
@@ -24,11 +24,13 @@
#include <stdint.h>
#include <string.h>
#include "css/utils.h"
+
#include "desktop/mouse.h"
#include "desktop/textarea.h"
#include "desktop/textinput.h"
#include "desktop/plotters.h"
#include "desktop/scrollbar.h"
+#include "desktop/gui_factory.h"
#include "render/font.h"
#include "utils/log.h"
#include "utils/utf8.h"
@@ -160,6 +162,7 @@ static void textarea_normalise_text(struct textarea *ta,
unsigned int b_start, unsigned int b_len)
{
bool multi = (ta->flags & TEXTAREA_MULTILINE) ? true : false;
+ struct textarea_msg msg;
unsigned int index;
/* Remove CR characters. If it's a CRLF pair delete the CR, or replace
@@ -187,6 +190,25 @@ static void textarea_normalise_text(struct textarea *ta,
ta->text.data[b_start + index] = ' ';
}
+ /* Build text modified message */
+ msg.ta = ta;
+ msg.type = TEXTAREA_MSG_TEXT_MODIFIED;
+ msg.data.modified.text = ta->text.data;
+ msg.data.modified.len = ta->text.len;
+
+ /* Pass message to client */
+ ta->callback(ta->data, &msg);
+}
+
+
+/**
+ * Reset the selection (no redraw)
+ *
+ * \param ta Text area
+ */
+static inline void textarea_reset_selection(struct textarea *ta)
+{
+ ta->sel_start = ta->sel_end = -1;
}
@@ -1408,7 +1430,7 @@ static bool textarea_replace_text_internal(struct textarea *ta, size_t b_start,
/* Place CUTs on clipboard */
if (add_to_clipboard) {
- gui_set_clipboard(ta->show->data + b_start, b_end - b_start,
+ guit->clipboard->set(ta->show->data + b_start, b_end - b_start,
NULL, 0);
}
@@ -1758,13 +1780,14 @@ static void textarea_setup_text_offsets(struct textarea *ta)
if (ta->flags & TEXTAREA_MULTILINE) {
/* Multiline textarea */
text_y_offset += ta->pad_top;
- text_y_offset_baseline += (ta->line_height * 3 + 2) / 4 +
- ta->pad_top;
+ text_y_offset_baseline +=
+ (ta->line_height * 3 + 2) / 4 + ta->pad_top;
} else {
/* Single line text area; text is vertically centered */
int vis_height = ta->vis_height - 2 * ta->border_width;
text_y_offset += (vis_height - ta->line_height + 1) / 2;
- text_y_offset_baseline += (vis_height * 3 + 2) / 4;
+ text_y_offset_baseline +=
+ (2 * vis_height + ta->line_height + 2) / 4;
}
ta->text_y_offset = text_y_offset;
@@ -1872,9 +1895,9 @@ struct textarea *textarea_create(const textarea_flags flags,
ret->show = &ret->text;
}
- ret->line_height = FIXTOINT(FDIV((FMUL(FLTTOFIX(1.3),
- FMUL(nscss_screen_dpi, INTTOFIX((setup->text.size))))),
- FONT_SIZE_SCALE * F_72));
+ ret->line_height = FIXTOINT(FMUL(FLTTOFIX(1.3), FDIV(FMUL(
+ nscss_screen_dpi, FDIV(INTTOFIX(setup->text.size),
+ INTTOFIX(FONT_SIZE_SCALE))), F_72)));
ret->caret_pos.line = ret->caret_pos.byte_off = -1;
ret->caret_x = 0;
@@ -2067,10 +2090,17 @@ void textarea_redraw(struct textarea *ta, int x, int y, colour bg, float scale,
r = *clip;
- if (r.x1 < x || r.x0 > x + ta->vis_width || r.y1 < y ||
- r.y0 > y + ta->vis_height)
- /* Textarea outside the clipping rectangle */
+ /* Nothing to render if textarea is outside clip rectangle */
+ if (r.x1 < x || r.y1 < y)
return;
+ if (scale == 1.0) {
+ if (r.x0 > x + ta->vis_width || r.y0 > y + ta->vis_height)
+ return;
+ } else {
+ if (r.x0 > x + ta->vis_width * scale ||
+ r.y0 > y + ta->vis_height * scale)
+ return;
+ }
if (ta->lines == NULL)
/* Nothing to redraw */
@@ -2146,7 +2176,7 @@ void textarea_redraw(struct textarea *ta, int x, int y, colour bg, float scale,
scale)
r.y1 = y + (ta->vis_height - ta->border_width -
(ta->bar_x != NULL ? SCROLLBAR_WIDTH :
- 0) * scale);
+ 0)) * scale;
}
if (line0 > 0)
@@ -2253,6 +2283,8 @@ void textarea_redraw(struct textarea *ta, int x, int y, colour bg, float scale,
&right);
} else {
right = ta->lines[line].width;
+ if (scale != 1.0)
+ right *= scale;
}
right += x + ta->border_width + ta->pad_left -
ta->scroll_x;
@@ -2380,8 +2412,9 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
length, false, &byte_delta, &r))
return false;
+ redraw = true;
caret = ta->sel_end;
- textarea_clear_selection(ta);
+ textarea_reset_selection(ta);
} else {
if (!textarea_replace_text(ta, caret, caret,
utf8, length, false, &byte_delta, &r))
@@ -2411,8 +2444,9 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
"", 0, false, &byte_delta, &r))
return false;
+ redraw = true;
caret = ta->sel_end;
- textarea_clear_selection(ta);
+ textarea_reset_selection(ta);
} else if (caret > 0) {
b_off = utf8_prev(ta->show->data, caret);
if (!textarea_replace_text(ta, b_off, caret,
@@ -2431,8 +2465,9 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
"", 0, false, &byte_delta, &r))
return false;
+ redraw = true;
caret = ta->sel_end;
- textarea_clear_selection(ta);
+ textarea_reset_selection(ta);
} else if (caret < ta->show->len - 1) {
b_off = utf8_next(ta->show->data,
ta->show->len - 1, caret);
@@ -2456,8 +2491,9 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
&byte_delta, &r))
return false;
+ redraw = true;
caret = ta->sel_end;
- textarea_clear_selection(ta);
+ textarea_reset_selection(ta);
} else {
if (!textarea_replace_text(ta, caret, caret,
"\n", 1, false,
@@ -2475,7 +2511,7 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
if (readonly)
break;
- gui_get_clipboard(&clipboard, &clipboard_length);
+ guit->clipboard->get(&clipboard, &clipboard_length);
if (clipboard == NULL)
return false;
@@ -2486,8 +2522,9 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
false, &byte_delta, &r))
return false;
+ redraw = true;
caret = ta->sel_end;
- textarea_clear_selection(ta);
+ textarea_reset_selection(ta);
} else {
if (!textarea_replace_text(ta,
caret, caret,
@@ -2510,9 +2547,10 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
"", 0, true, &byte_delta, &r))
return false;
+ redraw = true;
caret = ta->sel_end;
caret += byte_delta;
- textarea_clear_selection(ta);
+ textarea_reset_selection(ta);
}
break;
case KEY_ESCAPE:
@@ -2684,8 +2722,9 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
ta->sel_start, ta->sel_end,
"", 0, false, &byte_delta, &r))
return false;
+ redraw = true;
caret = ta->sel_end;
- textarea_clear_selection(ta);
+ textarea_reset_selection(ta);
} else {
if (ta->lines[line].b_length != 0) {
/* Delete line */
@@ -2716,8 +2755,9 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
ta->sel_start, ta->sel_end,
"", 0, false, &byte_delta, &r))
return false;
+ redraw = true;
caret = ta->sel_end;
- textarea_clear_selection(ta);
+ textarea_reset_selection(ta);
} else {
b_len = ta->lines[line].b_length;
b_off = ta->lines[line].b_start + b_len;
@@ -2737,8 +2777,9 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
ta->sel_start, ta->sel_end,
"", 0, false, &byte_delta, &r))
return false;
+ redraw = true;
caret = ta->sel_end;
- textarea_clear_selection(ta);
+ textarea_reset_selection(ta);
} else {
if (!textarea_replace_text(ta,
caret - ta->caret_pos.byte_off,
@@ -3023,7 +3064,7 @@ bool textarea_clear_selection(struct textarea *ta)
break;
/* Clear selection and redraw */
- ta->sel_start = ta->sel_end = -1;
+ textarea_reset_selection(ta);
msg.ta = ta;
msg.type = TEXTAREA_MSG_REDRAW_REQUEST;
diff --git a/desktop/textarea.h b/desktop/textarea.h
index 016f15a10..1c24dd1cc 100644
--- a/desktop/textarea.h
+++ b/desktop/textarea.h
@@ -51,7 +51,8 @@ typedef enum {
TEXTAREA_MSG_DRAG_REPORT, /**< Textarea drag start/end report */
TEXTAREA_MSG_SELECTION_REPORT, /**< Textarea text selection presence */
TEXTAREA_MSG_REDRAW_REQUEST, /**< Textarea redraw request */
- TEXTAREA_MSG_CARET_UPDATE /**< Textarea caret */
+ TEXTAREA_MSG_CARET_UPDATE, /**< Textarea caret */
+ TEXTAREA_MSG_TEXT_MODIFIED /**< Textarea text modified */
} textarea_msg_type;
struct textarea_msg {
@@ -77,6 +78,10 @@ struct textarea_msg {
struct rect *clip; /**< Carret clip rect */
} pos; /**< With _CARET_SET_POS */
} caret; /**< With _CARET_UPDATE */
+ struct {
+ const char *text; /**< UTF8 text */
+ unsigned int len; /**< Byte length of text */
+ } modified; /**< With _TEXT_MODIFIED */
} data; /**< Depends on msg type */
};
diff --git a/desktop/textinput.c b/desktop/textinput.c
index e804829fa..fd6ae9ff1 100644
--- a/desktop/textinput.c
+++ b/desktop/textinput.c
@@ -30,7 +30,7 @@
#include <dom/dom.h>
#include "desktop/browser_private.h"
-#include "desktop/gui.h"
+#include "desktop/gui_factory.h"
#include "desktop/mouse.h"
#include "desktop/scrollbar.h"
#include "desktop/selection.h"
@@ -85,7 +85,7 @@ void browser_window_place_caret(struct browser_window *bw, int x, int y,
/* TODO: intersect with bw viewport */
- gui_window_place_caret(root_bw->window, x, y, height * bw->scale, crp);
+ guit->window->place_caret(root_bw->window, x, y, height * bw->scale, crp);
/* Set focus browser window */
root_bw->focus = bw;
@@ -110,8 +110,9 @@ void browser_window_remove_caret(struct browser_window *bw, bool only_hide)
else
root_bw->can_edit = false;
- if (root_bw->window)
- gui_window_remove_caret(root_bw->window);
+ if (root_bw->window) {
+ guit->window->remove_caret(root_bw->window);
+ }
}
diff --git a/desktop/tree.c b/desktop/tree.c
index 6097c22a6..c29afa761 100644
--- a/desktop/tree.c
+++ b/desktop/tree.c
@@ -36,7 +36,6 @@
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/utils.h"
-#include "utils/url.h"
struct tree {
unsigned int flags; /* Tree flags */
@@ -133,6 +132,10 @@ static bool treeview_test_init(struct tree *tree)
switch (tree->flags) {
case TREE_COOKIES:
+ assert(ssl_current_session == NULL &&
+ "Call sslcert_viewer_init directly, "
+ "this compat. layer can't cope with simultanious "
+ "sslcert viewers");
err = cookie_manager_init(&cw_t, (struct core_window *)tree);
if (err != NSERROR_OK)
warn_user("Couldn't init new cookie manager.", 0);
@@ -180,7 +183,10 @@ static bool treeview_test_fini(struct tree *tree)
warn_user("Couldn't finalise hotlist.", 0);
break;
case TREE_SSLCERT:
+ assert(ssl_current_session != NULL &&
+ "Can't use sslcert window after sslcert_viewer_fini()");
err = sslcert_viewer_fini(ssl_current_session);
+ ssl_current_session = NULL;
if (err != NSERROR_OK)
warn_user("Couldn't finalise sslcert viewer.", 0);
break;
@@ -206,7 +212,9 @@ static bool treeview_test_redraw(struct tree *tree, int x, int y,
switch (tree->flags) {
case TREE_SSLCERT:
- sslcert_viewer_redraw(ssl_current_session, x, y, &clip, ctx);
+ if (ssl_current_session != NULL) {
+ sslcert_viewer_redraw(ssl_current_session, x, y, &clip, ctx);
+ }
return true;
case TREE_COOKIES:
cookie_manager_redraw(x, y, &clip, ctx);
@@ -227,6 +235,8 @@ static bool treeview_test_mouse_action(struct tree *tree,
{
switch (tree->flags) {
case TREE_SSLCERT:
+ assert(ssl_current_session != NULL &&
+ "Can't use sslcert window after sslcert_viewer_fini()");
sslcert_viewer_mouse_action(ssl_current_session, mouse, x, y);
return true;
case TREE_COOKIES:
@@ -247,6 +257,8 @@ static bool treeview_test_keypress(struct tree *tree, uint32_t key)
{
switch (tree->flags) {
case TREE_SSLCERT:
+ assert(ssl_current_session != NULL &&
+ "Can't use sslcert window after sslcert_viewer_fini()");
sslcert_viewer_keypress(ssl_current_session, key);
return true;
case TREE_COOKIES:
diff --git a/desktop/tree.h b/desktop/tree.h
index db164c013..b4e0f66b7 100644
--- a/desktop/tree.h
+++ b/desktop/tree.h
@@ -27,10 +27,18 @@
#include <stdbool.h>
#include <stdint.h>
-#include "desktop/browser.h"
+#include "desktop/mouse.h"
struct sslcert_session_data;
+struct tree;
+struct redraw_context;
+/**
+ * Current ssl session data for treeview
+ *
+ * @todo FIXME global certificate treeview state must go away, this is
+ * just wrong.
+ */
extern struct sslcert_session_data *ssl_current_session;
extern const char *tree_hotlist_path;
@@ -42,9 +50,6 @@ enum tree_flags {
TREE_HOTLIST
};
-
-struct tree;
-
typedef enum {
TREE_NO_DRAG = 0,
TREE_SELECT_DRAG,
diff --git a/desktop/treeview.c b/desktop/treeview.c
index a137c46c5..484d279cf 100644
--- a/desktop/treeview.c
+++ b/desktop/treeview.c
@@ -20,15 +20,17 @@
* Treeview handling (implementation).
*/
+#include "utils/log.h"
#include "css/utils.h"
-#include "desktop/gui.h"
+#include "image/bitmap.h"
+#include "render/font.h"
+#include "content/hlcache.h"
+
+#include "desktop/system_colour.h"
#include "desktop/knockout.h"
#include "desktop/plotters.h"
#include "desktop/textarea.h"
#include "desktop/treeview.h"
-#include "image/bitmap.h"
-#include "render/font.h"
-#include "utils/log.h"
/* TODO: get rid of REDRAW_MAX -- need to be able to know window size */
#define REDRAW_MAX 8000
@@ -64,10 +66,10 @@ struct treeview_field {
};
enum treeview_node_flags {
- TREE_NODE_NONE = 0, /**< No node flags set */
- TREE_NODE_EXPANDED = (1 << 0), /**< Whether node is expanded */
- TREE_NODE_SELECTED = (1 << 1), /**< Whether node is selected */
- TREE_NODE_SPECIAL = (1 << 2) /**< Render as special node */
+ TV_NFLAGS_NONE = 0, /**< No node flags set */
+ TV_NFLAGS_EXPANDED = (1 << 0), /**< Whether node is expanded */
+ TV_NFLAGS_SELECTED = (1 << 1), /**< Whether node is selected */
+ TV_NFLAGS_SPECIAL = (1 << 2) /**< Render as special node */
};
enum treeview_target_pos {
@@ -219,7 +221,7 @@ static inline treeview_node * treeview_node_next(treeview_node *node, bool full)
{
assert(node != NULL);
- if ((full || (node->flags & TREE_NODE_EXPANDED)) &&
+ if ((full || (node->flags & TV_NFLAGS_EXPANDED)) &&
node->children != NULL) {
/* Next node is child */
node = node->children;
@@ -330,7 +332,7 @@ static nserror treeview_walk_internal(treeview_node *root, bool full,
parent = node->parent;
next_sibling = node->next_sib;
child = (!skip_children &&
- (full || (node->flags & TREE_NODE_EXPANDED))) ?
+ (full || (node->flags & TV_NFLAGS_EXPANDED))) ?
node->children : NULL;
while (node != NULL) {
@@ -387,7 +389,7 @@ static nserror treeview_walk_internal(treeview_node *root, bool full,
parent = node->parent;
next_sibling = node->next_sib;
- child = (full || (node->flags & TREE_NODE_EXPANDED)) ?
+ child = (full || (node->flags & TV_NFLAGS_EXPANDED)) ?
node->children : NULL;
if (callback_fwd != NULL) {
@@ -423,7 +425,7 @@ static nserror treeview_create_node_root(treeview_node **root)
return NSERROR_NOMEM;
}
- n->flags = TREE_NODE_EXPANDED;
+ n->flags = TV_NFLAGS_EXPANDED;
n->type = TREE_NODE_ROOT;
n->height = 0;
@@ -506,7 +508,7 @@ static inline void treeview_insert_node(treeview_node *a,
treeview_set_inset_from_parent, NULL);
}
- if (a->parent->flags & TREE_NODE_EXPANDED) {
+ if (a->parent->flags & TV_NFLAGS_EXPANDED) {
int height = a->height;
/* Parent is expanded, so inserted node will be visible and
* affect layout */
@@ -550,7 +552,7 @@ nserror treeview_create_node_folder(treeview *tree,
}
n->flags = (flags & TREE_OPTION_SPECIAL_DIR) ?
- TREE_NODE_SPECIAL : TREE_NODE_NONE;
+ TV_NFLAGS_SPECIAL : TV_NFLAGS_NONE;
n->type = TREE_NODE_FOLDER;
n->height = tree_g.line_height;
@@ -568,7 +570,7 @@ nserror treeview_create_node_folder(treeview *tree,
treeview_insert_node(n, relation, rel);
- if (n->parent->flags & TREE_NODE_EXPANDED) {
+ if (n->parent->flags & TV_NFLAGS_EXPANDED) {
/* Inform front end of change in dimensions */
if (!(flags & TREE_OPTION_SUPPRESS_RESIZE))
tree->cw_t->update_size(tree->cw_h, -1,
@@ -613,7 +615,7 @@ nserror treeview_update_node_folder(treeview *tree,
folder->text.len = field->value_len;
folder->text.width = 0;
- if (folder->parent->flags & TREE_NODE_EXPANDED) {
+ if (folder->parent->flags & TV_NFLAGS_EXPANDED) {
/* Text will be seen, get its width */
nsfont.font_width(&plot_style_odd.text,
folder->text.data,
@@ -625,7 +627,7 @@ nserror treeview_update_node_folder(treeview *tree,
}
/* Redraw */
- if (folder->parent->flags & TREE_NODE_EXPANDED) {
+ if (folder->parent->flags & TV_NFLAGS_EXPANDED) {
struct rect r;
r.x0 = 0;
r.y0 = treeview_node_y(tree, folder);
@@ -663,7 +665,7 @@ nserror treeview_update_node_entry(treeview *tree,
entry->text.len = fields[0].value_len;
entry->text.width = 0;
- if (entry->parent->flags & TREE_NODE_EXPANDED) {
+ if (entry->parent->flags & TV_NFLAGS_EXPANDED) {
/* Text will be seen, get its width */
nsfont.font_width(&plot_style_odd.text,
entry->text.data,
@@ -683,7 +685,7 @@ nserror treeview_update_node_entry(treeview *tree,
e->fields[i - 1].value.data = fields[i].value;
e->fields[i - 1].value.len = fields[i].value_len;
- if (entry->flags & TREE_NODE_EXPANDED) {
+ if (entry->flags & TV_NFLAGS_EXPANDED) {
/* Text will be seen, get its width */
nsfont.font_width(&plot_style_odd.text,
e->fields[i - 1].value.data,
@@ -696,7 +698,7 @@ nserror treeview_update_node_entry(treeview *tree,
}
/* Redraw */
- if (entry->parent->flags & TREE_NODE_EXPANDED) {
+ if (entry->parent->flags & TV_NFLAGS_EXPANDED) {
struct rect r;
r.x0 = 0;
r.y0 = treeview_node_y(tree, entry);
@@ -740,7 +742,7 @@ nserror treeview_create_node_entry(treeview *tree,
n = (treeview_node *) e;
- n->flags = TREE_NODE_NONE;
+ n->flags = TV_NFLAGS_NONE;
n->type = TREE_NODE_ENTRY;
n->height = tree_g.line_height;
@@ -774,7 +776,7 @@ nserror treeview_create_node_entry(treeview *tree,
treeview_insert_node(n, relation, rel);
- if (n->parent->flags & TREE_NODE_EXPANDED) {
+ if (n->parent->flags & TV_NFLAGS_EXPANDED) {
/* Inform front end of change in dimensions */
if (!(flags & TREE_OPTION_SUPPRESS_RESIZE))
tree->cw_t->update_size(tree->cw_h, -1,
@@ -874,7 +876,7 @@ static inline bool treeview_unlink_node(treeview_node *n)
}
/* Reduce ancestor heights */
- if (n->parent != NULL && n->parent->flags & TREE_NODE_EXPANDED) {
+ if (n->parent != NULL && n->parent->flags & TV_NFLAGS_EXPANDED) {
return true;
}
@@ -1067,13 +1069,13 @@ static nserror treeview_delete_node_internal(treeview *tree, treeview_node *n,
n = p;
/* Reduce ancestor heights */
- while (n != NULL && n->flags & TREE_NODE_EXPANDED) {
+ while (n != NULL && n->flags & TV_NFLAGS_EXPANDED) {
n->height -= nd.h_reduction;
n = n->parent;
}
/* Inform front end of change in dimensions */
- if (tree->root != NULL && p != NULL && p->flags & TREE_NODE_EXPANDED &&
+ if (tree->root != NULL && p != NULL && p->flags & TV_NFLAGS_EXPANDED &&
nd.h_reduction > 0 &&
!(flags & TREE_OPTION_SUPPRESS_RESIZE)) {
tree->cw_t->update_size(tree->cw_h, -1,
@@ -1112,7 +1114,7 @@ static nserror treeview_delete_empty_nodes(treeview *tree, bool interaction)
node = tree->root;
parent = node->parent;
next_sibling = node->next_sib;
- child = (node->flags & TREE_NODE_EXPANDED) ? node->children : NULL;
+ child = (node->flags & TV_NFLAGS_EXPANDED) ? node->children : NULL;
while (node != NULL) {
@@ -1139,7 +1141,7 @@ static nserror treeview_delete_empty_nodes(treeview *tree, bool interaction)
/* Reduce ancestor heights */
while (p != NULL &&
p->flags &
- TREE_NODE_EXPANDED) {
+ TV_NFLAGS_EXPANDED) {
p->height -= nd.h_reduction;
p = p->parent;
}
@@ -1165,7 +1167,7 @@ static nserror treeview_delete_empty_nodes(treeview *tree, bool interaction)
/* Reduce ancestor heights */
while (p != NULL &&
- p->flags & TREE_NODE_EXPANDED) {
+ p->flags & TV_NFLAGS_EXPANDED) {
p->height -= nd.h_reduction;
p = p->parent;
}
@@ -1179,7 +1181,7 @@ static nserror treeview_delete_empty_nodes(treeview *tree, bool interaction)
parent = node->parent;
next_sibling = node->next_sib;
- child = (node->flags & TREE_NODE_EXPANDED) ?
+ child = (node->flags & TV_NFLAGS_EXPANDED) ?
node->children : NULL;
}
@@ -1199,7 +1201,7 @@ nserror treeview_delete_node(treeview *tree, treeview_node *n,
assert(n != NULL);
assert(n->parent != NULL);
- visible = n->parent->flags & TREE_NODE_EXPANDED;
+ visible = n->parent->flags & TV_NFLAGS_EXPANDED;
r.y0 = treeview_node_y(tree, n);
r.y1 = tree->root->height;
@@ -1365,7 +1367,7 @@ static nserror treeview_node_expand_internal(treeview *tree,
assert(tree != NULL);
assert(node != NULL);
- if (node->flags & TREE_NODE_EXPANDED) {
+ if (node->flags & TV_NFLAGS_EXPANDED) {
/* What madness is this? */
LOG(("Tried to expand an expanded node."));
return NSERROR_OK;
@@ -1380,7 +1382,7 @@ static nserror treeview_node_expand_internal(treeview *tree,
}
do {
- assert((child->flags & TREE_NODE_EXPANDED) == false);
+ assert((child->flags & TV_NFLAGS_EXPANDED) == false);
if (child->text.width == 0) {
nsfont.font_width(&plot_style_odd.text,
child->text.data,
@@ -1416,12 +1418,14 @@ static nserror treeview_node_expand_internal(treeview *tree,
break;
case TREE_NODE_ROOT:
+ case TREE_NODE_NONE:
assert(node->type != TREE_NODE_ROOT);
+ assert(node->type != TREE_NODE_NONE);
break;
}
/* Update the node */
- node->flags |= TREE_NODE_EXPANDED;
+ node->flags |= TV_NFLAGS_EXPANDED;
/* And parent's heights */
do {
@@ -1473,15 +1477,15 @@ static nserror treeview_node_contract_cb(treeview_node *n, void *ctx, bool *end)
assert(n != NULL);
assert(n->type != TREE_NODE_ROOT);
- n->flags &= ~TREE_NODE_SELECTED;
+ n->flags &= ~TV_NFLAGS_SELECTED;
- if ((n->flags & TREE_NODE_EXPANDED) == false ||
+ if ((n->flags & TV_NFLAGS_EXPANDED) == false ||
(n->type == TREE_NODE_FOLDER && data->only_entries)) {
/* Nothing to do. */
return NSERROR_OK;
}
- n->flags ^= TREE_NODE_EXPANDED;
+ n->flags ^= TV_NFLAGS_EXPANDED;
h_reduction = n->height - tree_g.line_height;
assert(h_reduction >= 0);
@@ -1507,14 +1511,14 @@ static nserror treeview_node_contract_internal(treeview *tree,
bool selected;
assert(node != NULL);
- if ((node->flags & TREE_NODE_EXPANDED) == false) {
+ if ((node->flags & TV_NFLAGS_EXPANDED) == false) {
/* What madness is this? */
LOG(("Tried to contract a contracted node."));
return NSERROR_OK;
}
data.only_entries = false;
- selected = node->flags & TREE_NODE_SELECTED;
+ selected = node->flags & TV_NFLAGS_SELECTED;
/* Contract children. */
treeview_walk_internal(node, false, treeview_node_contract_cb,
@@ -1524,7 +1528,7 @@ static nserror treeview_node_contract_internal(treeview *tree,
treeview_node_contract_cb(node, &data, false);
if (selected)
- node->flags |= TREE_NODE_SELECTED;
+ node->flags |= TV_NFLAGS_SELECTED;
/* Inform front end of change in dimensions */
tree->cw_t->update_size(tree->cw_h, -1, tree->root->height);
@@ -1576,11 +1580,11 @@ nserror treeview_contract(treeview *tree, bool all)
data.only_entries = !all;
for (n = tree->root->children; n != NULL; n = n->next_sib) {
- if ((n->flags & TREE_NODE_EXPANDED) == false) {
+ if ((n->flags & TV_NFLAGS_EXPANDED) == false) {
continue;
}
- selected = n->flags & TREE_NODE_SELECTED;
+ selected = n->flags & TV_NFLAGS_SELECTED;
/* Contract children. */
treeview_walk_internal(n, false,
@@ -1590,7 +1594,7 @@ nserror treeview_contract(treeview *tree, bool all)
treeview_node_contract_cb(n, &data, false);
if (selected)
- n->flags |= TREE_NODE_SELECTED;
+ n->flags |= TV_NFLAGS_SELECTED;
}
/* Inform front end of change in dimensions */
@@ -1617,7 +1621,7 @@ static nserror treeview_expand_cb(treeview_node *n, void *ctx,
assert(n != NULL);
assert(n->type != TREE_NODE_ROOT);
- if (n->flags & TREE_NODE_EXPANDED ||
+ if (n->flags & TV_NFLAGS_EXPANDED ||
(data->only_folders && n->type != TREE_NODE_FOLDER)) {
/* Nothing to do. */
return NSERROR_OK;
@@ -1683,7 +1687,7 @@ void treeview_redraw(treeview *tree, const int x, const int y,
assert(tree != NULL);
assert(tree->root != NULL);
- assert(tree->root->flags & TREE_NODE_EXPANDED);
+ assert(tree->root->flags & TV_NFLAGS_EXPANDED);
if (tree->drag.start.y > tree->drag.prev.y) {
sel_min = tree->drag.prev.y;
@@ -1716,7 +1720,7 @@ void treeview_redraw(treeview *tree, const int x, const int y,
while (node != NULL) {
int i;
- next = (node->flags & TREE_NODE_EXPANDED) ?
+ next = (node->flags & TV_NFLAGS_EXPANDED) ?
node->children : NULL;
if (next != NULL) {
@@ -1762,20 +1766,20 @@ void treeview_redraw(treeview *tree, const int x, const int y,
} else {
invert_selection = false;
}
- if ((node->flags & TREE_NODE_SELECTED && !invert_selection) ||
- (!(node->flags & TREE_NODE_SELECTED) &&
+ if ((node->flags & TV_NFLAGS_SELECTED && !invert_selection) ||
+ (!(node->flags & TV_NFLAGS_SELECTED) &&
invert_selection)) {
bg_style = &style->sbg;
text_style = &style->stext;
infotext_style = &style->sitext;
- furniture = (node->flags & TREE_NODE_EXPANDED) ?
+ furniture = (node->flags & TV_NFLAGS_EXPANDED) ?
style->furn[TREE_FURN_CONTRACT].sel :
style->furn[TREE_FURN_EXPAND].sel;
} else {
bg_style = &style->bg;
text_style = &style->text;
infotext_style = &style->itext;
- furniture = (node->flags & TREE_NODE_EXPANDED) ?
+ furniture = (node->flags & TV_NFLAGS_EXPANDED) ?
style->furn[TREE_FURN_CONTRACT].bmp :
style->furn[TREE_FURN_EXPAND].bmp;
}
@@ -1795,7 +1799,7 @@ void treeview_redraw(treeview *tree, const int x, const int y,
/* Render icon */
if (node->type == TREE_NODE_ENTRY)
res = TREE_RES_CONTENT;
- else if (node->flags & TREE_NODE_SPECIAL)
+ else if (node->flags & TV_NFLAGS_SPECIAL)
res = TREE_RES_FOLDER_SPECIAL;
else
res = TREE_RES_FOLDER;
@@ -1827,7 +1831,7 @@ void treeview_redraw(treeview *tree, const int x, const int y,
if (node->type != TREE_NODE_ENTRY ||
- !(node->flags & TREE_NODE_EXPANDED))
+ !(node->flags & TV_NFLAGS_EXPANDED))
/* Done everything for this node */
continue;
@@ -1949,7 +1953,7 @@ static nserror treeview_node_selection_walk_cb(treeview_node *n,
switch (sw->purpose) {
case TREEVIEW_WALK_HAS_SELECTION:
- if (n->flags & TREE_NODE_SELECTED) {
+ if (n->flags & TV_NFLAGS_SELECTED) {
sw->data.has_selection = true;
*end = true; /* Can abort tree walk */
return NSERROR_OK;
@@ -1957,7 +1961,7 @@ static nserror treeview_node_selection_walk_cb(treeview_node *n,
break;
case TREEVIEW_WALK_GET_FIRST_SELECTED:
- if (n->flags & TREE_NODE_SELECTED) {
+ if (n->flags & TV_NFLAGS_SELECTED) {
sw->data.first.n = n;
*end = true; /* Can abort tree walk */
return NSERROR_OK;
@@ -1965,7 +1969,7 @@ static nserror treeview_node_selection_walk_cb(treeview_node *n,
break;
case TREEVIEW_WALK_DELETE_SELECTION:
- if (n->flags & TREE_NODE_SELECTED) {
+ if (n->flags & TV_NFLAGS_SELECTED) {
err = treeview_delete_node_internal(sw->tree, n, true,
TREE_OPTION_NONE);
if (err != NSERROR_OK) {
@@ -1978,23 +1982,23 @@ static nserror treeview_node_selection_walk_cb(treeview_node *n,
case TREEVIEW_WALK_PROPAGATE_SELECTION:
if (n->parent != NULL &&
- n->parent->flags & TREE_NODE_SELECTED &&
- !(n->flags & TREE_NODE_SELECTED)) {
- n->flags ^= TREE_NODE_SELECTED;
+ n->parent->flags & TV_NFLAGS_SELECTED &&
+ !(n->flags & TV_NFLAGS_SELECTED)) {
+ n->flags ^= TV_NFLAGS_SELECTED;
changed = true;
}
break;
case TREEVIEW_WALK_CLEAR_SELECTION:
- if (n->flags & TREE_NODE_SELECTED) {
- n->flags ^= TREE_NODE_SELECTED;
+ if (n->flags & TV_NFLAGS_SELECTED) {
+ n->flags ^= TV_NFLAGS_SELECTED;
changed = true;
}
break;
case TREEVIEW_WALK_SELECT_ALL:
- if (!(n->flags & TREE_NODE_SELECTED)) {
- n->flags ^= TREE_NODE_SELECTED;
+ if (!(n->flags & TV_NFLAGS_SELECTED)) {
+ n->flags ^= TV_NFLAGS_SELECTED;
changed = true;
}
break;
@@ -2003,12 +2007,12 @@ static nserror treeview_node_selection_walk_cb(treeview_node *n,
if (sw->current_y >= sw->data.drag.sel_min &&
sw->current_y - height <
sw->data.drag.sel_max) {
- n->flags ^= TREE_NODE_SELECTED;
+ n->flags ^= TV_NFLAGS_SELECTED;
}
return NSERROR_OK;
case TREEVIEW_WALK_YANK_SELECTION:
- if (n->flags & TREE_NODE_SELECTED) {
+ if (n->flags & TV_NFLAGS_SELECTED) {
treeview_node *p = n->parent;
int h = 0;
@@ -2016,7 +2020,7 @@ static nserror treeview_node_selection_walk_cb(treeview_node *n,
h = n->height;
/* Reduce ancestor heights */
- while (p != NULL && p->flags & TREE_NODE_EXPANDED) {
+ while (p != NULL && p->flags & TV_NFLAGS_EXPANDED) {
p->height -= h;
p = p->parent;
}
@@ -2089,7 +2093,8 @@ static treeview_node * treeview_get_first_selected(treeview *tree)
/* Exported interface, documented in treeview.h */
-void treeview_get_selection(treeview *tree, void **node_data)
+enum treeview_node_type treeview_get_selection(treeview *tree,
+ void **node_data)
{
treeview_node *n;
@@ -2097,7 +2102,13 @@ void treeview_get_selection(treeview *tree, void **node_data)
n = treeview_get_first_selected(tree);
- *node_data = n->client_data;
+ if (n != NULL && n->type & (TREE_NODE_ENTRY | TREE_NODE_FOLDER)) {
+ *node_data = n->client_data;
+ return n->type;
+ }
+
+ *node_data = NULL;
+ return TREE_NODE_NONE;
}
@@ -2332,7 +2343,7 @@ static nserror treeview_move_selection(treeview *tree, struct rect *rect)
}
/* The node that we're moving selection to can't itself be selected */
- assert(!(relation->flags & TREE_NODE_SELECTED));
+ assert(!(relation->flags & TV_NFLAGS_SELECTED));
/* Move all selected nodes from treeview to tree->move.root */
treeview_move_yank_selection(tree);
@@ -2341,10 +2352,10 @@ static nserror treeview_move_selection(treeview *tree, struct rect *rect)
for (node = tree->move.root; node != NULL; node = next) {
next = node->next_sib;
- if (!(parent->flags & TREE_NODE_EXPANDED)) {
- if (node->flags & TREE_NODE_EXPANDED)
+ if (!(parent->flags & TV_NFLAGS_EXPANDED)) {
+ if (node->flags & TV_NFLAGS_EXPANDED)
treeview_node_contract_internal(tree, node);
- node->flags &= ~TREE_NODE_SELECTED;
+ node->flags &= ~TV_NFLAGS_SELECTED;
}
treeview_insert_node(node, relation, relationship);
@@ -2378,7 +2389,7 @@ static nserror treeview_node_launch_walk_bwd_cb(treeview_node *n, void *ctx,
{
struct treeview_launch_walk_data *lw = ctx;
- if (n->type == TREE_NODE_FOLDER && n->flags == TREE_NODE_SELECTED) {
+ if (n->type == TREE_NODE_FOLDER && n->flags == TV_NFLAGS_SELECTED) {
lw->selected_depth--;
}
@@ -2390,11 +2401,11 @@ static nserror treeview_node_launch_walk_fwd_cb(treeview_node *n, void *ctx,
{
struct treeview_launch_walk_data *lw = ctx;
- if (n->type == TREE_NODE_FOLDER && n->flags & TREE_NODE_SELECTED) {
+ if (n->type == TREE_NODE_FOLDER && n->flags & TV_NFLAGS_SELECTED) {
lw->selected_depth++;
} else if (n->type == TREE_NODE_ENTRY &&
- (n->flags & TREE_NODE_SELECTED ||
+ (n->flags & TV_NFLAGS_SELECTED ||
lw->selected_depth > 0)) {
struct treeview_node_msg msg;
msg.msg = TREE_MSG_NODE_LAUNCH;
@@ -2491,7 +2502,7 @@ static nserror treeview_node_nav_cb(treeview_node *node, void *ctx,
if (node == ns->tree->root)
return NSERROR_OK;
- if (node->flags & TREE_NODE_SELECTED) {
+ if (node->flags & TV_NFLAGS_SELECTED) {
ns->n_selected++;
if (ns->curr == NULL) {
ns->curr = node;
@@ -2554,51 +2565,51 @@ static bool treeview_keyboard_navigation(treeview *tree, uint32_t key,
ns.curr->parent != NULL &&
ns.curr->parent->type != TREE_NODE_ROOT) {
/* Step to parent */
- ns.curr->parent->flags |= TREE_NODE_SELECTED;
+ ns.curr->parent->flags |= TV_NFLAGS_SELECTED;
} else if (ns.curr != NULL && tree->root->children != NULL) {
/* Select first node in tree */
- tree->root->children->flags |= TREE_NODE_SELECTED;
+ tree->root->children->flags |= TV_NFLAGS_SELECTED;
}
break;
case KEY_RIGHT:
if (ns.curr != NULL) {
- if (!(ns.curr->flags & TREE_NODE_EXPANDED)) {
+ if (!(ns.curr->flags & TV_NFLAGS_EXPANDED)) {
/* Toggle node to expanded */
treeview_node_expand_internal(tree, ns.curr);
if (ns.curr->children != NULL) {
/* Step to first child */
ns.curr->children->flags |=
- TREE_NODE_SELECTED;
+ TV_NFLAGS_SELECTED;
} else {
/* Retain current node selection */
- ns.curr->flags |= TREE_NODE_SELECTED;
+ ns.curr->flags |= TV_NFLAGS_SELECTED;
}
} else {
/* Toggle node to contracted */
treeview_node_contract_internal(tree, ns.curr);
/* Retain current node selection */
- ns.curr->flags |= TREE_NODE_SELECTED;
+ ns.curr->flags |= TV_NFLAGS_SELECTED;
}
} else if (ns.curr != NULL) {
/* Retain current node selection */
- ns.curr->flags |= TREE_NODE_SELECTED;
+ ns.curr->flags |= TV_NFLAGS_SELECTED;
}
break;
case KEY_UP:
if (ns.prev != NULL) {
/* Step to previous node */
- ns.prev->flags |= TREE_NODE_SELECTED;
+ ns.prev->flags |= TV_NFLAGS_SELECTED;
}
break;
case KEY_DOWN:
if (ns.next != NULL) {
/* Step to next node */
- ns.next->flags |= TREE_NODE_SELECTED;
+ ns.next->flags |= TV_NFLAGS_SELECTED;
}
break;
@@ -2720,16 +2731,16 @@ static bool treeview_set_move_indicator(treeview *tree, bool need_redraw,
assert(tree->root->children != NULL);
assert(target != NULL);
- if (target->flags & TREE_NODE_SELECTED) {
+ if (target->flags & TV_NFLAGS_SELECTED) {
/* Find top selected ancestor */
while (target->parent &&
- target->parent->flags & TREE_NODE_SELECTED) {
+ target->parent->flags & TV_NFLAGS_SELECTED) {
target = target->parent;
}
/* Find top ajdacent selected sibling */
while (target->prev_sib &&
- target->prev_sib->flags & TREE_NODE_SELECTED) {
+ target->prev_sib->flags & TV_NFLAGS_SELECTED) {
target = target->prev_sib;
}
target_pos = TV_TARGET_ABOVE;
@@ -2739,7 +2750,7 @@ static bool treeview_set_move_indicator(treeview *tree, bool need_redraw,
if (mouse_pos <= node_height / 4) {
target_pos = TV_TARGET_ABOVE;
} else if (mouse_pos <= (3 * node_height) / 4 ||
- target->flags & TREE_NODE_EXPANDED) {
+ target->flags & TV_NFLAGS_EXPANDED) {
target_pos = TV_TARGET_INSIDE;
} else {
target_pos = TV_TARGET_BELOW;
@@ -3127,7 +3138,7 @@ static nserror treeview_node_mouse_action_cb(treeview_node *node, void *ctx,
/* Record what position / part a drag started on */
if (ma->mouse & (BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_PRESS_2) &&
ma->tree->drag.type == TV_DRAG_NONE) {
- ma->tree->drag.selected = node->flags & TREE_NODE_SELECTED;
+ ma->tree->drag.selected = node->flags & TV_NFLAGS_SELECTED;
ma->tree->drag.start_node = node;
ma->tree->drag.part = part;
ma->tree->drag.start.x = ma->x;
@@ -3167,7 +3178,7 @@ static nserror treeview_node_mouse_action_cb(treeview_node *node, void *ctx,
if (ma->tree->drag.start_node != NULL &&
ma->tree->drag.type == TV_DRAG_SELECTION) {
- ma->tree->drag.start_node->flags ^= TREE_NODE_SELECTED;
+ ma->tree->drag.start_node->flags ^= TV_NFLAGS_SELECTED;
}
}
@@ -3212,7 +3223,7 @@ static nserror treeview_node_mouse_action_cb(treeview_node *node, void *ctx,
redraw |= treeview_clear_selection(ma->tree, &r);
/* Toggle node expansion */
- if (node->flags & TREE_NODE_EXPANDED) {
+ if (node->flags & TV_NFLAGS_EXPANDED) {
err = treeview_node_contract_internal(ma->tree, node);
} else {
err = treeview_node_expand_internal(ma->tree, node);
@@ -3260,7 +3271,7 @@ static nserror treeview_node_mouse_action_cb(treeview_node *node, void *ctx,
} else if (ma->mouse & BROWSER_MOUSE_PRESS_1 &&
!(ma->mouse &
(BROWSER_MOUSE_MOD_1 | BROWSER_MOUSE_MOD_3)) &&
- !(node->flags & TREE_NODE_SELECTED) &&
+ !(node->flags & TV_NFLAGS_SELECTED) &&
part != TV_NODE_PART_TOGGLE) {
/* Clear any existing selection */
redraw |= treeview_clear_selection(ma->tree, &r);
@@ -3272,7 +3283,7 @@ static nserror treeview_node_mouse_action_cb(treeview_node *node, void *ctx,
if (action & TV_NODE_ACTION_SELECTION) {
/* Handle change in selection */
- node->flags ^= TREE_NODE_SELECTED;
+ node->flags ^= TV_NFLAGS_SELECTED;
/* Redraw */
if (!redraw) {
@@ -3398,7 +3409,7 @@ void treeview_mouse_action(treeview *tree,
if (tree->drag.start_node != NULL &&
tree->drag.type == TV_DRAG_SELECTION) {
tree->drag.start_node->flags ^=
- TREE_NODE_SELECTED;
+ TV_NFLAGS_SELECTED;
}
}
@@ -3466,15 +3477,15 @@ static void treeview_init_plot_styles(int font_pt_size)
plot_style_even.bg.stroke_width = 0;
plot_style_even.bg.stroke_colour = 0;
plot_style_even.bg.fill_type = PLOT_OP_TYPE_SOLID;
- plot_style_even.bg.fill_colour = gui_system_colour_char("Window");
+ plot_style_even.bg.fill_colour = ns_system_colour_char("Window");
/* Text colour */
plot_style_even.text.family = PLOT_FONT_FAMILY_SANS_SERIF;
plot_style_even.text.size = font_pt_size * FONT_SIZE_SCALE;
plot_style_even.text.weight = 400;
plot_style_even.text.flags = FONTF_NONE;
- plot_style_even.text.foreground = gui_system_colour_char("WindowText");
- plot_style_even.text.background = gui_system_colour_char("Window");
+ plot_style_even.text.foreground = ns_system_colour_char("WindowText");
+ plot_style_even.text.background = ns_system_colour_char("Window");
/* Entry field text colour */
plot_style_even.itext = plot_style_even.text;
@@ -3484,13 +3495,13 @@ static void treeview_init_plot_styles(int font_pt_size)
/* Selected background colour */
plot_style_even.sbg = plot_style_even.bg;
- plot_style_even.sbg.fill_colour = gui_system_colour_char("Highlight");
+ plot_style_even.sbg.fill_colour = ns_system_colour_char("Highlight");
/* Selected text colour */
plot_style_even.stext = plot_style_even.text;
plot_style_even.stext.foreground =
- gui_system_colour_char("HighlightText");
- plot_style_even.stext.background = gui_system_colour_char("Highlight");
+ ns_system_colour_char("HighlightText");
+ plot_style_even.stext.background = ns_system_colour_char("Highlight");
/* Selected entry field text colour */
plot_style_even.sitext = plot_style_even.stext;
diff --git a/desktop/treeview.h b/desktop/treeview.h
index 6fda230b1..0b5bbbbd9 100644
--- a/desktop/treeview.h
+++ b/desktop/treeview.h
@@ -26,6 +26,7 @@
#include <stdbool.h>
#include <stdint.h>
+#include "desktop/mouse.h"
#include "desktop/core_window.h"
#include "desktop/textinput.h"
#include "utils/types.h"
@@ -34,9 +35,10 @@ typedef struct treeview treeview;
typedef struct treeview_node treeview_node;
enum treeview_node_type {
- TREE_NODE_ROOT = (1 << 0),
- TREE_NODE_FOLDER = (1 << 1),
- TREE_NODE_ENTRY = (1 << 2)
+ TREE_NODE_NONE = 0, /**< No node */
+ TREE_NODE_ROOT = (1 << 0), /**< Node is treeview's root */
+ TREE_NODE_FOLDER = (1 << 1), /**< Node is folder */
+ TREE_NODE_ENTRY = (1 << 2) /**< Node is an entry */
};
enum treeview_relationship {
@@ -381,8 +383,10 @@ bool treeview_has_selection(treeview *tree);
*
* \param tree Treeview object to get selected node in
* \param node_data Client data for the selected treeview node, or NULL
+ * \return node type of first selected node.
*/
-void treeview_get_selection(treeview *tree, void **node_data);
+enum treeview_node_type treeview_get_selection(treeview *tree,
+ void **node_data);
/**
* Edit the first selected node
diff --git a/desktop/version.c b/desktop/version.c
index 11544c01b..44d58715f 100644
--- a/desktop/version.c
+++ b/desktop/version.c
@@ -1,10 +1,10 @@
-#include "utils/testament.h"
+#include "testament.h"
-const char * const netsurf_version = "3.1 (Dev"
+const char * const netsurf_version = "3.3 (Dev"
#if defined(CI_BUILD)
" CI #" CI_BUILD
#endif
")"
;
const int netsurf_version_major = 3;
-const int netsurf_version_minor = 0;
+const int netsurf_version_minor = 3;