summaryrefslogtreecommitdiff
path: root/desktop
diff options
context:
space:
mode:
Diffstat (limited to 'desktop')
-rw-r--r--desktop/Makefile2
-rw-r--r--desktop/browser.c624
-rw-r--r--desktop/browser_history.c588
-rw-r--r--desktop/browser_history.h162
-rw-r--r--desktop/browser_private.h214
-rw-r--r--desktop/cookie_manager.c19
-rw-r--r--desktop/font_haru.c26
-rw-r--r--desktop/frames.c52
-rw-r--r--desktop/global_history.c22
-rw-r--r--desktop/gui_factory.c17
-rw-r--r--desktop/hotlist.c249
-rw-r--r--desktop/hotlist.h14
-rw-r--r--desktop/knockout.c778
-rw-r--r--desktop/knockout.h14
-rw-r--r--desktop/local_history.c446
-rw-r--r--desktop/local_history.h144
-rw-r--r--desktop/mouse.c2
-rw-r--r--desktop/netsurf.c40
-rw-r--r--desktop/options.h5
-rw-r--r--desktop/plot_style.c14
-rw-r--r--desktop/print.c48
-rw-r--r--desktop/print.h3
-rw-r--r--desktop/save_complete.c37
-rw-r--r--desktop/save_pdf.c59
-rw-r--r--desktop/save_text.c12
-rw-r--r--desktop/scrollbar.c777
-rw-r--r--desktop/scrollbar.h98
-rw-r--r--desktop/searchweb.c20
-rw-r--r--desktop/selection.c75
-rw-r--r--desktop/selection.h7
-rw-r--r--desktop/sslcert_viewer.c214
-rw-r--r--desktop/sslcert_viewer.h15
-rw-r--r--desktop/system_colour.c23
-rw-r--r--desktop/system_colour.h46
-rw-r--r--desktop/textarea.c175
-rw-r--r--desktop/textarea.h171
-rw-r--r--desktop/textinput.c6
-rw-r--r--desktop/textinput.h14
-rw-r--r--desktop/treeview.c2535
-rw-r--r--desktop/treeview.h212
-rw-r--r--desktop/version.c4
41 files changed, 5291 insertions, 2692 deletions
diff --git a/desktop/Makefile b/desktop/Makefile
index 2dcd61611..ffd932177 100644
--- a/desktop/Makefile
+++ b/desktop/Makefile
@@ -3,7 +3,7 @@
S_DESKTOP := cookie_manager.c knockout.c hotlist.c mouse.c \
plot_style.c print.c search.c searchweb.c scrollbar.c \
sslcert_viewer.c textarea.c version.c system_colour.c \
- global_history.c treeview.c
+ local_history.c global_history.c treeview.c
S_DESKTOP := $(addprefix desktop/,$(S_DESKTOP))
diff --git a/desktop/browser.c b/desktop/browser.c
index d3648d76a..1c8aa95fa 100644
--- a/desktop/browser.c
+++ b/desktop/browser.c
@@ -56,9 +56,9 @@
#include "content/hlcache.h"
#include "content/urldb.h"
#include "css/utils.h"
-#include "render/form_internal.h"
-#include "render/html.h"
-#include "render/box.h"
+#include "html/form_internal.h"
+#include "html/html.h"
+#include "html/box.h"
#include "javascript/js.h"
#include "desktop/browser_history.h"
@@ -87,7 +87,6 @@
* \param x Updated to x-coord of top left of scrollbar widget
* \param y Updated to y-coord of top left of scrollbar widget
*/
-
static inline void browser_window_get_scrollbar_pos(struct browser_window *bw,
bool horizontal, int *x, int *y)
{
@@ -129,6 +128,7 @@ browser_window_get_name(struct browser_window *bw, const char **out_name)
return NSERROR_OK;
}
+
/* exported interface, documented in browser.h */
nserror
browser_window_set_name(struct browser_window *bw, const char *name)
@@ -153,9 +153,13 @@ browser_window_set_name(struct browser_window *bw, const char *name)
return NSERROR_OK;
}
+
/* exported interface, documented in browser.h */
-bool browser_window_redraw(struct browser_window *bw, int x, int y,
- const struct rect *clip, const struct redraw_context *ctx)
+bool
+browser_window_redraw(struct browser_window *bw,
+ int x, int y,
+ const struct rect *clip,
+ const struct redraw_context *ctx)
{
struct redraw_context new_ctx = *ctx;
int width = 0;
@@ -164,29 +168,28 @@ bool browser_window_redraw(struct browser_window *bw, int x, int y,
content_type content_type;
struct content_redraw_data data;
struct rect content_clip;
+ nserror res;
if (bw == NULL) {
- LOG("NULL browser window");
+ NSLOG(netsurf, INFO, "NULL browser window");
return false;
}
- if (bw->current_content == NULL && bw->children == NULL) {
+ if ((bw->current_content == NULL) &&
+ (bw->children == NULL)) {
/* Browser window has no content, render blank fill */
- ctx->plot->clip(clip);
- return ctx->plot->rectangle(clip->x0, clip->y0,
- clip->x1, clip->y1,
- plot_style_fill_white);
+ ctx->plot->clip(ctx, clip);
+ return (ctx->plot->rectangle(ctx, plot_style_fill_white, clip) == NSERROR_OK);
}
/* Browser window has content OR children (frames) */
-
if ((bw->window != NULL) &&
(ctx->plot->option_knockout)) {
/* Root browser window: start knockout */
knockout_plot_start(ctx, &new_ctx);
}
- new_ctx.plot->clip(clip);
+ new_ctx.plot->clip(ctx, clip);
/* Handle redraw of any browser window children */
if (bw->children) {
@@ -194,11 +197,12 @@ bool browser_window_redraw(struct browser_window *bw, int x, int y,
int cur_child;
int children = bw->rows * bw->cols;
- if (bw->window != NULL)
+ if (bw->window != NULL) {
/* Root browser window; start with blank fill */
- plot_ok &= new_ctx.plot->rectangle(clip->x0, clip->y0,
- clip->x1, clip->y1,
- plot_style_fill_white);
+ plot_ok &= (new_ctx.plot->rectangle(ctx,
+ plot_style_fill_white,
+ clip) == NSERROR_OK);
+ }
/* Loop through all children of bw */
for (cur_child = 0; cur_child < children; cur_child++) {
@@ -225,7 +229,7 @@ bool browser_window_redraw(struct browser_window *bw, int x, int y,
/* Skip this frame if it lies outside clip rectangle */
if (content_clip.x0 >= content_clip.x1 ||
- content_clip.y0 >= content_clip.y1)
+ content_clip.y0 >= content_clip.y1)
continue;
/* Redraw frame */
@@ -235,10 +239,11 @@ bool browser_window_redraw(struct browser_window *bw, int x, int y,
}
/* Nothing else to redraw for browser windows with children;
- * cleanup and return */
+ * cleanup and return
+ */
if (bw->window != NULL && ctx->plot->option_knockout) {
/* Root browser window: knockout end */
- knockout_plot_end();
+ knockout_plot_end(ctx);
}
return plot_ok;
@@ -254,8 +259,9 @@ bool browser_window_redraw(struct browser_window *bw, int x, int y,
/* Non-HTML may not fill viewport to extents, so plot white
* background fill */
- plot_ok &= new_ctx.plot->rectangle(clip->x0, clip->y0,
- clip->x1, clip->y1, plot_style_fill_white);
+ plot_ok &= (new_ctx.plot->rectangle(&new_ctx,
+ plot_style_fill_white,
+ clip) == NSERROR_OK);
}
/* Set up content redraw data */
@@ -290,7 +296,7 @@ bool browser_window_redraw(struct browser_window *bw, int x, int y,
&content_clip, &new_ctx);
/* Back to full clip rect */
- new_ctx.plot->clip(clip);
+ new_ctx.plot->clip(&new_ctx, clip);
if (!bw->window) {
/* Render scrollbars */
@@ -298,32 +304,39 @@ bool browser_window_redraw(struct browser_window *bw, int x, int y,
if (bw->scroll_x != NULL) {
browser_window_get_scrollbar_pos(bw, true,
&off_x, &off_y);
- plot_ok &= scrollbar_redraw(bw->scroll_x,
+ res = scrollbar_redraw(bw->scroll_x,
x + off_x, y + off_y, clip,
bw->scale, &new_ctx);
+ if (res != NSERROR_OK) {
+ plot_ok = false;
+ }
}
if (bw->scroll_y != NULL) {
browser_window_get_scrollbar_pos(bw, false,
&off_x, &off_y);
- plot_ok &= scrollbar_redraw(bw->scroll_y,
+ res = scrollbar_redraw(bw->scroll_y,
x + off_x, y + off_y, clip,
bw->scale, &new_ctx);
+ if (res != NSERROR_OK) {
+ plot_ok = false;
+ }
}
}
if (bw->window != NULL && ctx->plot->option_knockout) {
/* Root browser window: end knockout */
- knockout_plot_end();
+ knockout_plot_end(ctx);
}
return plot_ok;
}
+
/* exported interface, documented in browser.h */
bool browser_window_redraw_ready(struct browser_window *bw)
{
if (bw == NULL) {
- LOG("NULL browser window");
+ NSLOG(netsurf, INFO, "NULL browser window");
return false;
} else if (bw->current_content != NULL) {
/* Can't render locked contents */
@@ -333,6 +346,7 @@ bool browser_window_redraw_ready(struct browser_window *bw)
return true;
}
+
/* exported interface, documented in browser_private.h */
void browser_window_update_extent(struct browser_window *bw)
{
@@ -344,9 +358,13 @@ void browser_window_update_extent(struct browser_window *bw)
browser_window_handle_scrollbars(bw);
}
+
/* exported interface, documented in browser.h */
-void browser_window_get_position(struct browser_window *bw, bool root,
- int *pos_x, int *pos_y)
+void
+browser_window_get_position(struct browser_window *bw,
+ bool root,
+ int *pos_x,
+ int *pos_y)
{
*pos_x = 0;
*pos_y = 0;
@@ -386,6 +404,7 @@ void browser_window_get_position(struct browser_window *bw, bool root,
}
}
+
/* exported interface, documented in browser.h */
void browser_window_set_position(struct browser_window *bw, int x, int y)
{
@@ -396,28 +415,31 @@ void browser_window_set_position(struct browser_window *bw, int x, int y)
bw->x = x;
bw->y = y;
} else {
- LOG("Asked to set position of front end window.");
+ NSLOG(netsurf, INFO,
+ "Asked to set position of front end window.");
assert(0);
}
}
/* exported interface, documented in browser.h */
-void browser_window_set_drag_type(struct browser_window *bw,
- browser_drag_type type, const struct rect *rect)
+void
+browser_window_set_drag_type(struct browser_window *bw,
+ browser_drag_type type,
+ const struct rect *rect)
{
struct browser_window *top_bw = browser_window_get_root(bw);
gui_drag_type gtype;
- bw->drag_type = type;
+ bw->drag.type = type;
if (type == DRAGGING_NONE) {
- top_bw->drag_window = NULL;
+ top_bw->drag.window = NULL;
} else {
- top_bw->drag_window = bw;
+ top_bw->drag.window = bw;
switch (type) {
case DRAGGING_SELECTION:
- /* TODO: tell front end */
+ /** \todo tell front end */
return;
case DRAGGING_SCR_X:
case DRAGGING_SCR_Y:
@@ -436,7 +458,7 @@ void browser_window_set_drag_type(struct browser_window *bw,
/* exported interface, documented in browser.h */
browser_drag_type browser_window_get_drag_type(struct browser_window *bw)
{
- return bw->drag_type;
+ return bw->drag.type;
}
/* exported interface, documented in browser.h */
@@ -565,36 +587,33 @@ static void browser_window_set_selection(struct browser_window *bw,
top->selection.read_only = read_only;
}
-/* exported interface, documented in browser.h */
-void browser_window_scroll_visible(struct browser_window *bw,
- const struct rect *rect)
-{
- assert(bw != NULL);
+/**
+ * Set the scroll position of a browser window.
+ *
+ * scrolls the viewport to ensure the specified rectangle of the
+ * content is shown.
+ *
+ * \param bw window to scroll
+ * \param rect The rectangle to ensure is shown.
+ * \return NSERROR_OK on success or apropriate error code.
+ */
+static nserror
+browser_window_set_scroll(struct browser_window *bw,
+ const struct rect *rect)
+{
if (bw->window != NULL) {
- /* Front end window */
- guit->window->scroll_visible(bw->window,
- rect->x0, rect->y0, rect->x1, rect->y1);
- } else {
- /* Core managed browser window */
- if (bw->scroll_x != NULL)
- scrollbar_set(bw->scroll_x, rect->x0, false);
- if (bw->scroll_y != NULL)
- scrollbar_set(bw->scroll_y, rect->y0, false);
+ return guit->window->set_scroll(bw->window, rect);
}
-}
-/* exported interface, documented in browser.h */
-void browser_window_set_scroll(struct browser_window *bw, int x, int y)
-{
- if (bw->window != NULL) {
- guit->window->set_scroll(bw->window, x, y);
- } else {
- if (bw->scroll_x != NULL)
- scrollbar_set(bw->scroll_x, x, false);
- if (bw->scroll_y != NULL)
- scrollbar_set(bw->scroll_y, y, false);
+ if (bw->scroll_x != NULL) {
+ scrollbar_set(bw->scroll_x, rect->x0, false);
+ }
+ if (bw->scroll_y != NULL) {
+ scrollbar_set(bw->scroll_y, rect->y0, false);
}
+
+ return NSERROR_OK;
}
/**
@@ -793,7 +812,7 @@ nserror browser_window_debug(struct browser_window *bw, enum content_debug op)
static bool slow_script(void *ctx)
{
static int count = 0;
- LOG("Continuing execution %d", count);
+ NSLOG(netsurf, INFO, "Continuing execution %d", count);
count++;
if (count > 1) {
count = 0;
@@ -868,7 +887,7 @@ nserror browser_window_create(enum browser_window_create_flags flags,
}
if (url != NULL) {
- enum browser_window_nav_flags nav_flags = BW_NAVIGATE_NONE;
+ enum browser_window_nav_flags nav_flags = BW_NAVIGATE_NO_TERMINAL_HISTORY_UPDATE;
if (flags & BW_CREATE_UNVERIFIABLE)
nav_flags |= BW_NAVIGATE_UNVERIFIABLE;
if (flags & BW_CREATE_HISTORY)
@@ -920,7 +939,7 @@ nserror browser_window_initialise_common(enum browser_window_create_flags flags,
/* window characteristics */
bw->refresh_interval = -1;
- bw->drag_type = DRAGGING_NONE;
+ bw->drag.type = DRAGGING_NONE;
bw->scroll_x = NULL;
bw->scroll_y = NULL;
@@ -928,10 +947,10 @@ nserror browser_window_initialise_common(enum browser_window_create_flags flags,
bw->focus = NULL;
/* initialise status text cache */
- bw->status_text = NULL;
- bw->status_text_len = 0;
- bw->status_match = 0;
- bw->status_miss = 0;
+ bw->status.text = NULL;
+ bw->status.text_len = 0;
+ bw->status.match = 0;
+ bw->status.miss = 0;
return NSERROR_OK;
}
@@ -964,11 +983,12 @@ browser_window_download(struct browser_window *bw,
/* no internal handler for this type, call out to frontend */
error = guit->misc->launch_url(url);
} else if (error != NSERROR_OK) {
- LOG("Failed to fetch download: %d", error);
+ NSLOG(netsurf, INFO, "Failed to fetch download: %d", error);
} else {
error = download_context_create(l, root->window);
if (error != NSERROR_OK) {
- LOG("Failed creating download context: %d", error);
+ NSLOG(netsurf, INFO,
+ "Failed creating download context: %d", error);
llcache_handle_abort(l);
llcache_handle_release(l);
}
@@ -1040,63 +1060,71 @@ static void browser_window_stop_throbber(struct browser_window *bw)
/**
* Callback for fetchcache() for browser window favicon fetches.
+ *
+ * \param c content handle of favicon
+ * \param event The event to process
+ * \param pw a context containing the browser window
+ * \return NSERROR_OK on success else appropriate error code.
*/
-static nserror browser_window_favicon_callback(hlcache_handle *c,
- const hlcache_event *event, void *pw)
+static nserror
+browser_window_favicon_callback(hlcache_handle *c,
+ const hlcache_event *event,
+ void *pw)
{
struct browser_window *bw = pw;
switch (event->type) {
case CONTENT_MSG_DONE:
- if (bw->current_favicon != NULL) {
+ if (bw->favicon.current != NULL) {
content_status status =
- content_get_status(bw->current_favicon);
+ content_get_status(bw->favicon.current);
if ((status == CONTENT_STATUS_READY) ||
(status == CONTENT_STATUS_DONE))
- content_close(bw->current_favicon);
+ content_close(bw->favicon.current);
- hlcache_handle_release(bw->current_favicon);
+ hlcache_handle_release(bw->favicon.current);
}
- bw->current_favicon = c;
- bw->loading_favicon = NULL;
+ bw->favicon.current = c;
+ bw->favicon.loading = NULL;
/* content_get_bitmap on the hlcache_handle should give
- * us the favicon bitmap at this point
+ * the favicon bitmap at this point
*/
guit->window->set_icon(bw->window, c);
break;
case CONTENT_MSG_ERROR:
+ case CONTENT_MSG_ERRORCODE:
/* clean up after ourselves */
- if (c == bw->loading_favicon)
- bw->loading_favicon = NULL;
- else if (c == bw->current_favicon) {
- bw->current_favicon = NULL;
+ if (c == bw->favicon.loading) {
+ bw->favicon.loading = NULL;
+ } else if (c == bw->favicon.current) {
+ bw->favicon.current = NULL;
}
hlcache_handle_release(c);
- if (bw->failed_favicon == false) {
+ if (bw->favicon.failed == false) {
nsurl *nsref = NULL;
nsurl *nsurl;
nserror error;
- bw->failed_favicon = true;
+ bw->favicon.failed = true;
error = nsurl_create("resource:favicon.ico", &nsurl);
if (error != NSERROR_OK) {
- LOG("Unable to create default location url");
+ NSLOG(netsurf, INFO,
+ "Unable to create default location url");
} else {
-
hlcache_handle_retrieve(nsurl,
HLCACHE_RETRIEVE_SNIFF_TYPE,
nsref, NULL,
browser_window_favicon_callback,
bw, NULL, CONTENT_IMAGE,
- &bw->loading_favicon);
+ &bw->favicon.loading);
nsurl_unref(nsurl);
}
@@ -1110,8 +1138,18 @@ static nserror browser_window_favicon_callback(hlcache_handle *c,
return NSERROR_OK;
}
-static void browser_window_update_favicon(hlcache_handle *c,
- struct browser_window *bw, struct content_rfc5988_link *link)
+
+/**
+ * update the favicon associated with the browser window
+ *
+ * \param c the page content handle.
+ * \param bw A top level browser window.
+ * \param link A link context or NULL to attempt fallback scanning.
+ */
+static void
+browser_window_update_favicon(hlcache_handle *c,
+ struct browser_window *bw,
+ struct content_rfc5988_link *link)
{
nsurl *nsref = NULL;
nsurl *nsurl;
@@ -1125,10 +1163,10 @@ static void browser_window_update_favicon(hlcache_handle *c,
return;
/* already fetching the favicon - use that */
- if (bw->loading_favicon != NULL)
+ if (bw->favicon.loading != NULL)
return;
- bw->failed_favicon = false;
+ bw->favicon.failed = false;
if (link == NULL) {
/* Look for "icon" */
@@ -1165,11 +1203,12 @@ static void browser_window_update_favicon(hlcache_handle *c,
/* no favicon via link, try for the default location */
error = nsurl_join(nsurl, "/favicon.ico", &nsurl);
} else {
- bw->failed_favicon = true;
+ bw->favicon.failed = true;
error = nsurl_create("resource:favicon.ico", &nsurl);
}
if (error != NSERROR_OK) {
- LOG("Unable to create default location url");
+ NSLOG(netsurf, INFO,
+ "Unable to create default location url");
return;
}
} else {
@@ -1177,14 +1216,16 @@ static void browser_window_update_favicon(hlcache_handle *c,
}
if (link == NULL) {
- LOG("fetching general favicon from '%s'", nsurl_access(nsurl));
+ NSLOG(netsurf, INFO, "fetching general favicon from '%s'",
+ nsurl_access(nsurl));
} else {
- LOG("fetching favicon rel:%s '%s'", lwc_string_data(link->rel), nsurl_access(nsurl));
+ NSLOG(netsurf, INFO, "fetching favicon rel:%s '%s'",
+ lwc_string_data(link->rel), nsurl_access(nsurl));
}
hlcache_handle_retrieve(nsurl, HLCACHE_RETRIEVE_SNIFF_TYPE,
nsref, NULL, browser_window_favicon_callback,
- bw, NULL, CONTENT_IMAGE, &bw->loading_favicon);
+ bw, NULL, CONTENT_IMAGE, &bw->favicon.loading);
nsurl_unref(nsurl);
}
@@ -1307,11 +1348,14 @@ static void browser_window_convert_to_download(struct browser_window *bw,
/**
* Browser window content event callback handler.
*/
-static nserror browser_window_callback(hlcache_handle *c,
- const hlcache_event *event, void *pw)
+static nserror
+browser_window_callback(hlcache_handle *c,
+ const hlcache_event *event,
+ void *pw)
{
struct browser_window *bw = pw;
nserror res = NSERROR_OK;
+ float sx, sy;
switch (event->type) {
case CONTENT_MSG_DOWNLOAD:
@@ -1365,19 +1409,6 @@ static nserror browser_window_callback(hlcache_handle *c,
browser_window_get_dimensions(bw, &width, &height, true);
content_reformat(c, false, width, height);
- browser_window_remove_caret(bw, false);
-
- if (bw->window != NULL) {
- guit->window->new_content(bw->window);
-
- browser_window_refresh_url_bar(bw);
- }
-
- /* new content; set scroll_to_top */
- browser_window_update(bw, true);
- content_open(c, bw, 0, 0);
- browser_window_set_status(bw, content_get_status_message(c));
-
/* history */
if (bw->history_add && bw->history) {
nsurl *url = hlcache_handle_get_url(c);
@@ -1410,10 +1441,27 @@ static nserror browser_window_callback(hlcache_handle *c,
* all newly visited URLs. With the history_add call
* after, we only leak the thumbnails when urldb does
* not add the URL.
+ *
+ * Also, since browser_window_history_add can create
+ * a thumbnail (content_redraw), we need to do it after
+ * content_reformat.
*/
browser_window_history_add(bw, c, bw->frag_id);
}
+ browser_window_remove_caret(bw, false);
+
+ if (bw->window != NULL) {
+ guit->window->new_content(bw->window);
+
+ browser_window_refresh_url_bar(bw);
+ }
+
+ /* new content; set scroll_to_top */
+ browser_window_update(bw, true);
+ content_open(c, bw, 0, 0);
+ browser_window_set_status(bw, content_get_status_message(c));
+
/* frames */
if ((content_get_type(c) == CONTENT_HTML) &&
(html_get_frameset(c) != NULL)) {
@@ -1442,6 +1490,19 @@ static nserror browser_window_callback(hlcache_handle *c,
browser_window_stop_throbber(bw);
browser_window_update_favicon(c, bw, NULL);
+ if (browser_window_history_get_scroll(bw, &sx, &sy) == NSERROR_OK) {
+ int scrollx = (int)((float)content_get_width(bw->current_content) * sx);
+ int scrolly = (int)((float)content_get_height(bw->current_content) * sy);
+ struct rect rect;
+ rect.x0 = rect.x1 = scrollx;
+ rect.y0 = rect.y1 = scrolly;
+ if (browser_window_set_scroll(bw, &rect) != NSERROR_OK) {
+ NSLOG(netsurf, WARNING,
+ "Unable to set browser scroll offsets to %d by %d",
+ scrollx, scrolly);
+ }
+ }
+
browser_window_history_update(bw, c);
hotlist_update_url(hlcache_handle_get_url(c));
@@ -1571,25 +1632,28 @@ static nserror browser_window_callback(hlcache_handle *c,
break;
case CONTENT_MSG_SCROLL:
+ {
+ struct rect rect = {
+ .x0 = event->data.scroll.x0,
+ .y0 = event->data.scroll.y0,
+ };
+
/* Content wants to be scrolled */
- if (bw->current_content != c)
+ if (bw->current_content != c) {
break;
+ }
if (event->data.scroll.area) {
- struct rect rect = {
- .x0 = event->data.scroll.x0,
- .y0 = event->data.scroll.y0,
- .x1 = event->data.scroll.x1,
- .y1 = event->data.scroll.y1
- };
- browser_window_scroll_visible(bw, &rect);
+ rect.x1 = event->data.scroll.x1;
+ rect.y1 = event->data.scroll.y1;
} else {
- browser_window_set_scroll(bw,
- event->data.scroll.x0,
- event->data.scroll.y0);
+ rect.x1 = event->data.scroll.x0;
+ rect.y1 = event->data.scroll.y0;
}
+ browser_window_set_scroll(bw, &rect);
break;
+ }
case CONTENT_MSG_DRAGSAVE:
{
@@ -1742,6 +1806,27 @@ static void browser_window_destroy_children(struct browser_window *bw)
/**
+ * internal scheduled reformat callback.
+ *
+ * scheduled reformat callback to allow reformats from unthreaded context.
+ *
+ * \param vbw The browser window to be reformatted
+ */
+static void scheduled_reformat(void *vbw)
+{
+ struct browser_window *bw = vbw;
+ int width;
+ int height;
+ nserror res;
+
+ res = guit->window->get_dimensions(bw->window, &width, &height, false);
+ if (res == NSERROR_OK) {
+ browser_window_reformat(bw, false, width, height);
+ }
+}
+
+
+/**
* Release all memory associated with a browser window.
*
* \param bw browser window
@@ -1750,7 +1835,7 @@ static void browser_window_destroy_internal(struct browser_window *bw)
{
assert(bw);
- LOG("Destroying window");
+ NSLOG(netsurf, INFO, "Destroying window");
if (bw->children != NULL || bw->iframes != NULL) {
browser_window_destroy_children(bw);
@@ -1770,8 +1855,9 @@ static void browser_window_destroy_internal(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("Clearing schedule %p(%p)", guit->window->reformat, bw->window);
- guit->misc->schedule(-1, (void(*)(void*))guit->window->reformat, bw->window);
+ NSLOG(netsurf, INFO,
+ "Clearing reformat schedule for browser window %p", bw);
+ guit->misc->schedule(-1, scheduled_reformat, bw);
/* If this brower window is not the root window, and has focus, unset
* the root browser window's focus pointer. */
@@ -1812,21 +1898,22 @@ static void browser_window_destroy_internal(struct browser_window *bw)
bw->current_content = NULL;
}
- if (bw->loading_favicon != NULL) {
- hlcache_handle_abort(bw->loading_favicon);
- hlcache_handle_release(bw->loading_favicon);
- bw->loading_favicon = NULL;
+ if (bw->favicon.loading != NULL) {
+ hlcache_handle_abort(bw->favicon.loading);
+ hlcache_handle_release(bw->favicon.loading);
+ bw->favicon.loading = NULL;
}
- if (bw->current_favicon != NULL) {
- content_status status = content_get_status(bw->current_favicon);
+ if (bw->favicon.current != NULL) {
+ content_status status = content_get_status(bw->favicon.current);
if (status == CONTENT_STATUS_READY ||
- status == CONTENT_STATUS_DONE)
- content_close(bw->current_favicon);
+ status == CONTENT_STATUS_DONE) {
+ content_close(bw->favicon.current);
+ }
- hlcache_handle_release(bw->current_favicon);
- bw->current_favicon = NULL;
+ hlcache_handle_release(bw->favicon.current);
+ bw->favicon.current = NULL;
}
if (bw->box != NULL) {
@@ -1840,15 +1927,17 @@ static void browser_window_destroy_internal(struct browser_window *bw)
/* These simply free memory, so are safe here */
- if (bw->frag_id != NULL)
+ if (bw->frag_id != NULL) {
lwc_string_unref(bw->frag_id);
+ }
browser_window_history_destroy(bw);
free(bw->name);
- free(bw->status_text);
- bw->status_text = NULL;
- LOG("Status text cache match:miss %d:%d", bw->status_match, bw->status_miss);
+ free(bw->status.text);
+ bw->status.text = NULL;
+ NSLOG(netsurf, INFO, "Status text cache match:miss %d:%d",
+ bw->status.match, bw->status.miss);
}
/**
@@ -1920,7 +2009,8 @@ nserror browser_window_refresh_url_bar(struct browser_window *bw)
/* exported interface documented in netsurf/browser_window.h */
-nserror browser_window_navigate(struct browser_window *bw,
+nserror
+browser_window_navigate(struct browser_window *bw,
nsurl *url,
nsurl *referrer,
enum browser_window_nav_flags flags,
@@ -1940,14 +2030,28 @@ nserror browser_window_navigate(struct browser_window *bw,
assert(bw);
assert(url);
- LOG("bw %p, url %s", bw, nsurl_access(url));
+ NSLOG(netsurf, INFO, "bw %p, url %s", bw, nsurl_access(url));
+
+ /* If we're navigating and we have a history entry and a content
+ * then update the history entry before we navigate to save our
+ * current state. However since history navigation pre-moves
+ * the history state, we ensure that we only do this if we've not
+ * been suppressed. In the suppressed case, the history code
+ * updates the history itself before navigating.
+ */
+ if (bw->current_content != NULL &&
+ bw->history != NULL &&
+ bw->history->current != NULL &&
+ !(flags & BW_NAVIGATE_NO_TERMINAL_HISTORY_UPDATE)) {
+ browser_window_history_update(bw, bw->current_content);
+ }
/* don't allow massively nested framesets */
for (cur = bw; cur->parent; cur = cur->parent) {
depth++;
}
if (depth > FRAME_DEPTH) {
- LOG("frame depth too high.");
+ NSLOG(netsurf, INFO, "frame depth too high.");
return NSERROR_FRAME_DEPTH;
}
@@ -2039,7 +2143,7 @@ nserror browser_window_navigate(struct browser_window *bw,
browser_window_remove_caret(bw, false);
browser_window_destroy_children(bw);
- LOG("Loading '%s'", nsurl_access(url));
+ NSLOG(netsurf, INFO, "Loading '%s'", nsurl_access(url));
browser_window_set_status(bw, messages_get("Loading"));
bw->history_add = (flags & BW_NAVIGATE_HISTORY);
@@ -2121,7 +2225,7 @@ nserror browser_window_navigate_up(struct browser_window *bw, bool new_window)
if (bw == NULL)
return NSERROR_BAD_PARAMETER;
- current = browser_window_get_url(bw);
+ current = browser_window_access_url(bw);
err = nsurl_parent(current, &parent);
if (err != NSERROR_OK) {
@@ -2147,8 +2251,8 @@ nserror browser_window_navigate_up(struct browser_window *bw, bool new_window)
}
-/* Exported interface, documented in browser.h */
-nsurl* browser_window_get_url(struct browser_window *bw)
+/* Exported interface, documented in include/netsurf/browser_window.h */
+nsurl* browser_window_access_url(struct browser_window *bw)
{
assert(bw != NULL);
@@ -2163,6 +2267,36 @@ nsurl* browser_window_get_url(struct browser_window *bw)
return corestring_nsurl_about_blank;
}
+/* Exported interface, documented in include/netsurf/browser_window.h */
+nserror browser_window_get_url(
+ struct browser_window *bw,
+ bool fragment,
+ nsurl** url_out)
+{
+ nserror err;
+ nsurl *url;
+
+ assert(bw != NULL);
+
+ if (!fragment || bw->frag_id == NULL || bw->loading_content != NULL) {
+ /* If there's a loading content, then the bw->frag_id will have
+ * been trampled, possibly with a new frag_id, but we will
+ * still be returning the current URL, so in this edge case
+ * we just drop any fragment. */
+ url = nsurl_ref(browser_window_access_url(bw));
+
+ } else {
+ err = nsurl_refragment(browser_window_access_url(bw),
+ bw->frag_id, &url);
+ if (err != NSERROR_OK) {
+ return err;
+ }
+ }
+
+ *url_out = url;
+ return NSERROR_OK;
+}
+
/* Exported interface, documented in browser.h */
const char* browser_window_get_title(struct browser_window *bw)
{
@@ -2255,19 +2389,60 @@ void browser_window_set_dimensions(struct browser_window *bw,
bw->width = width;
bw->height = height;
} else {
- LOG("Asked to set dimensions of front end window.");
+ NSLOG(netsurf, INFO,
+ "Asked to set dimensions of front end window.");
assert(0);
}
}
+/**
+ * scroll to a fragment if present
+ *
+ * \param bw browser window
+ * \return true if the scroll was sucessful
+ */
+static bool frag_scroll(struct browser_window *bw)
+{
+ struct rect rect;
+
+ if (bw->frag_id == NULL) {
+ return false;
+ }
+
+ if (!html_get_id_offset(bw->current_content,
+ bw->frag_id,
+ &rect.x0,
+ &rect.y0)) {
+ return false;
+ }
+
+ rect.x1 = rect.x0;
+ rect.y1 = rect.y0;
+ if (browser_window_set_scroll(bw, &rect) == NSERROR_OK) {
+ if (bw->current_content != NULL &&
+ bw->history != NULL &&
+ bw->history->current != NULL) {
+ browser_window_history_update(bw, bw->current_content);
+ }
+ return true;
+ }
+ return false;
+}
+
/* Exported interface, documented in browser.h */
void browser_window_update(struct browser_window *bw, bool scroll_to_top)
{
- int x, y;
+ static const struct rect zrect = {
+ .x0 = 0,
+ .y0 = 0,
+ .x1 = 0,
+ .y1 = 0
+ };
- if (bw->current_content == NULL)
+ if (bw->current_content == NULL) {
return;
+ }
switch (bw->browser_window_type) {
@@ -2278,17 +2453,15 @@ void browser_window_update(struct browser_window *bw, bool scroll_to_top)
browser_window_update_extent(bw);
- if (scroll_to_top)
- browser_window_set_scroll(bw, 0, 0);
-
/* if frag_id exists, then try to scroll to it */
/** @todo don't do this if the user has scrolled */
- if (bw->frag_id && html_get_id_offset(bw->current_content,
- bw->frag_id, &x, &y)) {
- browser_window_set_scroll(bw, x, y);
+ if (!frag_scroll(bw)) {
+ if (scroll_to_top) {
+ browser_window_set_scroll(bw, &zrect);
+ }
}
- guit->window->redraw(bw->window);
+ guit->window->invalidate(bw->window, NULL);
break;
@@ -2299,15 +2472,13 @@ void browser_window_update(struct browser_window *bw, bool scroll_to_top)
browser_window_update_extent(bw);
- if (scroll_to_top)
- browser_window_set_scroll(bw, 0, 0);
+ if (scroll_to_top) {
+ browser_window_set_scroll(bw, &zrect);
+ }
/* if frag_id exists, then try to scroll to it */
/** @todo don't do this if the user has scrolled */
- if (bw->frag_id && html_get_id_offset(bw->current_content,
- bw->frag_id, &x, &y)) {
- browser_window_set_scroll(bw, x, y);
- }
+ frag_scroll(bw);
html_redraw_a_box(bw->parent->current_content, bw->box);
break;
@@ -2317,15 +2488,13 @@ void browser_window_update(struct browser_window *bw, bool scroll_to_top)
struct rect rect;
browser_window_update_extent(bw);
- if (scroll_to_top)
- browser_window_set_scroll(bw, 0, 0);
+ if (scroll_to_top) {
+ browser_window_set_scroll(bw, &zrect);
+ }
/* if frag_id exists, then try to scroll to it */
/** @todo don't do this if the user has scrolled */
- if (bw->frag_id && html_get_id_offset(bw->current_content,
- bw->frag_id, &x, &y)) {
- browser_window_set_scroll(bw, x, y);
- }
+ frag_scroll(bw);
rect.x0 = scrollbar_get_offset(bw->scroll_x);
rect.y0 = scrollbar_get_offset(bw->scroll_y);
@@ -2354,7 +2523,7 @@ void browser_window_update_box(struct browser_window *bw, struct rect *rect)
if (bw->window != NULL) {
/* Front end window */
- guit->window->update(bw->window, rect);
+ guit->window->invalidate(bw->window, rect);
} else {
/* Core managed browser window */
browser_window_get_position(bw, true, &pos_x, &pos_y);
@@ -2366,7 +2535,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;
- guit->window->update(top->window, rect);
+ guit->window->invalidate(top->window, rect);
}
}
@@ -2465,10 +2634,10 @@ void browser_window_set_status(struct browser_window *bw, const char *text)
while (bw->parent)
bw = bw->parent;
- if ((bw->status_text != NULL) &&
- (strcmp(text, bw->status_text) == 0)) {
+ if ((bw->status.text != NULL) &&
+ (strcmp(text, bw->status.text) == 0)) {
/* status text is unchanged */
- bw->status_match++;
+ bw->status.match++;
return;
}
@@ -2476,18 +2645,18 @@ void browser_window_set_status(struct browser_window *bw, const char *text)
text_len = strlen(text);
- if ((bw->status_text == NULL) || (bw->status_text_len < text_len)) {
+ if ((bw->status.text == NULL) || (bw->status.text_len < text_len)) {
/* no current string allocation or it is not long enough */
- free(bw->status_text);
- bw->status_text = strdup(text);
- bw->status_text_len = text_len;
+ free(bw->status.text);
+ bw->status.text = strdup(text);
+ bw->status.text_len = text_len;
} else {
/* current allocation has enough space */
- memcpy(bw->status_text, text, text_len + 1);
+ memcpy(bw->status.text, text, text_len + 1);
}
- bw->status_miss++;
- guit->window->set_status(bw->window, bw->status_text);
+ bw->status.miss++;
+ guit->window->set_status(bw->window, bw->status.text);
}
@@ -2530,13 +2699,16 @@ void browser_window_set_pointer(struct browser_window *bw,
guit->window->set_pointer(root->window, gui_shape);
}
+
/* exported function documented in netsurf/browser_window.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*
- */
- guit->misc->schedule(0, (void(*)(void*))guit->window->reformat, bw->window);
+ if (bw->window == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ guit->misc->schedule(0, scheduled_reformat, bw);
+
return NSERROR_OK;
}
@@ -2837,7 +3009,7 @@ static void browser_window_mouse_drag_end(struct browser_window *bw,
{
int scr_x, scr_y;
- switch (bw->drag_type) {
+ switch (bw->drag.type) {
case DRAGGING_SELECTION:
case DRAGGING_OTHER:
case DRAGGING_CONTENT_SCROLLBAR:
@@ -2853,7 +3025,7 @@ static void browser_window_mouse_drag_end(struct browser_window *bw,
scrollbar_mouse_drag_end(bw->scroll_x, mouse, scr_x, scr_y);
- bw->drag_type = DRAGGING_NONE;
+ bw->drag.type = DRAGGING_NONE;
break;
case DRAGGING_SCR_Y:
@@ -2865,7 +3037,7 @@ static void browser_window_mouse_drag_end(struct browser_window *bw,
scrollbar_mouse_drag_end(bw->scroll_y, mouse, scr_x, scr_y);
- bw->drag_type = DRAGGING_NONE;
+ bw->drag.type = DRAGGING_NONE;
break;
default:
@@ -2883,11 +3055,11 @@ void browser_window_mouse_track(struct browser_window *bw,
const char *status = NULL;
browser_pointer_shape pointer = BROWSER_POINTER_DEFAULT;
- if (bw->window != NULL && bw->drag_window && bw != bw->drag_window) {
+ if (bw->window != NULL && bw->drag.window && bw != bw->drag.window) {
/* This is the root browser window and there's an active drag
* in a sub window.
* Pass the mouse action straight on to that bw. */
- struct browser_window *drag_bw = bw->drag_window;
+ struct browser_window *drag_bw = bw->drag.window;
int off_x = 0;
int off_y = 0;
@@ -2940,25 +3112,27 @@ void browser_window_mouse_track(struct browser_window *bw,
return;
}
- if (c == NULL && bw->drag_type != DRAGGING_FRAME)
+ if (c == NULL && bw->drag.type != DRAGGING_FRAME) {
return;
+ }
- if (bw->drag_type != DRAGGING_NONE && !mouse) {
+ if (bw->drag.type != DRAGGING_NONE && !mouse) {
browser_window_mouse_drag_end(bw, mouse, x, y);
}
/* Browser window's horizontal scrollbar */
- if (bw->scroll_x != NULL && bw->drag_type != DRAGGING_SCR_Y) {
+ if (bw->scroll_x != NULL && bw->drag.type != DRAGGING_SCR_Y) {
int scr_x, scr_y;
browser_window_get_scrollbar_pos(bw, true, &scr_x, &scr_y);
scr_x = x - scr_x - scrollbar_get_offset(bw->scroll_x);
scr_y = y - scr_y - scrollbar_get_offset(bw->scroll_y);
- if ((scr_x > 0 && scr_x < browser_window_get_scrollbar_len(bw,
- true) &&
- scr_y > 0 && scr_y < SCROLLBAR_WIDTH &&
- bw->drag_type == DRAGGING_NONE) ||
- bw->drag_type == DRAGGING_SCR_X) {
+ if ((bw->drag.type == DRAGGING_SCR_X) ||
+ (scr_x > 0 &&
+ scr_x < browser_window_get_scrollbar_len(bw, true) &&
+ scr_y > 0 &&
+ scr_y < SCROLLBAR_WIDTH &&
+ bw->drag.type == DRAGGING_NONE)) {
/* Start a scrollbar drag, or continue existing drag */
status = scrollbar_mouse_status_to_message(
scrollbar_mouse_action(
@@ -2966,8 +3140,9 @@ void browser_window_mouse_track(struct browser_window *bw,
scr_x, scr_y));
pointer = BROWSER_POINTER_DEFAULT;
- if (status != NULL)
+ if (status != NULL) {
browser_window_set_status(bw, status);
+ }
browser_window_set_pointer(bw, pointer);
return;
@@ -2981,11 +3156,12 @@ void browser_window_mouse_track(struct browser_window *bw,
scr_x = x - scr_x - scrollbar_get_offset(bw->scroll_x);
scr_y = y - scr_y - scrollbar_get_offset(bw->scroll_y);
- if ((scr_y > 0 && scr_y < browser_window_get_scrollbar_len(bw,
- false) &&
- scr_x > 0 && scr_x < SCROLLBAR_WIDTH &&
- bw->drag_type == DRAGGING_NONE) ||
- bw->drag_type == DRAGGING_SCR_Y) {
+ if ((bw->drag.type == DRAGGING_SCR_Y) ||
+ (scr_y > 0 &&
+ scr_y < browser_window_get_scrollbar_len(bw, false) &&
+ scr_x > 0 &&
+ scr_x < SCROLLBAR_WIDTH &&
+ bw->drag.type == DRAGGING_NONE)) {
/* Start a scrollbar drag, or continue existing drag */
status = scrollbar_mouse_status_to_message(
scrollbar_mouse_action(
@@ -2993,29 +3169,32 @@ void browser_window_mouse_track(struct browser_window *bw,
scr_x, scr_y));
pointer = BROWSER_POINTER_DEFAULT;
- if (status != NULL)
+ if (status != NULL) {
browser_window_set_status(bw, status);
+ }
browser_window_set_pointer(bw, pointer);
return;
}
}
- if (bw->drag_type == DRAGGING_FRAME) {
+ if (bw->drag.type == DRAGGING_FRAME) {
browser_window_resize_frame(bw, bw->x + x, bw->y + y);
- } else if (bw->drag_type == DRAGGING_PAGE_SCROLL) {
+ } else if (bw->drag.type == DRAGGING_PAGE_SCROLL) {
/* mouse movement since drag started */
- int scrollx = bw->drag_start_x - x;
- int scrolly = bw->drag_start_y - y;
+ struct rect rect;
+
+ rect.x0 = bw->drag.start_x - x;
+ rect.y0 = bw->drag.start_y - y;
/* new scroll offsets */
- scrollx += bw->drag_start_scroll_x;
- scrolly += bw->drag_start_scroll_y;
+ rect.x0 += bw->drag.start_scroll_x;
+ rect.y0 += bw->drag.start_scroll_y;
- bw->drag_start_scroll_x = scrollx;
- bw->drag_start_scroll_y = scrolly;
+ bw->drag.start_scroll_x = rect.x1 = rect.x0;
+ bw->drag.start_scroll_y = rect.y1 = rect.y0;
- browser_window_set_scroll(bw, scrollx, scrolly);
+ browser_window_set_scroll(bw, &rect);
} else {
assert(c != NULL);
content_mouse_track(c, bw, mouse, x, y);
@@ -3163,19 +3342,20 @@ void browser_window_page_drag_start(struct browser_window *bw, int x, int y)
browser_window_set_drag_type(bw, DRAGGING_PAGE_SCROLL, NULL);
- bw->drag_start_x = x;
- bw->drag_start_y = y;
+ bw->drag.start_x = x;
+ bw->drag.start_y = y;
if (bw->window != NULL) {
/* Front end window */
- guit->window->get_scroll(bw->window, &bw->drag_start_scroll_x,
- &bw->drag_start_scroll_y);
+ guit->window->get_scroll(bw->window,
+ &bw->drag.start_scroll_x,
+ &bw->drag.start_scroll_y);
guit->window->scroll_start(bw->window);
} else {
/* Core managed browser window */
- bw->drag_start_scroll_x = scrollbar_get_offset(bw->scroll_x);
- bw->drag_start_scroll_y = scrollbar_get_offset(bw->scroll_y);
+ bw->drag.start_scroll_x = scrollbar_get_offset(bw->scroll_x);
+ bw->drag.start_scroll_y = scrollbar_get_offset(bw->scroll_y);
}
}
diff --git a/desktop/browser_history.c b/desktop/browser_history.c
index d21c5bc25..d9db0eb18 100644
--- a/desktop/browser_history.c
+++ b/desktop/browser_history.c
@@ -31,13 +31,12 @@
#include "utils/log.h"
#include "utils/utils.h"
#include "netsurf/layout.h"
-#include "netsurf/plotters.h"
#include "netsurf/content.h"
+#include "netsurf/window.h"
#include "content/hlcache.h"
#include "content/urldb.h"
#include "netsurf/bitmap.h"
-#include "desktop/system_colour.h"
#include "desktop/gui_internal.h"
#include "desktop/browser_history.h"
#include "desktop/browser_private.h"
@@ -47,45 +46,12 @@
#define RIGHT_MARGIN 50
#define BOTTOM_MARGIN 30
-struct history_page {
- nsurl *url; /**< Page URL, never 0. */
- lwc_string *frag_id; /** Fragment identifier, or 0. */
- char *title; /**< Page title, never 0. */
-};
-
-/** A node in the history tree. */
-struct history_entry {
- struct history_page page;
- struct history_entry *back; /**< Parent. */
- struct history_entry *next; /**< Next sibling. */
- struct history_entry *forward; /**< First child. */
- struct history_entry *forward_pref; /**< Child in direction of
- current entry. */
- struct history_entry *forward_last; /**< Last child. */
- unsigned int children; /**< Number of children. */
- int x; /**< Position of node. */
- int y; /**< Position of node. */
- struct bitmap *bitmap; /**< Thumbnail bitmap, or 0. */
-};
-
-/** History tree for a window. */
-struct history {
- /** First page in tree (page that window opened with). */
- struct history_entry *start;
- /** Current position in tree. */
- struct history_entry *current;
- /** Width of layout. */
- int width;
- /** Height of layout. */
- int height;
-};
-
/**
* Clone a history entry
*
* \param history opaque history structure, as returned by history_create()
- * \param entry entry to clone
+ * \param entry entry to clone
* \return A cloned history entry or NULL on error
*/
static struct history_entry *
@@ -97,47 +63,85 @@ browser_window_history__clone_entry(struct history *history,
struct history_entry *prev = NULL;
struct history_entry *new_entry;
+ assert(entry);
assert(entry->page.url);
assert(entry->page.title);
/* clone the entry */
- new_entry = malloc(sizeof *entry);
- if (!new_entry)
+ new_entry = calloc(1, sizeof *entry);
+ if (!new_entry) {
return NULL;
+ }
- memcpy(new_entry, entry, sizeof *entry);
- new_entry->page.url = nsurl_ref(entry->page.url);
- if (entry->page.frag_id)
- new_entry->page.frag_id = lwc_string_ref(entry->page.frag_id);
-
+ /* copy page information */
new_entry->page.title = strdup(entry->page.title);
- if (!new_entry->page.url || !new_entry->page.title ||
- ((entry->page.frag_id) && (!new_entry->page.frag_id))) {
- nsurl_unref(new_entry->page.url);
- if (new_entry->page.frag_id)
- lwc_string_unref(new_entry->page.frag_id);
+ if (new_entry->page.title == NULL) {
+ free(new_entry);
+ return NULL;
+ }
+
+ new_entry->page.url = nsurl_ref(entry->page.url);
+ if (new_entry->page.url == NULL) {
free(new_entry->page.title);
free(new_entry);
return NULL;
}
- /* update references */
- if (history->current == entry)
- history->current = new_entry;
+ if (entry->page.frag_id == NULL) {
+ new_entry->page.frag_id = NULL;
+ } else {
+ new_entry->page.frag_id = lwc_string_ref(entry->page.frag_id);
+ if (new_entry->page.frag_id == NULL) {
+ nsurl_unref(new_entry->page.url);
+ free(new_entry);
+ return NULL;
+ }
+ }
+
+ if (entry->page.bitmap == NULL) {
+ new_entry->page.bitmap = NULL;
+ } else {
+ /* create a new bitmap and copy original into it */
+ unsigned char *bmsrc_data;
+ unsigned char *bmdst_data;
+ size_t bmsize;
+
+ new_entry->page.bitmap = guit->bitmap->create(WIDTH, HEIGHT,
+ BITMAP_NEW | BITMAP_OPAQUE);
+
+ if (new_entry->page.bitmap != NULL) {
+ bmsrc_data = guit->bitmap->get_buffer(entry->page.bitmap);
+ bmdst_data = guit->bitmap->get_buffer(new_entry->page.bitmap);
+ bmsize = guit->bitmap->get_rowstride(new_entry->page.bitmap) *
+ guit->bitmap->get_height(new_entry->page.bitmap);
+ memcpy(bmdst_data, bmsrc_data, bmsize);
+ }
+ }
+
+ /* copy tree values */
+ new_entry->back = entry->back;
+ new_entry->next = entry->next;
+ new_entry->forward = entry->forward;
+ new_entry->forward_pref = entry->forward_pref;
+ new_entry->forward_last = entry->forward_last;
/* recurse for all children */
- for (child = new_entry->forward; child; child = child->next) {
+ for (child = new_entry->forward; child != NULL; child = child->next) {
new_child = browser_window_history__clone_entry(history, child);
- if (new_child) {
- new_child->back = new_entry;
- } else {
+ if (new_child == NULL) {
nsurl_unref(new_entry->page.url);
- if (new_entry->page.frag_id)
+ if (new_entry->page.frag_id) {
lwc_string_unref(new_entry->page.frag_id);
+ }
free(new_entry->page.title);
+ if (entry->page.bitmap != NULL) {
+ guit->bitmap->destroy(entry->page.bitmap);
+ }
free(new_entry);
return NULL;
}
+
+ new_child->back = new_entry;
if (prev)
prev->next = new_child;
if (new_entry->forward == child)
@@ -148,6 +152,12 @@ browser_window_history__clone_entry(struct history *history,
new_entry->forward_last = new_child;
prev = new_child;
}
+
+ /* update references */
+ if (history->current == entry) {
+ history->current = new_entry;
+ }
+
return new_entry;
}
@@ -158,15 +168,20 @@ browser_window_history__clone_entry(struct history *history,
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);
+ if (entry != NULL) {
+ 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);
+ if (entry->page.bitmap != NULL) {
+ guit->bitmap->destroy(entry->page.bitmap);
+ }
+ free(entry);
+ }
}
@@ -236,197 +251,9 @@ static void browser_window_history__layout(struct history *history)
history->height += BOTTOM_MARGIN / 2;
}
-/** plot style for drawing lines between nodes */
-static plot_style_t pstyle_line = {
- .stroke_type = PLOT_OP_TYPE_SOLID,
- .stroke_width = 2,
-};
-
-/** plot style for drawing background */
-static plot_style_t pstyle_bg = {
- .fill_type = PLOT_OP_TYPE_SOLID,
-};
-
-/** plot style for drawing rectangle round unselected nodes */
-static plot_style_t pstyle_rect = {
- .stroke_type = PLOT_OP_TYPE_SOLID,
- .stroke_width = 1,
-};
-
-/** plot style for drawing rectangle round selected nodes */
-static plot_style_t pstyle_rect_sel = {
- .stroke_type = PLOT_OP_TYPE_SOLID,
- .stroke_width = 3,
-};
-
-/** plot style for font on unselected nodes */
-static plot_font_style_t pfstyle_node = {
- .family = PLOT_FONT_FAMILY_SANS_SERIF,
- .size = 8 * FONT_SIZE_SCALE,
- .weight = 400,
- .flags = FONTF_NONE,
-};
-
-/** plot style for font on unselected nodes */
-static plot_font_style_t pfstyle_node_sel = {
- .family = PLOT_FONT_FAMILY_SANS_SERIF,
- .size = 8 * FONT_SIZE_SCALE,
- .weight = 900,
- .flags = FONTF_NONE,
-};
-
-/**
- * Recursively redraw a history_entry.
- *
- * \param history history containing the entry
- * \param entry entry to render
- * \param x0 area top left x coordinate
- * \param y0 area top left y coordinate
- * \param x1 area bottom right x coordinate
- * \param y1 area bottom right y coordinate
- * \param x window x offset
- * \param y window y offset
- * \param clip clip redraw
- * \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;
- int tailsize = 5;
- int xoffset = x - x0;
- int yoffset = y - y0;
-
- plot_style_t *pstyle;
- plot_font_style_t *pfstyle;
-
- nserror res;
-
- /* setup plot styles */
- if (entry == history->current) {
- pstyle = &pstyle_rect_sel;
- pfstyle = &pfstyle_node_sel;
- } else {
- pstyle = &pstyle_rect;
- pfstyle = &pfstyle_node;
- }
-
- /* setup clip area */
- 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;
- }
- }
-
- /* Only attempt to plot bitmap if it is present */
- if (entry->bitmap != NULL) {
- plot->bitmap(entry->x + xoffset,
- entry->y + yoffset,
- WIDTH, HEIGHT,
- entry->bitmap,
- 0xffffff,
- 0);
- }
-
- if (!plot->rectangle(entry->x - 1 + xoffset,
- entry->y - 1 + yoffset,
- entry->x + xoffset + WIDTH,
- entry->y + yoffset + HEIGHT,
- pstyle)) {
- return false;
- }
-
- res = guit->layout->position(plot_style_font, entry->page.title,
- strlen(entry->page.title), WIDTH,
- &char_offset, &actual_x);
- if (res != NSERROR_OK) {
- return false;
- }
-
-
- if (!plot->text(entry->x + xoffset,
- entry->y + HEIGHT + 12 + yoffset,
- entry->page.title,
- char_offset,
- pfstyle)) {
- return false;
- }
-
- /* for each child node draw a line and recurse redraw into it */
- 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,
- &pstyle_line)) {
- return false;
- }
- if (!plot->line(entry->x + WIDTH + tailsize + xoffset,
- entry->y + HEIGHT / 2 + yoffset,
- child->x - tailsize +xoffset,
- child->y + HEIGHT / 2 + yoffset,
- &pstyle_line)) {
- return false;
- }
- if (!plot->line(child->x - tailsize + xoffset,
- child->y + HEIGHT / 2 + yoffset,
- child->x + xoffset, child->y +
- HEIGHT / 2 + yoffset,
- &pstyle_line)) {
- 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
@@ -469,17 +296,6 @@ nserror browser_window_history_create(struct browser_window *bw)
{
struct history *history;
- pstyle_bg.fill_colour = ns_system_colour_char("Window");
- pfstyle_node.background = pstyle_bg.fill_colour;
- pfstyle_node_sel.background = pstyle_bg.fill_colour;
-
- pstyle_line.stroke_colour = ns_system_colour_char("GrayText");
- pstyle_rect.stroke_colour = pstyle_line.stroke_colour;
- pfstyle_node.foreground = pstyle_line.stroke_colour;
-
- pstyle_rect_sel.stroke_colour = ns_system_colour_char("Highlight");
- pfstyle_node_sel.foreground = pstyle_rect_sel.stroke_colour;
-
bw->history = NULL;
history = calloc(1, sizeof *history);
@@ -520,7 +336,7 @@ nserror browser_window_history_clone(const struct browser_window *existing,
new_history->start = browser_window_history__clone_entry(new_history,
new_history->start);
if (!new_history->start) {
- LOG("Insufficient memory to clone history");
+ NSLOG(netsurf, INFO, "Insufficient memory to clone history");
browser_window_history_destroy(clone);
clone->history = NULL;
return NSERROR_NOMEM;
@@ -531,14 +347,14 @@ nserror browser_window_history_clone(const struct browser_window *existing,
/* exported interface documented in desktop/browser_history.h */
-nserror browser_window_history_add(struct browser_window *bw,
- struct hlcache_handle *content, lwc_string *frag_id)
+nserror
+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;
nserror ret;
assert(bw);
@@ -547,32 +363,50 @@ nserror browser_window_history_add(struct browser_window *bw,
history = bw->history;
- /* allocate space */
entry = malloc(sizeof *entry);
if (entry == NULL) {
return NSERROR_NOMEM;
}
+ /* page information */
title = strdup(content_get_title(content));
if (title == NULL) {
free(entry);
return NSERROR_NOMEM;
}
- entry->page.url = nsurl_ref(nsurl);
- entry->page.frag_id = frag_id ? lwc_string_ref(frag_id) : 0;
-
+ entry->page.url = nsurl_ref(hlcache_handle_get_url(content));
+ entry->page.frag_id = frag_id ? lwc_string_ref(frag_id) : NULL;
entry->page.title = title;
+ entry->page.scroll_x = 0.0f;
+ entry->page.scroll_y = 0.0f;
+
+ /* create thumbnail for localhistory view */
+ NSLOG(netsurf, DEBUG,
+ "Creating thumbnail for %s", nsurl_access(entry->page.url));
+
+ entry->page.bitmap = guit->bitmap->create(WIDTH, HEIGHT,
+ BITMAP_NEW | BITMAP_CLEAR_MEMORY | BITMAP_OPAQUE);
+ if (entry->page.bitmap != NULL) {
+ ret = guit->bitmap->render(entry->page.bitmap, content);
+ if (ret != NSERROR_OK) {
+ /* Thumbnail render failed */
+ NSLOG(netsurf, WARNING, "Thumbnail render failed");
+ }
+ }
+
+ /* insert into tree */
entry->back = history->current;
- entry->next = 0;
- entry->forward = entry->forward_pref = entry->forward_last = 0;
+ entry->next = NULL;
+ entry->forward = entry->forward_pref = entry->forward_last = NULL;
entry->children = 0;
- entry->bitmap = 0;
+
if (history->current) {
- if (history->current->forward_last)
+ if (history->current->forward_last) {
history->current->forward_last->next = entry;
- else
+ } else {
history->current->forward = entry;
+ }
history->current->forward_pref = entry;
history->current->forward_last = entry;
history->current->children++;
@@ -581,33 +415,6 @@ nserror browser_window_history_add(struct browser_window *bw,
}
history->current = entry;
- /* if we have a thumbnail, don't update until the page has finished
- * loading */
- bitmap = urldb_get_thumbnail(nsurl);
- if (bitmap == NULL) {
- LOG("Creating thumbnail for %s", nsurl_access(nsurl));
- bitmap = guit->bitmap->create(WIDTH, HEIGHT,
- BITMAP_NEW | BITMAP_CLEAR_MEMORY |
- BITMAP_OPAQUE);
- if (bitmap != NULL) {
- ret = guit->bitmap->render(bitmap, content);
- if (ret == NSERROR_OK) {
- /* Successful thumbnail so register it
- * with the url.
- */
- urldb_set_thumbnail(nsurl, bitmap);
- } else {
- /* Thumbnailing failed. Ignore it
- * silently but clean up bitmap.
- */
- LOG("Thumbnail renderfailed");
- guit->bitmap->destroy(bitmap);
- bitmap = NULL;
- }
- }
- }
- entry->bitmap = bitmap;
-
browser_window_history__layout(history);
return NSERROR_OK;
@@ -620,12 +427,15 @@ nserror browser_window_history_update(struct browser_window *bw,
{
struct history *history;
char *title;
+ int sx, sy;
assert(bw != NULL);
history = bw->history;
- if (!history || !history->current || !history->current->bitmap) {
+ if (!history ||
+ !history->current ||
+ !history->current->page.bitmap) {
return NSERROR_INVALID;
}
@@ -636,16 +446,50 @@ nserror browser_window_history_update(struct browser_window *bw,
if (title == NULL) {
return NSERROR_NOMEM;
}
-
+ NSLOG(netsurf, INFO, "Updating history entry for %s", title);
free(history->current->page.title);
history->current->page.title = title;
- guit->bitmap->render(history->current->bitmap, content);
+ if (history->current->page.bitmap != NULL) {
+ guit->bitmap->render(history->current->page.bitmap, content);
+ }
+ if (bw->window != NULL &&
+ guit->window->get_scroll(bw->window, &sx, &sy)) {
+ /* Successfully got scroll offsets, update the entry */
+ history->current->page.scroll_x = \
+ (float)sx / (float)content_get_width(content);
+ history->current->page.scroll_y = \
+ (float)sy / (float)content_get_height(content);
+ NSLOG(netsurf, INFO, "Updated scroll offsets to %g by %g",
+ history->current->page.scroll_x,
+ history->current->page.scroll_y);
+ }
return NSERROR_OK;
}
+/* exported interface documented in desktop/browser_private.h */
+nserror
+browser_window_history_get_scroll(struct browser_window *bw,
+ float *sx, float *sy)
+{
+ struct history *history;
+
+ assert(bw != NULL);
+
+ history = bw->history;
+
+ if (!history ||
+ !history->current ||
+ !history->current->page.bitmap) {
+ return NSERROR_INVALID;
+ }
+
+ *sx = history->current->page.scroll_x;
+ *sy = history->current->page.scroll_y;
+ return NSERROR_OK;
+}
/* exported interface documented in desktop/browser_history.h */
void browser_window_history_destroy(struct browser_window *bw)
@@ -704,6 +548,27 @@ bool browser_window_history_forward_available(struct browser_window *bw)
bw->history->current->forward_pref);
}
+/* exported interface documented in desktop/browser_history.h */
+nserror
+browser_window_history_get_thumbnail(struct browser_window *bw,
+ struct bitmap **bitmap_out)
+{
+ struct bitmap *bitmap;
+
+ if (!bw || !bw->history || !bw->history->current) {
+ return NSERROR_INVALID;
+ }
+
+ if (bw->history->current->page.bitmap == NULL) {
+ bitmap = content_get_bitmap(bw->current_content);
+ } else {
+ bitmap = bw->history->current->page.bitmap;
+ }
+
+ *bitmap_out = bitmap;
+
+ return NSERROR_OK;
+}
/* exported interface documented in desktop/browser_history.h */
nserror browser_window_history_go(struct browser_window *bw,
@@ -736,9 +601,13 @@ nserror browser_window_history_go(struct browser_window *bw,
url, NULL, bw, NULL);
history->current = current;
} else {
+ if (bw->current_content != NULL) {
+ browser_window_history_update(bw, bw->current_content);
+ }
history->current = entry;
error = browser_window_navigate(bw, url, NULL,
- BW_NAVIGATE_NONE, NULL, NULL, NULL);
+ BW_NAVIGATE_NO_TERMINAL_HISTORY_UPDATE,
+ NULL, NULL, NULL);
}
nsurl_unref(url);
@@ -748,99 +617,7 @@ nserror browser_window_history_go(struct browser_window *bw,
/* exported interface documented in desktop/browser_history.h */
-void browser_window_history_size(struct browser_window *bw,
- int *width, int *height)
-{
- assert(bw != NULL);
- assert(bw->history != NULL);
-
- *width = bw->history->width;
- *height = bw->history->height;
-}
-
-
-/* exported interface documented in desktop/browser_history.h */
-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 == NULL) {
- LOG("Attempt to draw NULL history.");
- return false;
- }
-
- if (!history->start)
- return true;
-
- return browser_window_history__redraw_entry(history, history->start,
- 0, 0, 0, 0, 0, 0, false, ctx);
-}
-
-
-/* exported interface documented in desktop/browser_history.h */
-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 browser_window_history__redraw_entry(history, history->start,
- x0, y0, x1, y1, x, y, true, ctx);
-}
-
-
-/* exported interface documented in desktop/browser_history.h */
-bool browser_window_history_click(struct browser_window *bw,
- int x, int y, bool new_window)
-{
- struct history_entry *entry;
- struct history *history;
-
- 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;
-
- browser_window_history_go(bw, entry, new_window);
-
- return true;
-}
-
-
-/* exported interface documented in desktop/browser_history.h */
-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 = browser_window_history__find_position(history->start, x, y);
- if (!entry)
- return 0;
-
- return nsurl_access(entry->page.url);
-}
-
-
-/* exported interface documented in desktop/browser_history.h */
-void browser_window_history_enumerate_forward(const struct browser_window *bw,
+void browser_window_history_enumerate_forward(const struct browser_window *bw,
browser_window_history_enumerate_cb cb, void *user_data)
{
struct history_entry *e;
@@ -858,7 +635,7 @@ void browser_window_history_enumerate_forward(const struct browser_window *bw,
/* exported interface documented in desktop/browser_history.h */
-void browser_window_history_enumerate_back(const struct browser_window *bw,
+void browser_window_history_enumerate_back(const struct browser_window *bw,
browser_window_history_enumerate_cb cb, void *user_data)
{
struct history_entry *e;
@@ -886,10 +663,9 @@ void browser_window_history_enumerate(const struct browser_window *bw,
/* exported interface documented in desktop/browser_history.h */
-const char *browser_window_history_entry_get_url(
- const struct history_entry *entry)
+nsurl *browser_window_history_entry_get_url(const struct history_entry *entry)
{
- return nsurl_access(entry->page.url);
+ return nsurl_ref(entry->page.url);
}
diff --git a/desktop/browser_history.h b/desktop/browser_history.h
index 8ffb6125b..9b6f1fd42 100644
--- a/desktop/browser_history.h
+++ b/desktop/browser_history.h
@@ -16,71 +16,28 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- * Browser history tree (interface).
+/**
+ * \file
+ * Interface to browser history operations
+ *
+ * The are operations on a browsing contexts history. These interfaces
+ * allow navigation forward and backwards in the history as well as
+ * enumerating the entries.
+ *
+ * The local history viewing is distinct via corewindow defined in
+ * desktop/local_history.h
*/
-#ifndef _NETSURF_DESKTOP_BROWSER_HISTORY_H_
-#define _NETSURF_DESKTOP_BROWSER_HISTORY_H_
+#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;
-
-/**
- * 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);
-
-/**
- * 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);
-/**
- * Insert a url into the history tree.
- *
- * \param bw browser window with history object
- * \param content content to add to history
- * \param frag_id fragment identifier, or NULL.
- * \return NSERROR_OK or error code on faliure.
- *
- * The page is added after the current entry and becomes current.
- */
-nserror browser_window_history_add(struct browser_window *bw,
- struct hlcache_handle *content, lwc_string *frag_id);
-
-/**
- * Update the thumbnail for the current entry.
- *
- * \param bw The browser window to update the history within.
- * \param content content for current entry
- * \return NSERROR_OK or error code on faliure.
- */
-nserror browser_window_history_update(struct browser_window *bw,
- struct hlcache_handle *content);
-
-/**
- * Free a history structure.
- *
- * \param bw The browser window to destroy the history within.
- */
-void browser_window_history_destroy(struct browser_window *bw);
+struct bitmap;
/**
* Go back in the history.
@@ -91,6 +48,7 @@ void browser_window_history_destroy(struct browser_window *bw);
*/
nserror browser_window_history_back(struct browser_window *bw, bool new_window);
+
/**
* Go forward in the history.
*
@@ -100,6 +58,7 @@ nserror browser_window_history_back(struct browser_window *bw, bool new_window);
*/
nserror browser_window_history_forward(struct browser_window *bw, bool new_window);
+
/**
* Check whether it is pssible to go back in the history.
*
@@ -108,6 +67,7 @@ nserror browser_window_history_forward(struct browser_window *bw, bool new_windo
*/
bool browser_window_history_back_available(struct browser_window *bw);
+
/**
* Check whether it is pssible to go forwards in the history.
*
@@ -117,62 +77,13 @@ bool browser_window_history_back_available(struct browser_window *bw);
bool browser_window_history_forward_available(struct browser_window *bw);
/**
- * Get the dimensions of a history.
- *
- * \param bw browser window with history object.
- * \param width updated to width
- * \param height updated to height
- */
-void browser_window_history_size(struct browser_window *bw,
- int *width, int *height);
-
-/**
- * Redraw all of a history area.
+ * Get the thumbnail bitmap for the current history entry
*
- * \param bw browser window with history object.
- * \param ctx current redraw context
- */
-bool browser_window_history_redraw(struct browser_window *bw,
- const struct redraw_context *ctx);
-
-/**
- * Redraw part of a history area.
- *
- * \param bw browser window with history object.
- * \param x0 left X co-ordinate of redraw area
- * \param y0 top Y co-ordinate of redraw area
- * \param x1 right X co-ordinate of redraw area
- * \param y1 lower Y co-ordinate of redraw area
- * \param x start X co-ordinate on plot canvas
- * \param y start Y co-ordinate on plot canvas
- * \param ctx current redraw context
- */
-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);
-
-/**
- * Handle a mouse click in a history.
- *
- * \param bw browser window containing history
- * \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 browser_window_history_click(struct browser_window *bw,
- int x, int y, bool new_window);
-
-/**
- * Determine the URL of the entry at a position.
- *
- * \param bw browser window containing history
- * \param x x coordinate.
- * \param y y coordinate.
- * \return URL, or 0 if no entry at (x, y)
+ * \param bw The browser window
+ * \param bitmap The bitmat for the current history entry.
+ * \return NSERROR_OK or error code on faliure.
*/
-const char *browser_window_history_position_url(struct browser_window *bw,
- int x, int y);
+nserror browser_window_history_get_thumbnail(struct browser_window *bw, struct bitmap **bitmap_out);
/**
* Callback function type for history enumeration
@@ -187,6 +98,7 @@ typedef bool (*browser_window_history_enumerate_cb)(
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.
@@ -198,6 +110,7 @@ typedef bool (*browser_window_history_enumerate_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
*
@@ -208,6 +121,7 @@ void browser_window_history_enumerate(const struct browser_window *bw,
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
*
@@ -218,32 +132,33 @@ void browser_window_history_enumerate_forward(const struct browser_window *bw,
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
+ * \param entry the history entry to retrieve the URL from
+ * \return A referenced nsurl URL
*/
-const char *browser_window_history_entry_get_url(
- const struct history_entry *entry);
+struct nsurl *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
+ * \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);
+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
+ * \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);
+const char *browser_window_history_entry_get_title(const struct history_entry *entry);
+
/**
* Navigate to specified history entry, optionally in new window
@@ -253,7 +168,6 @@ const char *browser_window_history_entry_get_title(
* \param new_window open entry in new window
* \return NSERROR_OK or error code on faliure.
*/
-nserror browser_window_history_go(struct browser_window *bw,
- struct history_entry *entry, bool new_window);
+nserror 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 072a894d6..192d22bf0 100644
--- a/desktop/browser_private.h
+++ b/desktop/browser_private.h
@@ -17,7 +17,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
+/**
+ * \file
* Browser window private structure.
*/
@@ -34,27 +35,94 @@
struct box;
struct hlcache_handle;
struct gui_window;
-struct history;
struct selection;
+struct nsurl;
+
+/**
+ * history entry page information
+ */
+struct history_page {
+ struct nsurl *url; /**< Page URL, never NULL. */
+ lwc_string *frag_id; /** Fragment identifier, or NULL. */
+ char *title; /**< Page title, never NULL. */
+ struct bitmap *bitmap; /**< Thumbnail bitmap, or NULL. */
+ float scroll_x; /**< Scroll X offset when visited */
+ float scroll_y; /**< Scroll Y offset when visited */
+};
+
+/**
+ * A node in the history tree.
+ */
+struct history_entry {
+ struct history_page page;
+ struct history_entry *back; /**< Parent. */
+ struct history_entry *next; /**< Next sibling. */
+ struct history_entry *forward; /**< First child. */
+ struct history_entry *forward_pref; /**< Child in direction of
+ current entry. */
+ struct history_entry *forward_last; /**< Last child. */
+ unsigned int children; /**< Number of children. */
+ int x; /**< Position of node. */
+ int y; /**< Position of node. */
+};
+
+/**
+ * History tree for a window.
+ */
+struct history {
+ /** First page in tree (page that window opened with). */
+ struct history_entry *start;
+ /** Current position in tree. */
+ struct history_entry *current;
+ /** Width of layout. */
+ int width;
+ /** Height of layout. */
+ int height;
+};
-/** Browser window data. */
+/**
+ * Browser window data.
+ */
struct browser_window {
- /** Page currently displayed, or 0. Must have status READY or DONE. */
+ /**
+ * Content handle of page currently displayed which must have
+ * READY or DONE status or NULL for no content.
+ */
struct hlcache_handle *current_content;
- /** Page being loaded, or 0. */
+ /**
+ * Content handle of page in process of being loaded or NULL
+ * if no page is being loaded.
+ */
struct hlcache_handle *loading_content;
- /** Page Favicon */
- struct hlcache_handle *current_favicon;
- /** handle for favicon which we started loading early */
- struct hlcache_handle *loading_favicon;
- /** favicon fetch already failed - prevents infinite error looping */
- bool failed_favicon;
-
- /** Window history structure. */
+ /**
+ * Favicon
+ */
+ struct {
+ /**
+ * content handle of current page favicon
+ */
+ struct hlcache_handle *current;
+
+ /**
+ * content handle for favicon which we started loading
+ * early
+ */
+ struct hlcache_handle *loading;
+
+ /**
+ * flag to indicate favicon fetch already failed which
+ * prevents infinite error looping.
+ */
+ bool failed;
+ } favicon;
+
+ /** local history handle. */
struct history *history;
- /** Platform specific window data. */
+ /**
+ * Platform specific window data only valid at top level.
+ */
struct gui_window *window;
/** Busy indicator is active. */
@@ -65,23 +133,32 @@ struct browser_window {
/** Fragment identifier for current_content. */
lwc_string *frag_id;
- /** Current drag status. */
- browser_drag_type drag_type;
+ /**
+ * Current drag status.
+ *
+ * These values are only vald whle type is not DRAGGING_NONE
+ */
+ struct {
+ /** the type of drag in progress */
+ browser_drag_type type;
+
+ /** Current drag's browser window, when not in root bw. */
+ struct browser_window *window;
+
+ /** Mouse position at start of current scroll drag. */
+ int start_x;
+ int start_y;
- /** Current drag's browser window, when not in root bw. */
- struct browser_window *drag_window;
+ /** Scroll offsets at start of current scroll draw. */
+ int start_scroll_x;
+ int start_scroll_y;
- /** Mouse position at start of current scroll drag. */
- int drag_start_x;
- int drag_start_y;
- /** Scroll offsets at start of current scroll draw. */
- int drag_start_scroll_x;
- int drag_start_scroll_y;
- /** Frame resize directions for current frame resize drag. */
- unsigned int drag_resize_left : 1;
- unsigned int drag_resize_right : 1;
- unsigned int drag_resize_up : 1;
- unsigned int drag_resize_down : 1;
+ /** Frame resize directions for current frame resize drag. */
+ unsigned int resize_left : 1;
+ unsigned int resize_right : 1;
+ unsigned int resize_up : 1;
+ unsigned int resize_down : 1;
+ } drag;
/** Current fetch is download */
bool download;
@@ -156,14 +233,15 @@ struct browser_window {
struct jscontext *jsctx;
/** cache of the currently displayed status text. */
- char *status_text; /**< Current status bar text. */
- int status_text_len; /**< Length of the browser_window::status_text buffer. */
- int status_match; /**< Number of times an idempotent status-set operation was performed. */
- int status_miss; /**< Number of times status was really updated. */
+ struct {
+ char *text; /**< Current status bar text. */
+ int text_len; /**< Length of the status::text buffer. */
+ int match; /**< Number of times an idempotent status-set operation was performed. */
+ int miss; /**< Number of times status was really updated. */
+ } status;
};
-
/**
* Initialise common parts of a browser window
*
@@ -174,6 +252,7 @@ struct browser_window {
nserror browser_window_initialise_common(enum browser_window_create_flags flags,
struct browser_window *bw, struct browser_window *existing);
+
/**
* Get the dimensions of the area a browser window occupies
*
@@ -185,6 +264,7 @@ nserror browser_window_initialise_common(enum browser_window_create_flags flags,
void browser_window_get_dimensions(struct browser_window *bw,
int *width, int *height, bool scaled);
+
/**
* Update the extent of the inside of a browser window to that of the current
* content
@@ -193,6 +273,7 @@ void browser_window_get_dimensions(struct browser_window *bw,
*/
void browser_window_update_extent(struct browser_window *bw);
+
/**
* Change the status bar of a browser window.
*
@@ -201,6 +282,7 @@ void browser_window_update_extent(struct browser_window *bw);
*/
void browser_window_set_status(struct browser_window *bw, const char *text);
+
/**
* Get the root level browser window
*
@@ -209,4 +291,68 @@ void browser_window_set_status(struct browser_window *bw, const char *text);
*/
struct browser_window * browser_window_get_root(struct browser_window *bw);
+
+/**
+ * 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);
+
+/**
+ * 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);
+
+
+/**
+ * Insert a url into the history tree.
+ *
+ * \param bw browser window with history object
+ * \param content content to add to history
+ * \param frag_id fragment identifier, or NULL.
+ * \return NSERROR_OK or error code on faliure.
+ *
+ * The page is added after the current entry and becomes current.
+ */
+nserror browser_window_history_add(struct browser_window *bw,
+ struct hlcache_handle *content, lwc_string *frag_id);
+
+/**
+ * Update the thumbnail and scroll offsets for the current entry.
+ *
+ * \param bw The browser window to update the history within.
+ * \param content content for current entry
+ * \return NSERROR_OK or error code on faliure.
+ */
+nserror browser_window_history_update(struct browser_window *bw,
+ struct hlcache_handle *content);
+
+/**
+ * Retrieve the stored scroll offsets for the current history entry
+ *
+ * \param bw The browser window to retrieve scroll offsets for.
+ * \param sx Pointer to a float for the X scroll offset
+ * \param sy Pointer to a float for the Y scroll offset
+ * \return NSERROR_OK or error code on failure.
+ */
+nserror browser_window_history_get_scroll(struct browser_window *bw,
+ float *sx, float *sy);
+
+/**
+ * Free a history structure.
+ *
+ * \param bw The browser window to destroy the history within.
+ */
+void browser_window_history_destroy(struct browser_window *bw);
+
+
#endif
diff --git a/desktop/cookie_manager.c b/desktop/cookie_manager.c
index 5429f6864..a2aab8e9f 100644
--- a/desktop/cookie_manager.c
+++ b/desktop/cookie_manager.c
@@ -576,7 +576,9 @@ static nserror cookie_manager_init_entry_fields(void)
goto error;
}
- cm_ctx.fields[COOKIE_M_DOMAIN].flags = TREE_FLAG_SHOW_NAME;
+ cm_ctx.fields[COOKIE_M_DOMAIN].flags =
+ TREE_FLAG_SHOW_NAME |
+ TREE_FLAG_SEARCHABLE;
label = "TreeviewLabelDomain";
label = messages_get(label);
if (lwc_intern_string(label, strlen(label),
@@ -718,7 +720,8 @@ static void cookie_manager_delete_entry(struct cookie_manager_entry *e)
urldb_delete_cookie(domain, path, name);
} else {
- LOG("Delete cookie fail: ""need domain, path, and name.");
+ NSLOG(netsurf, INFO,
+ "Delete cookie fail: ""need domain, path, and name.");
}
}
@@ -788,7 +791,7 @@ nserror cookie_manager_init(struct core_window_callback_table *cw_t,
return err;
}
- LOG("Generating cookie manager data");
+ NSLOG(netsurf, INFO, "Generating cookie manager data");
/* Init. cookie manager treeview entry fields */
err = cookie_manager_init_entry_fields();
@@ -808,7 +811,9 @@ nserror cookie_manager_init(struct core_window_callback_table *cw_t,
err = treeview_create(&cm_ctx.tree, &cm_tree_cb_t,
COOKIE_M_N_FIELDS, cm_ctx.fields,
cw_t, core_window_handle,
- TREEVIEW_NO_MOVES | TREEVIEW_DEL_EMPTY_DIRS);
+ TREEVIEW_NO_MOVES |
+ TREEVIEW_DEL_EMPTY_DIRS |
+ TREEVIEW_SEARCHABLE);
if (err != NSERROR_OK) {
cm_ctx.tree = NULL;
return err;
@@ -825,7 +830,7 @@ nserror cookie_manager_init(struct core_window_callback_table *cw_t,
/* Inform client of window height */
treeview_get_height(cm_ctx.tree);
- LOG("Generated cookie manager data");
+ NSLOG(netsurf, INFO, "Generated cookie manager data");
return NSERROR_OK;
}
@@ -837,7 +842,7 @@ nserror cookie_manager_fini(void)
int i;
nserror err;
- LOG("Finalising cookie manager");
+ NSLOG(netsurf, INFO, "Finalising cookie manager");
cm_ctx.built = false;
@@ -860,7 +865,7 @@ nserror cookie_manager_fini(void)
return err;
}
- LOG("Finalised cookie manager");
+ NSLOG(netsurf, INFO, "Finalised cookie manager");
return err;
}
diff --git a/desktop/font_haru.c b/desktop/font_haru.c
index caa751bcb..4ee9824f0 100644
--- a/desktop/font_haru.c
+++ b/desktop/font_haru.c
@@ -74,7 +74,10 @@ const struct font_functions haru_nsfont = {
static void error_handler(HPDF_STATUS error_no, HPDF_STATUS detail_no,
void *user_data)
{
- LOG("ERROR: in font_haru \n\terror_no=%x\n\tdetail_no=%d\n", (HPDF_UINT)error_no, (HPDF_UINT)detail_no);
+ NSLOG(netsurf, INFO,
+ "ERROR: in font_haru \n\terror_no=%x\n\tdetail_no=%d\n",
+ (HPDF_UINT)error_no,
+ (HPDF_UINT)detail_no);
#ifdef FONT_HARU_DEBUG
exit(1);
#endif
@@ -143,7 +146,9 @@ bool haru_nsfont_width(const plot_font_style_t *fstyle,
*width = width_real;
#ifdef FONT_HARU_DEBUG
- LOG("Measuring string: %s ; Calculated width: %f %i", string_nt, width_real, *width);
+ NSLOG(netsurf, INFO,
+ "Measuring string: %s ; Calculated width: %f %i", string_nt,
+ width_real, *width);
#endif
free(string_nt);
HPDF_Free(pdf);
@@ -201,7 +206,11 @@ bool haru_nsfont_position_in_string(const plot_font_style_t *fstyle,
*actual_x = real_width;
#ifdef FONT_HARU_DEBUG
- LOG("Position in string: %s at x: %i; Calculated position: %i", string_nt, x, *char_offset);
+ NSLOG(netsurf, INFO,
+ "Position in string: %s at x: %i; Calculated position: %i",
+ string_nt,
+ x,
+ *char_offset);
#endif
free(string_nt);
HPDF_Free(pdf);
@@ -246,7 +255,12 @@ bool haru_nsfont_split(const plot_font_style_t *fstyle,
HPDF_TRUE, &real_width);
#ifdef FONT_HARU_DEBUG
- LOG("Splitting string: %s for width: %i ; Calculated position: %i Calculated real_width: %f", string_nt, x, *char_offset, real_width);
+ NSLOG(netsurf, INFO,
+ "Splitting string: %s for width: %i ; Calculated position: %i Calculated real_width: %f",
+ string_nt,
+ x,
+ *char_offset,
+ real_width);
#endif
*char_offset = offset - 1;
@@ -327,7 +341,7 @@ bool haru_nsfont_apply_style(const plot_font_style_t *fstyle,
strcat(font_name, "-Roman");
#ifdef FONT_HARU_DEBUG
- LOG("Setting font: %s", font_name);
+ NSLOG(netsurf, INFO, "Setting font: %s", font_name);
#endif
size = fstyle->size;
@@ -338,7 +352,7 @@ bool haru_nsfont_apply_style(const plot_font_style_t *fstyle,
if (size <= 0)
return true;
- size /= FONT_SIZE_SCALE;
+ size /= PLOT_STYLE_SCALE;
if (size > HPDF_MAX_FONTSIZE)
size = HPDF_MAX_FONTSIZE;
diff --git a/desktop/frames.c b/desktop/frames.c
index 70e51e754..ebc54c6d5 100644
--- a/desktop/frames.c
+++ b/desktop/frames.c
@@ -33,8 +33,8 @@
#include "utils/utils.h"
#include "netsurf/content.h"
#include "content/hlcache.h"
-#include "render/html.h"
-#include "render/box.h"
+#include "html/html.h"
+#include "html/box.h"
#include "desktop/browser_private.h"
#include "desktop/frames.h"
@@ -354,9 +354,11 @@ nserror browser_window_create_frameset(struct browser_window *bw,
window->parent = bw;
if (window->name)
- LOG("Created frame '%s'", window->name);
+ NSLOG(netsurf, INFO, "Created frame '%s'",
+ window->name);
else
- LOG("Created frame (unnamed)");
+ NSLOG(netsurf, INFO,
+ "Created frame (unnamed)");
}
}
@@ -675,25 +677,31 @@ void browser_window_resize_frame(struct browser_window *bw, int x, int y)
assert((col >= 0) && (row >= 0));
sibling = NULL;
- if (bw->drag_resize_left)
+ if (bw->drag.resize_left) {
sibling = &parent->children[row * parent->cols + (col - 1)];
- else if (bw->drag_resize_right)
+ } else if (bw->drag.resize_right) {
sibling = &parent->children[row * parent->cols + (col + 1)];
- if (sibling)
+ }
+ if (sibling) {
change |= browser_window_resolve_frame_dimension(bw, sibling,
x, y, true, false);
+ }
sibling = NULL;
- if (bw->drag_resize_up)
+ if (bw->drag.resize_up) {
sibling = &parent->children[(row - 1) * parent->cols + col];
- else if (bw->drag_resize_down)
+ } else if (bw->drag.resize_down) {
sibling = &parent->children[(row + 1) * parent->cols + col];
- if (sibling)
+ }
+
+ if (sibling) {
change |= browser_window_resolve_frame_dimension(bw, sibling,
x, y, false, true);
+ }
- if (change)
+ if (change) {
browser_window_recalculate_frameset(parent);
+ }
}
@@ -711,20 +719,22 @@ bool browser_window_resolve_frame_dimension(struct browser_window *bw,
/* extend/shrink the box to the pointer */
if (width) {
- if (bw->drag_resize_left)
+ if (bw->drag.resize_left) {
bw_dimension = bw->x + bw->width - x;
- else
+ } else {
bw_dimension = x - bw->x;
+ }
bw_pixels = bw->width;
sibling_pixels = sibling->width;
bw_d = &bw->frame_width;
sibling_d = &sibling->frame_width;
frame_size = bw->parent->width;
} else {
- if (bw->drag_resize_up)
+ if (bw->drag.resize_up) {
bw_dimension = bw->y + bw->height - y;
- else
+ } else {
bw_dimension = y - bw->y;
+ }
bw_pixels = bw->height;
sibling_pixels = sibling->height;
bw_d = &bw->frame_height;
@@ -919,12 +929,12 @@ static bool browser_window_resize_frames(struct browser_window *bw,
* front end to clamp pointer range */
browser_window_set_drag_type(bw,
DRAGGING_FRAME, NULL);
- bw->drag_start_x = x;
- bw->drag_start_y = y;
- bw->drag_resize_left = left;
- bw->drag_resize_right = right;
- bw->drag_resize_up = up;
- bw->drag_resize_down = down;
+ bw->drag.start_x = x;
+ bw->drag.start_y = y;
+ bw->drag.resize_left = left;
+ bw->drag.resize_right = right;
+ bw->drag.resize_up = up;
+ bw->drag.resize_down = down;
}
return true;
}
diff --git a/desktop/global_history.c b/desktop/global_history.c
index a19349f51..ad39a3e41 100644
--- a/desktop/global_history.c
+++ b/desktop/global_history.c
@@ -536,7 +536,9 @@ static nserror global_history_initialise_entry_fields(void)
goto error;
}
- gh_ctx.fields[GH_URL].flags = TREE_FLAG_COPY_TEXT;
+ gh_ctx.fields[GH_URL].flags =
+ TREE_FLAG_COPY_TEXT |
+ TREE_FLAG_SEARCHABLE;
label = "TreeviewLabelURL";
label = messages_get(label);
if (lwc_intern_string(label, strlen(label),
@@ -596,7 +598,7 @@ static nserror global_history_initialise_time(void)
/* get the current time */
t = time(NULL);
if (t == -1) {
- LOG("time info unaviable");
+ NSLOG(netsurf, INFO, "time info unaviable");
return NSERROR_UNKNOWN;
}
@@ -607,7 +609,7 @@ static nserror global_history_initialise_time(void)
full_time->tm_hour = 0;
t = mktime(full_time);
if (t == -1) {
- LOG("mktime failed");
+ NSLOG(netsurf, INFO, "mktime failed");
return NSERROR_UNKNOWN;
}
@@ -729,7 +731,7 @@ nserror global_history_init(struct core_window_callback_table *cw_t,
return err;
}
- LOG("Loading global history");
+ NSLOG(netsurf, INFO, "Loading global history");
/* Init. global history treeview time */
err = global_history_initialise_time();
@@ -752,7 +754,8 @@ nserror global_history_init(struct core_window_callback_table *cw_t,
err = treeview_create(&gh_ctx.tree, &gh_tree_cb_t,
N_FIELDS, gh_ctx.fields,
cw_t, core_window_handle,
- TREEVIEW_NO_MOVES | TREEVIEW_DEL_EMPTY_DIRS);
+ TREEVIEW_NO_MOVES | TREEVIEW_DEL_EMPTY_DIRS |
+ TREEVIEW_SEARCHABLE);
if (err != NSERROR_OK) {
gh_ctx.tree = NULL;
return err;
@@ -785,7 +788,7 @@ nserror global_history_init(struct core_window_callback_table *cw_t,
/* Inform client of window height */
treeview_get_height(gh_ctx.tree);
- LOG("Loaded global history");
+ NSLOG(netsurf, INFO, "Loaded global history");
return NSERROR_OK;
}
@@ -797,7 +800,7 @@ nserror global_history_fini(void)
int i;
nserror err;
- LOG("Finalising global history");
+ NSLOG(netsurf, INFO, "Finalising global history");
gh_ctx.built = false;
@@ -815,7 +818,7 @@ nserror global_history_fini(void)
return err;
}
- LOG("Finalised global history");
+ NSLOG(netsurf, INFO, "Finalised global history");
return err;
}
@@ -832,7 +835,8 @@ nserror global_history_add(nsurl *url)
data = urldb_get_url_data(url);
if (data == NULL) {
- LOG("Can't add URL to history that's not present in urldb.");
+ NSLOG(netsurf, INFO,
+ "Can't add URL to history that's not present in urldb.");
return NSERROR_BAD_PARAMETER;
}
diff --git a/desktop/gui_factory.c b/desktop/gui_factory.c
index 88bb9baf5..ca9eff1da 100644
--- a/desktop/gui_factory.c
+++ b/desktop/gui_factory.c
@@ -82,12 +82,6 @@ static void gui_default_window_set_icon(struct gui_window *g,
{
}
-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)
{
@@ -161,10 +155,7 @@ static nserror verify_window_register(struct gui_window_table *gwt)
if (gwt->destroy == NULL) {
return NSERROR_BAD_PARAMETER;
}
- if (gwt->redraw == NULL) {
- return NSERROR_BAD_PARAMETER;
- }
- if (gwt->update == NULL) {
+ if (gwt->invalidate == NULL) {
return NSERROR_BAD_PARAMETER;
}
if (gwt->get_scroll == NULL) {
@@ -179,9 +170,6 @@ static nserror verify_window_register(struct gui_window_table *gwt)
if (gwt->update_extent == NULL) {
return NSERROR_BAD_PARAMETER;
}
- if (gwt->reformat == NULL) {
- return NSERROR_BAD_PARAMETER;
- }
/* fill in the optional entries with defaults */
@@ -218,9 +206,6 @@ static nserror verify_window_register(struct gui_window_table *gwt)
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;
}
diff --git a/desktop/hotlist.c b/desktop/hotlist.c
index 78473c744..4bdd7c8cb 100644
--- a/desktop/hotlist.c
+++ b/desktop/hotlist.c
@@ -62,6 +62,8 @@ struct hotlist_ctx {
struct treeview_field_desc fields[HL_N_FIELDS];
bool built;
struct hotlist_folder *default_folder;
+ char *save_path;
+ bool save_scheduled;
};
struct hotlist_ctx hl_ctx;
@@ -73,6 +75,113 @@ struct hotlist_entry {
};
+/*
+ * Get path for writing hotlist to
+ *
+ * \param path The final path of the hotlist
+ * \param loaded Updated to the path to write the holist to
+ * \return NSERROR_OK on success, or appropriate error otherwise
+ */
+static nserror hotlist_get_temp_path(const char *path, char **temp_path)
+{
+ const char *extension = "-bk";
+ char *joined;
+ int len;
+
+ len = strlen(path) + strlen(extension);
+
+ joined = malloc(len + 1);
+ if (joined == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ if (snprintf(joined, len + 1, "%s%s", path, extension) != len) {
+ free(joined);
+ return NSERROR_UNKNOWN;
+ }
+
+ *temp_path = joined;
+ return NSERROR_OK;
+}
+
+
+/* Save the hotlist to to a file at the given path
+ *
+ * \param path Path to save hotlist file to. NULL path is a no-op.
+ * \return NSERROR_OK on success, or appropriate error otherwise
+ */
+static nserror hotlist_save(const char *path)
+{
+ nserror res = NSERROR_OK;
+ char *temp_path;
+
+ /* NULL path is a no-op. */
+ if (path == NULL) {
+ return NSERROR_OK;
+ }
+
+ /* Get path to export to */
+ res = hotlist_get_temp_path(path, &temp_path);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ /* Export to temp path */
+ res = hotlist_export(temp_path, NULL);
+ if (res != NSERROR_OK) {
+ goto cleanup;
+ }
+
+ /* Remove old hotlist to handle non-POSIX rename() implementations. */
+ (void)remove(path);
+
+ /* Replace any old hotlist file with the one we just saved */
+ if (rename(temp_path, path) != 0) {
+ res = NSERROR_SAVE_FAILED;
+ NSLOG(netsurf, INFO, "Error renaming hotlist: %s.",
+ strerror(errno));
+ goto cleanup;
+ }
+
+cleanup:
+ free(temp_path);
+
+ return res;
+}
+
+
+/**
+ * Scheduler callback for saving the hotlist.
+ *
+ * \param p Unused user data.
+ */
+static void hotlist_schedule_save_cb(void *p)
+{
+ hl_ctx.save_scheduled = false;
+ hotlist_save(hl_ctx.save_path);
+}
+
+
+/**
+ * Schedule a hotlist save.
+ *
+ * \return NSERROR_OK on success, or appropriate error otherwise
+ */
+static nserror hotlist_schedule_save(void)
+{
+ if (hl_ctx.save_scheduled == false && hl_ctx.save_path != NULL) {
+ nserror err = guit->misc->schedule(10 * 1000,
+ hotlist_schedule_save_cb, NULL);
+ if (err != NSERROR_OK) {
+ return err;
+ }
+ hl_ctx.save_scheduled = true;
+ }
+
+ return NSERROR_OK;
+}
+
+
/**
* Set a hotlist entry's data from the url_data.
*
@@ -436,6 +545,8 @@ hotlist_tree_node_entry_cb(struct treeview_node_msg msg, void *data)
case TREE_MSG_NODE_DELETE:
e->entry = NULL;
hotlist_delete_entry_internal(e);
+
+ err = hotlist_schedule_save();
break;
case TREE_MSG_NODE_EDIT:
@@ -459,6 +570,8 @@ hotlist_tree_node_entry_cb(struct treeview_node_msg msg, void *data)
free((void *)old_text);
}
+ err = hotlist_schedule_save();
+
} else if (lwc_string_isequal(hl_ctx.fields[HL_URL].field,
msg.data.node_edit.field, &match) ==
lwc_error_ok && match == true &&
@@ -476,6 +589,8 @@ hotlist_tree_node_entry_cb(struct treeview_node_msg msg, void *data)
treeview_update_node_entry(hl_ctx.tree,
e->entry, e->data, e);
nsurl_unref(old_url);
+
+ err = hotlist_schedule_save();
}
}
break;
@@ -538,20 +653,20 @@ static nserror hotlist_load_entry(dom_node *li, hotlist_load_ctx *ctx)
/* The li must contain an "a" element */
a = libdom_find_first_element(li, corestring_lwc_a);
if (a == NULL) {
- LOG("Missing <a> in <li>");
+ NSLOG(netsurf, INFO, "Missing <a> in <li>");
return NSERROR_INVALID;
}
derror = dom_node_get_text_content(a, &title1);
if (derror != DOM_NO_ERR) {
- LOG("No title");
+ NSLOG(netsurf, INFO, "No title");
dom_node_unref(a);
return NSERROR_INVALID;
}
derror = dom_element_get_attribute(a, corestring_dom_href, &url1);
if (derror != DOM_NO_ERR || url1 == NULL) {
- LOG("No URL");
+ NSLOG(netsurf, INFO, "No URL");
dom_string_unref(title1);
dom_node_unref(a);
return NSERROR_INVALID;
@@ -569,7 +684,8 @@ static nserror hotlist_load_entry(dom_node *li, hotlist_load_ctx *ctx)
dom_string_unref(url1);
if (err != NSERROR_OK) {
- LOG("Failed normalising '%s'", dom_string_data(url1));
+ NSLOG(netsurf, INFO, "Failed normalising '%s'",
+ dom_string_data(url1));
if (title1 != NULL) {
dom_string_unref(title1);
@@ -596,7 +712,7 @@ static nserror hotlist_load_entry(dom_node *li, hotlist_load_ctx *ctx)
/*
- * Callback for libdom_iterate_child_elements, which dispite the namespace is
+ * Callback for libdom_iterate_child_elements, which despite the namespace is
* a NetSurf function.
*
* \param node Node that is a child of the directory UL node
@@ -649,7 +765,8 @@ nserror hotlist_load_directory_cb(dom_node *node, void *ctx)
error = dom_node_get_text_content(node, &title);
if (error != DOM_NO_ERR || title == NULL) {
- LOG("Empty <h4> or memory exhausted.");
+ NSLOG(netsurf, INFO,
+ "Empty <h4> or memory exhausted.");
dom_string_unref(name);
return NSERROR_DOM;
}
@@ -729,36 +846,6 @@ nserror hotlist_load_directory_cb(dom_node *node, void *ctx)
/*
- * Get path for writing hotlist to
- *
- * \param path The final path of the hotlist
- * \param loaded Updated to the path to write the holist to
- * \return NSERROR_OK on success, or appropriate error otherwise
- */
-static nserror hotlist_get_temp_path(const char *path, char **temp_path)
-{
- const char *extension = "-bk";
- char *joined;
- int len;
-
- len = strlen(path) + strlen(extension);
-
- joined = malloc(len + 1);
- if (joined == NULL) {
- return NSERROR_NOMEM;
- }
-
- if (snprintf(joined, len + 1, "%s%s", path, extension) != len) {
- free(joined);
- return NSERROR_UNKNOWN;
- }
-
- *temp_path = joined;
- return NSERROR_OK;
-}
-
-
-/*
* Load the hotlist data from file
*
* \param path The path to load the hotlist file from, or NULL
@@ -777,7 +864,7 @@ static nserror hotlist_load(const char *path, bool *loaded)
/* Handle no path */
if (path == NULL) {
- LOG("No hotlist file path provided.");
+ NSLOG(netsurf, INFO, "No hotlist file path provided.");
return NSERROR_OK;
}
@@ -918,45 +1005,6 @@ static nserror hotlist_generate(void)
}
-/* Save the hotlist to to a file at the given path
- *
- * \param path Path to save hostlist file to.
- * \return NSERROR_OK on success, or appropriate error otherwise
- */
-static nserror hotlist_save(const char *path)
-{
- nserror res = NSERROR_OK;
- char *temp_path;
-
- /* Get path to export to */
- res = hotlist_get_temp_path(path, &temp_path);
- if (res != NSERROR_OK) {
- return res;
- }
-
- /* Export to temp path */
- res = hotlist_export(temp_path, NULL);
- if (res != NSERROR_OK) {
- goto cleanup;
- }
-
- /* Remove old hotlist to handle non-POSIX rename() implementations. */
- (void)remove(path);
-
- /* Replace any old hotlist file with the one we just saved */
- if (rename(temp_path, path) != 0) {
- res = NSERROR_SAVE_FAILED;
- LOG("Error renaming hotlist: %s.", strerror(errno));
- goto cleanup;
- }
-
-cleanup:
- free(temp_path);
-
- return res;
-}
-
-
struct treeview_export_walk_ctx {
FILE *fp;
};
@@ -1150,8 +1198,10 @@ static nserror hotlist_initialise_entry_fields(void)
goto error;
}
- hl_ctx.fields[HL_URL].flags = TREE_FLAG_ALLOW_EDIT |
- TREE_FLAG_COPY_TEXT;
+ hl_ctx.fields[HL_URL].flags =
+ TREE_FLAG_ALLOW_EDIT |
+ TREE_FLAG_COPY_TEXT |
+ TREE_FLAG_SEARCHABLE;
label = "TreeviewLabelURL";
label = messages_get(label);
if (lwc_intern_string(label, strlen(label),
@@ -1227,7 +1277,9 @@ static nserror hotlist_populate(const char *path)
/* Exported interface, documented in hotlist.h */
-nserror hotlist_init(const char *path)
+nserror hotlist_init(
+ const char *load_path,
+ const char *save_path)
{
nserror err;
@@ -1236,15 +1288,26 @@ nserror hotlist_init(const char *path)
return err;
}
- LOG("Loading hotlist");
+ NSLOG(netsurf, INFO, "Loading hotlist");
hl_ctx.tree = NULL;
hl_ctx.built = false;
hl_ctx.default_folder = NULL;
+ /* Store the save path */
+ if (save_path != NULL) {
+ hl_ctx.save_path = strdup(save_path);
+ if (hl_ctx.save_path == NULL) {
+ return NSERROR_NOMEM;
+ }
+ } else {
+ hl_ctx.save_path = NULL;
+ }
+
/* Init. hotlist treeview entry fields */
err = hotlist_initialise_entry_fields();
if (err != NSERROR_OK) {
+ free(hl_ctx.save_path);
hl_ctx.tree = NULL;
return err;
}
@@ -1252,15 +1315,17 @@ nserror hotlist_init(const char *path)
/* Create the hotlist treeview */
err = treeview_create(&hl_ctx.tree, &hl_tree_cb_t,
HL_N_FIELDS, hl_ctx.fields, NULL, NULL,
- TREEVIEW_NO_FLAGS);
+ TREEVIEW_SEARCHABLE);
if (err != NSERROR_OK) {
+ free(hl_ctx.save_path);
hl_ctx.tree = NULL;
return err;
}
/* Populate the hotlist */
- err = hotlist_populate(path);
+ err = hotlist_populate(load_path);
if (err != NSERROR_OK) {
+ free(hl_ctx.save_path);
return err;
}
@@ -1269,7 +1334,7 @@ nserror hotlist_init(const char *path)
* the treeview is built. */
hl_ctx.built = true;
- LOG("Loaded hotlist");
+ NSLOG(netsurf, INFO, "Loaded hotlist");
return NSERROR_OK;
}
@@ -1310,19 +1375,25 @@ nserror hotlist_manager_fini(void)
/* Exported interface, documented in hotlist.h */
-nserror hotlist_fini(const char *path)
+nserror hotlist_fini(void)
{
int i;
nserror err;
- LOG("Finalising hotlist");
+ NSLOG(netsurf, INFO, "Finalising hotlist");
+
+ /* Remove any existing scheduled save callback */
+ guit->misc->schedule(-1, hotlist_schedule_save_cb, NULL);
+ hl_ctx.save_scheduled = false;
/* Save the hotlist */
- err = hotlist_save(path);
+ err = hotlist_save(hl_ctx.save_path);
if (err != NSERROR_OK) {
- LOG("Problem saving the hotlist.");
+ NSLOG(netsurf, INFO, "Problem saving the hotlist.");
}
+ free(hl_ctx.save_path);
+
/* Destroy the hotlist treeview */
err = treeview_destroy(hl_ctx.tree);
hl_ctx.built = false;
@@ -1337,7 +1408,7 @@ nserror hotlist_fini(const char *path)
return err;
}
- LOG("Finalised hotlist");
+ NSLOG(netsurf, INFO, "Finalised hotlist");
return err;
}
@@ -1380,7 +1451,7 @@ nserror hotlist_add_url(nsurl *url)
if (err != NSERROR_OK)
return err;
- return NSERROR_OK;
+ return hotlist_schedule_save();
}
diff --git a/desktop/hotlist.h b/desktop/hotlist.h
index c77ac92d2..571f4de97 100644
--- a/desktop/hotlist.h
+++ b/desktop/hotlist.h
@@ -40,10 +40,16 @@ struct rect;
* be called before URLs can be added to the hotlist, and before the
* hotlist can be queried to ask if URLs are present in the hotlist.
*
- * \param path The path to hotlist file to load
+ * In read-only mode the hotlist can be modified, but changes will not
+ * persist over sessions.
+ *
+ * \param load_path The path to load hotlist from.
+ * \param save_path The path to save hotlist to, or NULL for read-only mode.
* \return NSERROR_OK on success, appropriate error otherwise
*/
-nserror hotlist_init(const char *path);
+nserror hotlist_init(
+ const char *load_path,
+ const char *save_path);
/**
* Initialise the hotlist manager.
@@ -67,7 +73,6 @@ nserror hotlist_manager_init(struct core_window_callback_table *cw_t,
* allowing destruction of a GUI hotlist window, without finalising the
* hotlist module.
*
- * \param path The path to save hotlist to
* \return NSERROR_OK on success, appropriate error otherwise
*/
nserror hotlist_manager_fini(void);
@@ -79,10 +84,9 @@ nserror hotlist_manager_fini(void);
* internal data. After calling this if hotlist is required again,
* hotlist_init must be called.
*
- * \param path The path to save hotlist to
* \return NSERROR_OK on success, appropriate error otherwise
*/
-nserror hotlist_fini(const char *path);
+nserror hotlist_fini(void);
/**
* Add an entry to the hotlist for given URL.
diff --git a/desktop/knockout.c b/desktop/knockout.c
index bcfc272eb..127a48cdb 100644
--- a/desktop/knockout.c
+++ b/desktop/knockout.c
@@ -16,8 +16,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- * Knockout rendering (implementation).
+/**
+ * \file
+ * Knockout rendering implementation.
*
* Knockout rendering is an optimisation which is particularly for
* unaccelerated screen redraw. It tries to avoid plotting the same area more
@@ -86,47 +87,6 @@
struct knockout_box;
struct knockout_entry;
-
-static void knockout_calculate(int x0, int y0, int x1, int y1, struct knockout_box *box);
-static bool knockout_plot_fill_recursive(struct knockout_box *box, plot_style_t *plot_style);
-static bool knockout_plot_bitmap_recursive(struct knockout_box *box,
- struct knockout_entry *entry);
-
-static bool knockout_plot_line(int x0, int y0, int x1, int y1, const plot_style_t *pstyle);
-static bool knockout_plot_polygon(const int *p, unsigned int n, const plot_style_t *pstyle);
-static bool knockout_plot_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *plot_style);
-static bool knockout_plot_clip(const struct rect *clip);
-static bool knockout_plot_text(int x, int y, const char *text, size_t length,
- const plot_font_style_t *fstyle);
-static bool knockout_plot_disc(int x, int y, int radius, const plot_style_t *pstyle);
-static bool knockout_plot_arc(int x, int y, int radius, int angle1, int angle2, const plot_style_t *pstyle);
-static bool knockout_plot_bitmap(int x, int y, int width, int height,
- struct bitmap *bitmap, colour bg,
- bitmap_flags_t flags);
-static bool knockout_plot_flush(void);
-static bool knockout_plot_group_start(const char *name);
-static bool knockout_plot_group_end(void);
-static bool knockout_plot_path(const float *p, unsigned int n, colour fill,
- float width, colour c, const float transform[6]);
-
-
-const struct plotter_table knockout_plotters = {
- .rectangle = knockout_plot_rectangle,
- .line = knockout_plot_line,
- .polygon = knockout_plot_polygon,
- .clip = knockout_plot_clip,
- .text = knockout_plot_text,
- .disc = knockout_plot_disc,
- .arc = knockout_plot_arc,
- .bitmap = knockout_plot_bitmap,
- .group_start = knockout_plot_group_start,
- .group_end = knockout_plot_group_end,
- .flush = knockout_plot_flush,
- .path = knockout_plot_path,
- .option_knockout = true,
-};
-
-
typedef enum {
KNOCKOUT_PLOT_RECTANGLE,
KNOCKOUT_PLOT_LINE,
@@ -155,17 +115,11 @@ struct knockout_entry {
struct knockout_box *box; /* relating series of knockout clips */
union {
struct {
- int x0;
- int y0;
- int x1;
- int y1;
+ struct rect r;
plot_style_t plot_style;
} rectangle;
struct {
- int x0;
- int y0;
- int x1;
- int y1;
+ struct rect l;
plot_style_t plot_style;
} line;
struct {
@@ -174,10 +128,7 @@ struct knockout_entry {
plot_style_t plot_style;
} polygon;
struct {
- int x0;
- int y0;
- int x1;
- int y1;
+ struct rect r;
plot_style_t plot_style;
} fill;
struct rect clip;
@@ -231,166 +182,193 @@ static struct plotter_table real_plot;
static struct rect clip_cur;
static int nested_depth = 0;
+
/**
- * Start a knockout plotting session
- *
- * \param ctx the redraw context with real plotter table
- * \param knk_ctx updated to copy of ctx, with plotter table replaced
- * \return true on success, false otherwise
+ * fill an area recursively
*/
-bool knockout_plot_start(const struct redraw_context *ctx,
- struct redraw_context *knk_ctx)
+static nserror
+knockout_plot_fill_recursive(const struct redraw_context *ctx,
+ struct knockout_box *box,
+ plot_style_t *plot_style)
{
- /* check if we're recursing */
- if (nested_depth++ > 0) {
- /* we should already have the knockout renderer as default */
- assert(ctx->plot->rectangle == knockout_plotters.rectangle);
- *knk_ctx = *ctx;
- return true;
- }
-
- /* end any previous sessions */
- if (knockout_entry_cur > 0)
- knockout_plot_end();
-
- /* get copy of real plotter table */
- real_plot = *(ctx->plot);
+ struct knockout_box *parent;
+ nserror res;
+ nserror ffres = NSERROR_OK; /* first failing result */
- /* set up knockout rendering context */
- *knk_ctx = *ctx;
- knk_ctx->plot = &knockout_plotters;
- return true;
+ for (parent = box; parent; parent = parent->next) {
+ if (parent->deleted)
+ continue;
+ if (parent->child) {
+ res = knockout_plot_fill_recursive(ctx,
+ parent->child,
+ plot_style);
+ } else {
+ res = real_plot.rectangle(ctx, plot_style, &parent->bbox);
+ }
+ /* remember the first error */
+ if ((res != NSERROR_OK) && (ffres == NSERROR_OK)) {
+ ffres = res;
+ }
+ }
+ return ffres;
}
/**
- * End a knockout plotting session
- *
- * \return true on success, false otherwise
+ * bitmap plot recusivley
*/
-bool knockout_plot_end(void)
+static nserror
+knockout_plot_bitmap_recursive(const struct redraw_context *ctx,
+ struct knockout_box *box,
+ struct knockout_entry *entry)
{
- /* only output when we've finished any nesting */
- if (--nested_depth == 0)
- return knockout_plot_flush();
+ nserror res;
+ nserror ffres = NSERROR_OK; /* first failing result */
+ struct knockout_box *parent;
- assert(nested_depth > 0);
- return true;
-}
+ for (parent = box; parent; parent = parent->next) {
+ if (parent->deleted)
+ continue;
+ if (parent->child) {
+ res = knockout_plot_bitmap_recursive(ctx,
+ parent->child,
+ entry);
+ } else {
+ real_plot.clip(ctx, &parent->bbox);
+ res = real_plot.bitmap(ctx,
+ entry->data.bitmap.bitmap,
+ entry->data.bitmap.x,
+ entry->data.bitmap.y,
+ entry->data.bitmap.width,
+ entry->data.bitmap.height,
+ entry->data.bitmap.bg,
+ entry->data.bitmap.flags);
+ }
+ /* remember the first error */
+ if ((res != NSERROR_OK) && (ffres == NSERROR_OK)) {
+ ffres = res;
+ }
+ }
+ return ffres;
+}
/**
* Flush the current knockout session to empty the buffers
*
* \return true on success, false otherwise
*/
-bool knockout_plot_flush(void)
+static nserror knockout_plot_flush(const struct redraw_context *ctx)
{
int i;
- bool success = true;
struct knockout_box *box;
+ nserror res = NSERROR_OK; /* operation result */
+ nserror ffres = NSERROR_OK; /* first failing result */
/* debugging information */
#ifdef KNOCKOUT_DEBUG
- LOG("Entries are %i/%i, %i/%i, %i/%i", knockout_entry_cur, KNOCKOUT_ENTRIES, knockout_box_cur, KNOCKOUT_BOXES, knockout_polygon_cur, KNOCKOUT_POLYGONS);
+ NSLOG(netsurf, INFO, "Entries are %i/%i, %i/%i, %i/%i",
+ knockout_entry_cur, KNOCKOUT_ENTRIES, knockout_box_cur,
+ KNOCKOUT_BOXES, knockout_polygon_cur, KNOCKOUT_POLYGONS);
#endif
for (i = 0; i < knockout_entry_cur; i++) {
switch (knockout_entries[i].type) {
case KNOCKOUT_PLOT_RECTANGLE:
- success &= real_plot.rectangle(
- knockout_entries[i].data.rectangle.x0,
- knockout_entries[i].data.rectangle.y0,
- knockout_entries[i].data.rectangle.x1,
- knockout_entries[i].data.rectangle.y1,
- &knockout_entries[i].data.rectangle.plot_style);
+ res = real_plot.rectangle(ctx,
+ &knockout_entries[i].data.rectangle.plot_style,
+ &knockout_entries[i].data.rectangle.r);
break;
+
case KNOCKOUT_PLOT_LINE:
- success &= real_plot.line(
- knockout_entries[i].data.line.x0,
- knockout_entries[i].data.line.y0,
- knockout_entries[i].data.line.x1,
- knockout_entries[i].data.line.y1,
- &knockout_entries[i].data.line.plot_style);
+ res = real_plot.line(ctx,
+ &knockout_entries[i].data.line.plot_style,
+ &knockout_entries[i].data.line.l);
break;
+
case KNOCKOUT_PLOT_POLYGON:
- success &= real_plot.polygon(
- knockout_entries[i].data.polygon.p,
- knockout_entries[i].data.polygon.n,
- &knockout_entries[i].data.polygon.plot_style);
+ res = real_plot.polygon(ctx,
+ &knockout_entries[i].data.polygon.plot_style,
+ knockout_entries[i].data.polygon.p,
+ knockout_entries[i].data.polygon.n);
break;
+
case KNOCKOUT_PLOT_FILL:
box = knockout_entries[i].box->child;
- if (box)
- success &= knockout_plot_fill_recursive(box,
- &knockout_entries[i].data.fill.plot_style);
- else if (!knockout_entries[i].box->deleted)
- success &= real_plot.rectangle(
- knockout_entries[i].data.fill.x0,
- knockout_entries[i].data.fill.y0,
- knockout_entries[i].data.fill.x1,
- knockout_entries[i].data.fill.y1,
- &knockout_entries[i].data.fill.plot_style);
+ if (box) {
+ res = knockout_plot_fill_recursive(ctx,
+ box,
+ &knockout_entries[i].data.fill.plot_style);
+ } else if (!knockout_entries[i].box->deleted) {
+ res = real_plot.rectangle(ctx,
+ &knockout_entries[i].data.fill.plot_style,
+ &knockout_entries[i].data.fill.r);
+ }
break;
+
case KNOCKOUT_PLOT_CLIP:
- success &= real_plot.clip(
- &knockout_entries[i].data.clip);
+ res = real_plot.clip(ctx, &knockout_entries[i].data.clip);
break;
+
case KNOCKOUT_PLOT_TEXT:
- success &= real_plot.text(
+ res = real_plot.text(ctx,
+ &knockout_entries[i].data.text.font_style,
knockout_entries[i].data.text.x,
knockout_entries[i].data.text.y,
knockout_entries[i].data.text.text,
- knockout_entries[i].data.text.length,
- &knockout_entries[i].data.text.font_style);
+ knockout_entries[i].data.text.length);
break;
+
case KNOCKOUT_PLOT_DISC:
- success &= real_plot.disc(
+ res = real_plot.disc(ctx,
+ &knockout_entries[i].data.disc.plot_style,
knockout_entries[i].data.disc.x,
knockout_entries[i].data.disc.y,
- knockout_entries[i].data.disc.radius,
- &knockout_entries[i].data.disc.plot_style);
+ knockout_entries[i].data.disc.radius);
break;
+
case KNOCKOUT_PLOT_ARC:
- success &= real_plot.arc(
+ res = real_plot.arc(ctx,
+ &knockout_entries[i].data.arc.plot_style,
knockout_entries[i].data.arc.x,
knockout_entries[i].data.arc.y,
knockout_entries[i].data.arc.radius,
knockout_entries[i].data.arc.angle1,
- knockout_entries[i].data.arc.angle2,
- &knockout_entries[i].data.arc.plot_style);
+ knockout_entries[i].data.arc.angle2);
break;
+
case KNOCKOUT_PLOT_BITMAP:
box = knockout_entries[i].box->child;
if (box) {
- success &= knockout_plot_bitmap_recursive(box,
+ res = knockout_plot_bitmap_recursive(ctx,
+ box,
&knockout_entries[i]);
} else if (!knockout_entries[i].box->deleted) {
- success &= real_plot.bitmap(
- knockout_entries[i].data.
- bitmap.x,
- knockout_entries[i].data.
- bitmap.y,
- knockout_entries[i].data.
- bitmap.width,
- knockout_entries[i].data.
- bitmap.height,
- knockout_entries[i].data.
- bitmap.bitmap,
- knockout_entries[i].data.
- bitmap.bg,
- knockout_entries[i].data.
- bitmap.flags);
+ res = real_plot.bitmap(ctx,
+ knockout_entries[i].data.bitmap.bitmap,
+ knockout_entries[i].data.bitmap.x,
+ knockout_entries[i].data.bitmap.y,
+ knockout_entries[i].data.bitmap.width,
+ knockout_entries[i].data.bitmap.height,
+ knockout_entries[i].data.bitmap.bg,
+ knockout_entries[i].data.bitmap.flags);
}
break;
+
case KNOCKOUT_PLOT_GROUP_START:
- success &= real_plot.group_start(
- knockout_entries[i].data.group_start.name);
+ res = real_plot.group_start(ctx,
+ knockout_entries[i].data.group_start.name);
break;
+
case KNOCKOUT_PLOT_GROUP_END:
- success &= real_plot.group_end();
+ res = real_plot.group_end(ctx);
break;
}
+
+ /* remember the first error */
+ if ((res != NSERROR_OK) && (ffres == NSERROR_OK)) {
+ ffres = res;
+ }
}
knockout_entry_cur = 0;
@@ -398,20 +376,24 @@ bool knockout_plot_flush(void)
knockout_polygon_cur = 0;
knockout_list = NULL;
- return success;
+ return ffres;
}
/**
* Knockout a section of previous rendering
*
+ * \param ctx The current redraw context.
* \param x0 The left edge of the removal box
* \param y0 The bottom edge of the removal box
* \param x1 The right edge of the removal box
* \param y1 The top edge of the removal box
* \param owner The parent box set to consider, or NULL for top level
-*/
-void knockout_calculate(int x0, int y0, int x1, int y1, struct knockout_box *owner)
+ */
+static void
+knockout_calculate(const struct redraw_context *ctx,
+ int x0, int y0, int x1, int y1,
+ struct knockout_box *owner)
{
struct knockout_box *box;
struct knockout_box *parent;
@@ -464,11 +446,11 @@ void knockout_calculate(int x0, int y0, int x1, int y1, struct knockout_box *own
/* has the box been replaced by children? */
if (parent->child) {
- knockout_calculate(x0, y0, x1, y1, parent);
+ knockout_calculate(ctx, x0, y0, x1, y1, parent);
} else {
/* we need a maximum of 4 child boxes */
if (knockout_box_cur + 4 >= KNOCKOUT_BOXES) {
- knockout_plot_flush();
+ knockout_plot_flush(ctx);
return;
}
@@ -527,136 +509,138 @@ void knockout_calculate(int x0, int y0, int x1, int y1, struct knockout_box *own
}
-bool knockout_plot_fill_recursive(struct knockout_box *box, plot_style_t *plot_style)
-{
- bool success = true;
- struct knockout_box *parent;
-
- for (parent = box; parent; parent = parent->next) {
- if (parent->deleted)
- continue;
- if (parent->child)
- knockout_plot_fill_recursive(parent->child, plot_style);
- else
- success &= real_plot.rectangle(parent->bbox.x0,
- parent->bbox.y0,
- parent->bbox.x1,
- parent->bbox.y1,
- plot_style);
- }
- return success;
-}
-
-
-bool knockout_plot_bitmap_recursive(struct knockout_box *box,
- struct knockout_entry *entry)
-{
- bool success = true;
- struct knockout_box *parent;
-
- for (parent = box; parent; parent = parent->next) {
- if (parent->deleted)
- continue;
- if (parent->child)
- knockout_plot_bitmap_recursive(parent->child, entry);
- else {
- success &= real_plot.clip(&parent->bbox);
- success &= real_plot.bitmap(entry->data.bitmap.x,
- entry->data.bitmap.y,
- entry->data.bitmap.width,
- entry->data.bitmap.height,
- entry->data.bitmap.bitmap,
- entry->data.bitmap.bg,
- entry->data.bitmap.flags);
- }
- }
- return success;
-}
-
-bool knockout_plot_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *pstyle)
+/**
+ * knockout rectangle plotting.
+ *
+ * The rectangle can be filled an outline or both controlled
+ * by the plot style The line can be solid, dotted or
+ * dashed. Top left corner at (x0,y0) and rectangle has given
+ * width and height.
+ *
+ * \param ctx The current redraw context.
+ * \param pstyle Style controlling the rectangle plot.
+ * \param rect A rectangle defining the line to be drawn
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+knockout_plot_rectangle(const struct redraw_context *ctx,
+ const plot_style_t *pstyle,
+ const struct rect *rect)
{
int kx0, ky0, kx1, ky1;
+ nserror res = NSERROR_OK;
- if (pstyle->fill_type != PLOT_OP_TYPE_NONE) {
+ if (pstyle->fill_type != PLOT_OP_TYPE_NONE) {
/* filled draw */
/* get our bounds */
- kx0 = (x0 > clip_cur.x0) ? x0 : clip_cur.x0;
- ky0 = (y0 > clip_cur.y0) ? y0 : clip_cur.y0;
- kx1 = (x1 < clip_cur.x1) ? x1 : clip_cur.x1;
- ky1 = (y1 < clip_cur.y1) ? y1 : clip_cur.y1;
+ kx0 = (rect->x0 > clip_cur.x0) ? rect->x0 : clip_cur.x0;
+ ky0 = (rect->y0 > clip_cur.y0) ? rect->y0 : clip_cur.y0;
+ kx1 = (rect->x1 < clip_cur.x1) ? rect->x1 : clip_cur.x1;
+ ky1 = (rect->y1 < clip_cur.y1) ? rect->y1 : clip_cur.y1;
if ((kx0 > clip_cur.x1) || (kx1 < clip_cur.x0) ||
- (ky0 > clip_cur.y1) || (ky1 < clip_cur.y0))
- return true;
+ (ky0 > clip_cur.y1) || (ky1 < clip_cur.y0)) {
+ return NSERROR_OK;
+ }
/* fills both knock out and get knocked out */
- knockout_calculate(kx0, ky0, kx1, ky1, NULL);
- knockout_boxes[knockout_box_cur].bbox.x0 = x0;
- knockout_boxes[knockout_box_cur].bbox.y0 = y0;
- knockout_boxes[knockout_box_cur].bbox.x1 = x1;
- knockout_boxes[knockout_box_cur].bbox.y1 = y1;
+ knockout_calculate(ctx, kx0, ky0, kx1, ky1, NULL);
+ knockout_boxes[knockout_box_cur].bbox = *rect;
knockout_boxes[knockout_box_cur].deleted = false;
knockout_boxes[knockout_box_cur].child = NULL;
knockout_boxes[knockout_box_cur].next = knockout_list;
knockout_list = &knockout_boxes[knockout_box_cur];
knockout_entries[knockout_entry_cur].box = &knockout_boxes[knockout_box_cur];
- knockout_entries[knockout_entry_cur].data.fill.x0 = x0;
- knockout_entries[knockout_entry_cur].data.fill.y0 = y0;
- knockout_entries[knockout_entry_cur].data.fill.x1 = x1;
- knockout_entries[knockout_entry_cur].data.fill.y1 = y1;
+ knockout_entries[knockout_entry_cur].data.fill.r = *rect;
knockout_entries[knockout_entry_cur].data.fill.plot_style = *pstyle;
knockout_entries[knockout_entry_cur].data.fill.plot_style.stroke_type = PLOT_OP_TYPE_NONE; /* ensure we only plot the fill */
knockout_entries[knockout_entry_cur].type = KNOCKOUT_PLOT_FILL;
if ((++knockout_entry_cur >= KNOCKOUT_ENTRIES) ||
- (++knockout_box_cur >= KNOCKOUT_BOXES))
- knockout_plot_flush();
- }
+ (++knockout_box_cur >= KNOCKOUT_BOXES)) {
+ res = knockout_plot_flush(ctx);
+ }
+ }
if (pstyle->stroke_type != PLOT_OP_TYPE_NONE) {
/* draw outline */
- knockout_entries[knockout_entry_cur].data.rectangle.x0 = x0;
- knockout_entries[knockout_entry_cur].data.rectangle.y0 = y0;
- knockout_entries[knockout_entry_cur].data.rectangle.x1 = x1;
- knockout_entries[knockout_entry_cur].data.rectangle.y1 = y1;
+ knockout_entries[knockout_entry_cur].data.rectangle.r = *rect;
knockout_entries[knockout_entry_cur].data.fill.plot_style = *pstyle;
knockout_entries[knockout_entry_cur].data.fill.plot_style.fill_type = PLOT_OP_TYPE_NONE; /* ensure we only plot the outline */
knockout_entries[knockout_entry_cur].type = KNOCKOUT_PLOT_RECTANGLE;
- if (++knockout_entry_cur >= KNOCKOUT_ENTRIES)
- knockout_plot_flush();
- }
- return true;
+ if (++knockout_entry_cur >= KNOCKOUT_ENTRIES) {
+ res = knockout_plot_flush(ctx);
+ }
+ }
+ return res;
}
-bool knockout_plot_line(int x0, int y0, int x1, int y1, const plot_style_t *pstyle)
+
+/**
+ * Knockout line plotting.
+ *
+ * plot a line from (x0,y0) to (x1,y1). Coordinates are at
+ * centre of line width/thickness.
+ *
+ * \param ctx The current redraw context.
+ * \param pstyle Style controlling the line plot.
+ * \param line A rectangle defining the line to be drawn
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+knockout_plot_line(const struct redraw_context *ctx,
+ const plot_style_t *pstyle,
+ const struct rect *line)
{
- knockout_entries[knockout_entry_cur].data.line.x0 = x0;
- knockout_entries[knockout_entry_cur].data.line.y0 = y0;
- knockout_entries[knockout_entry_cur].data.line.x1 = x1;
- knockout_entries[knockout_entry_cur].data.line.y1 = y1;
+ knockout_entries[knockout_entry_cur].data.line.l = *line;
knockout_entries[knockout_entry_cur].data.line.plot_style = *pstyle;
knockout_entries[knockout_entry_cur].type = KNOCKOUT_PLOT_LINE;
- if (++knockout_entry_cur >= KNOCKOUT_ENTRIES)
- knockout_plot_flush();
- return true;
+ if (++knockout_entry_cur >= KNOCKOUT_ENTRIES) {
+ return knockout_plot_flush(ctx);
+ }
+ return NSERROR_OK;
}
-bool knockout_plot_polygon(const int *p, unsigned int n, const plot_style_t *pstyle)
+/**
+ * Knockout polygon plotting.
+ *
+ * Plots a filled polygon with straight lines between
+ * points. The lines around the edge of the ploygon are not
+ * plotted. The polygon is filled with the non-zero winding
+ * rule.
+ *
+ * \param ctx The current redraw context.
+ * \param pstyle Style controlling the polygon plot.
+ * \param p verticies of polygon
+ * \param n number of verticies.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+knockout_plot_polygon(const struct redraw_context *ctx,
+ const plot_style_t *pstyle,
+ const int *p,
+ unsigned int n)
{
- bool success = true;
int *dest;
+ nserror res = NSERROR_OK;
+ nserror ffres = NSERROR_OK;
/* ensure we have sufficient room even when flushed */
if (n * 2 >= KNOCKOUT_POLYGONS) {
- knockout_plot_flush();
- success = real_plot.polygon(p, n, pstyle);
- return success;
+ ffres = knockout_plot_flush(ctx);
+ res = real_plot.polygon(ctx, pstyle, p, n);
+ /* return the first error */
+ if ((res != NSERROR_OK) && (ffres == NSERROR_OK)) {
+ ffres = res;
+ }
+ return ffres;
}
/* ensure we have enough room right now */
- if (knockout_polygon_cur + n * 2 >= KNOCKOUT_POLYGONS)
- knockout_plot_flush();
+ if (knockout_polygon_cur + n * 2 >= KNOCKOUT_POLYGONS) {
+ ffres = knockout_plot_flush(ctx);
+ }
/* copy our data */
dest = &(knockout_polygons[knockout_polygon_cur]);
@@ -666,27 +650,62 @@ bool knockout_plot_polygon(const int *p, unsigned int n, const plot_style_t *pst
knockout_entries[knockout_entry_cur].data.polygon.n = n;
knockout_entries[knockout_entry_cur].data.polygon.plot_style = *pstyle;
knockout_entries[knockout_entry_cur].type = KNOCKOUT_PLOT_POLYGON;
- if (++knockout_entry_cur >= KNOCKOUT_ENTRIES)
- knockout_plot_flush();
- return true;
+ if (++knockout_entry_cur >= KNOCKOUT_ENTRIES) {
+ res = knockout_plot_flush(ctx);
+ }
+ /* return the first error */
+ if ((res != NSERROR_OK) && (ffres == NSERROR_OK)) {
+ ffres = res;
+ }
+ return ffres;
}
-bool knockout_plot_path(const float *p, unsigned int n, colour fill,
- float width, colour c, const float transform[6])
+/**
+ * knockout path plotting.
+ *
+ * The knockout implementation simply flushes the queue and plots the path
+ * directly using real plotter.
+ *
+ * \param ctx The current redraw context.
+ * \param pstyle Style controlling the path plot.
+ * \param p elements of path
+ * \param n nunber of elements on path
+ * \param transform A transform to apply to the path.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+knockout_plot_path(const struct redraw_context *ctx,
+ const plot_style_t *pstyle,
+ const float *p,
+ unsigned int n,
+ const float transform[6])
{
- knockout_plot_flush();
- return real_plot.path(p, n, fill, width, c, transform);
+ nserror res;
+ nserror ffres;
+
+ ffres = knockout_plot_flush(ctx);
+ res = real_plot.path(ctx, pstyle, p, n, transform);
+
+ /* return the first error */
+ if ((res != NSERROR_OK) && (ffres == NSERROR_OK)) {
+ ffres = res;
+ }
+ return ffres;
}
-bool knockout_plot_clip(const struct rect *clip)
+static nserror
+knockout_plot_clip(const struct redraw_context *ctx, const struct rect *clip)
{
+ nserror res = NSERROR_OK;
+
if (clip->x1 < clip->x0 || clip->y0 > clip->y1) {
#ifdef KNOCKOUT_DEBUG
- LOG("bad clip rectangle %i %i %i %i", clip->x0, clip->y0, clip->x1, clip->y1);
+ NSLOG(netsurf, INFO, "bad clip rectangle %i %i %i %i",
+ clip->x0, clip->y0, clip->x1, clip->y1);
#endif
- return false;
+ return NSERROR_BAD_SIZE;
}
/* memorise clip for bitmap tiling */
@@ -694,41 +713,107 @@ bool knockout_plot_clip(const struct rect *clip)
knockout_entries[knockout_entry_cur].data.clip = *clip;
knockout_entries[knockout_entry_cur].type = KNOCKOUT_PLOT_CLIP;
- if (++knockout_entry_cur >= KNOCKOUT_ENTRIES)
- knockout_plot_flush();
- return true;
+ if (++knockout_entry_cur >= KNOCKOUT_ENTRIES) {
+ res = knockout_plot_flush(ctx);
+ }
+ return res;
}
-bool knockout_plot_text(int x, int y, const char *text, size_t length,
- const plot_font_style_t *fstyle)
+/**
+ * Text plotting.
+ *
+ * \param ctx The current redraw context.
+ * \param fstyle plot style for this text
+ * \param x x coordinate
+ * \param y y coordinate
+ * \param text UTF-8 string to plot
+ * \param length length of string, in bytes
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+knockout_plot_text(const struct redraw_context *ctx,
+ const plot_font_style_t *fstyle,
+ int x,
+ int y,
+ const char *text,
+ size_t length)
{
+ nserror res = NSERROR_OK;
+
knockout_entries[knockout_entry_cur].data.text.x = x;
knockout_entries[knockout_entry_cur].data.text.y = y;
knockout_entries[knockout_entry_cur].data.text.text = text;
knockout_entries[knockout_entry_cur].data.text.length = length;
knockout_entries[knockout_entry_cur].data.text.font_style = *fstyle;
knockout_entries[knockout_entry_cur].type = KNOCKOUT_PLOT_TEXT;
- if (++knockout_entry_cur >= KNOCKOUT_ENTRIES)
- knockout_plot_flush();
- return true;
+ if (++knockout_entry_cur >= KNOCKOUT_ENTRIES) {
+ res = knockout_plot_flush(ctx);
+ }
+ return res;
}
-bool knockout_plot_disc(int x, int y, int radius, const plot_style_t *pstyle)
+/**
+ * knockout circle plotting
+ *
+ * Plot a circle centered on (x,y), which is optionally filled.
+ *
+ * \param ctx The current redraw context.
+ * \param pstyle Style controlling the circle plot.
+ * \param x x coordinate of circle centre.
+ * \param y y coordinate of circle centre.
+ * \param radius circle radius.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+knockout_plot_disc(const struct redraw_context *ctx,
+ const plot_style_t *pstyle,
+ int x,
+ int y,
+ int radius)
{
+ nserror res = NSERROR_OK;
+
knockout_entries[knockout_entry_cur].data.disc.x = x;
knockout_entries[knockout_entry_cur].data.disc.y = y;
knockout_entries[knockout_entry_cur].data.disc.radius = radius;
knockout_entries[knockout_entry_cur].data.disc.plot_style = *pstyle;
knockout_entries[knockout_entry_cur].type = KNOCKOUT_PLOT_DISC;
- if (++knockout_entry_cur >= KNOCKOUT_ENTRIES)
- knockout_plot_flush();
- return true;
+ if (++knockout_entry_cur >= KNOCKOUT_ENTRIES) {
+ res = knockout_plot_flush(ctx);
+ }
+ return res;
}
-bool knockout_plot_arc(int x, int y, int radius, int angle1, int angle2, const plot_style_t *pstyle)
+
+/**
+ * Plots an arc
+ *
+ * plot an arc segment around (x,y), anticlockwise from angle1
+ * to angle2. Angles are measured anticlockwise from
+ * horizontal, in degrees.
+ *
+ * \param ctx The current redraw context.
+ * \param pstyle Style controlling the arc plot.
+ * \param x The x coordinate of the arc.
+ * \param y The y coordinate of the arc.
+ * \param radius The radius of the arc.
+ * \param angle1 The start angle of the arc.
+ * \param angle2 The finish angle of the arc.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+knockout_plot_arc(const struct redraw_context *ctx,
+ const plot_style_t *pstyle,
+ int x,
+ int y,
+ int radius,
+ int angle1,
+ int angle2)
{
+ nserror res = NSERROR_OK;
+
knockout_entries[knockout_entry_cur].data.arc.x = x;
knockout_entries[knockout_entry_cur].data.arc.y = y;
knockout_entries[knockout_entry_cur].data.arc.radius = radius;
@@ -736,18 +821,48 @@ bool knockout_plot_arc(int x, int y, int radius, int angle1, int angle2, const p
knockout_entries[knockout_entry_cur].data.arc.angle2 = angle2;
knockout_entries[knockout_entry_cur].data.arc.plot_style = *pstyle;
knockout_entries[knockout_entry_cur].type = KNOCKOUT_PLOT_ARC;
- if (++knockout_entry_cur >= KNOCKOUT_ENTRIES)
- knockout_plot_flush();
- return true;
+ if (++knockout_entry_cur >= KNOCKOUT_ENTRIES) {
+ res = knockout_plot_flush(ctx);
+ }
+ return res;
}
-
-bool knockout_plot_bitmap(int x, int y, int width, int height,
- struct bitmap *bitmap, colour bg,
- bitmap_flags_t flags)
+/**
+ * knockout bitmap plotting.
+ *
+ * Tiled plot of a bitmap image. (x,y) gives the top left
+ * coordinate of an explicitly placed tile. From this tile the
+ * image can repeat in all four directions -- up, down, left
+ * and right -- to the extents given by the current clip
+ * rectangle.
+ *
+ * The bitmap_flags say whether to tile in the x and y
+ * directions. If not tiling in x or y directions, the single
+ * image is plotted. The width and height give the dimensions
+ * the image is to be scaled to.
+ *
+ * \param ctx The current redraw context.
+ * \param bitmap The bitmap to plot
+ * \param x The x coordinate to plot the bitmap
+ * \param y The y coordiante to plot the bitmap
+ * \param width The width of area to plot the bitmap into
+ * \param height The height of area to plot the bitmap into
+ * \param bg the background colour to alpha blend into
+ * \param flags the flags controlling the type of plot operation
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+knockout_plot_bitmap(const struct redraw_context *ctx,
+ struct bitmap *bitmap,
+ int x, int y,
+ int width, int height,
+ colour bg,
+ bitmap_flags_t flags)
{
int kx0, ky0, kx1, ky1;
+ nserror res;
+ nserror ffres = NSERROR_OK;
/* get our bounds */
kx0 = clip_cur.x0;
@@ -760,7 +875,7 @@ bool knockout_plot_bitmap(int x, int y, int width, int height,
if (x + width < kx1)
kx1 = x + width;
if ((kx0 > clip_cur.x1) || (kx1 < clip_cur.x0))
- return true;
+ return NSERROR_OK;
}
if (!(flags & BITMAPF_REPEAT_Y)) {
if (y > ky0)
@@ -768,12 +883,12 @@ bool knockout_plot_bitmap(int x, int y, int width, int height,
if (y + height < ky1)
ky1 = y + height;
if ((ky0 > clip_cur.y1) || (ky1 < clip_cur.y0))
- return true;
+ return NSERROR_OK;
}
/* tiled bitmaps both knock out and get knocked out */
if (guit->bitmap->get_opaque(bitmap)) {
- knockout_calculate(kx0, ky0, kx1, ky1, NULL);
+ knockout_calculate(ctx, kx0, ky0, kx1, ky1, NULL);
}
knockout_boxes[knockout_box_cur].bbox.x0 = kx0;
knockout_boxes[knockout_box_cur].bbox.y0 = ky0;
@@ -792,33 +907,120 @@ bool knockout_plot_bitmap(int x, int y, int width, int height,
knockout_entries[knockout_entry_cur].data.bitmap.bg = bg;
knockout_entries[knockout_entry_cur].data.bitmap.flags = flags;
knockout_entries[knockout_entry_cur].type = KNOCKOUT_PLOT_BITMAP;
+
if ((++knockout_entry_cur >= KNOCKOUT_ENTRIES) ||
- (++knockout_box_cur >= KNOCKOUT_BOXES))
- knockout_plot_flush();
- return knockout_plot_clip(&clip_cur);
+ (++knockout_box_cur >= KNOCKOUT_BOXES)) {
+ ffres = knockout_plot_flush(ctx);
+ }
+ res = knockout_plot_clip(ctx, &clip_cur);
+ /* return the first error */
+ if ((res != NSERROR_OK) && (ffres == NSERROR_OK)) {
+ ffres = res;
+ }
+ return ffres;
}
-bool knockout_plot_group_start(const char *name)
+
+/**
+ * Start of a group of objects.
+ *
+ * Used when plotter implements export to a vector graphics file format.
+ *
+ * \param ctx The current redraw context.
+ * \param name The name of the group being started.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+knockout_plot_group_start(const struct redraw_context *ctx, const char *name)
{
if (real_plot.group_start == NULL) {
- return true;
+ return NSERROR_OK;
}
knockout_entries[knockout_entry_cur].data.group_start.name = name;
knockout_entries[knockout_entry_cur].type = KNOCKOUT_PLOT_GROUP_START;
- if (++knockout_entry_cur >= KNOCKOUT_ENTRIES)
- knockout_plot_flush();
- return true;
+ if (++knockout_entry_cur >= KNOCKOUT_ENTRIES) {
+ return knockout_plot_flush(ctx);
+ }
+ return NSERROR_OK;
}
-bool knockout_plot_group_end(void)
+
+/**
+ * End a group of objects.
+ *
+ * Used when plotter implements export to a vector graphics file format.
+ *
+ * \param ctx The current redraw context.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror knockout_plot_group_end(const struct redraw_context *ctx)
{
if (real_plot.group_end == NULL) {
- return true;
+ return NSERROR_OK;
}
knockout_entries[knockout_entry_cur].type = KNOCKOUT_PLOT_GROUP_END;
- if (++knockout_entry_cur >= KNOCKOUT_ENTRIES)
- knockout_plot_flush();
+ if (++knockout_entry_cur >= KNOCKOUT_ENTRIES) {
+ return knockout_plot_flush(ctx);
+ }
+ return NSERROR_OK;
+}
+
+/* exported functions documented in desktop/knockout.h */
+bool knockout_plot_start(const struct redraw_context *ctx,
+ struct redraw_context *knk_ctx)
+{
+ /* check if we're recursing */
+ if (nested_depth++ > 0) {
+ /* we should already have the knockout renderer as default */
+ assert(ctx->plot->rectangle == knockout_plotters.rectangle);
+ *knk_ctx = *ctx;
+ return true;
+ }
+
+ /* end any previous sessions */
+ if (knockout_entry_cur > 0)
+ knockout_plot_end(ctx);
+
+ /* get copy of real plotter table */
+ real_plot = *(ctx->plot);
+
+ /* set up knockout rendering context */
+ *knk_ctx = *ctx;
+ knk_ctx->plot = &knockout_plotters;
return true;
}
+
+
+/* exported functions documented in desktop/knockout.h */
+bool knockout_plot_end(const struct redraw_context *ctx)
+{
+ /* only output when we've finished any nesting */
+ if (--nested_depth == 0) {
+ return knockout_plot_flush(ctx);
+ }
+
+ assert(nested_depth > 0);
+ return true;
+}
+
+
+/**
+ * knockout plotter operation table
+ */
+const struct plotter_table knockout_plotters = {
+ .rectangle = knockout_plot_rectangle,
+ .line = knockout_plot_line,
+ .polygon = knockout_plot_polygon,
+ .clip = knockout_plot_clip,
+ .text = knockout_plot_text,
+ .disc = knockout_plot_disc,
+ .arc = knockout_plot_arc,
+ .bitmap = knockout_plot_bitmap,
+ .group_start = knockout_plot_group_start,
+ .group_end = knockout_plot_group_end,
+ .flush = knockout_plot_flush,
+ .path = knockout_plot_path,
+ .option_knockout = true,
+};
diff --git a/desktop/knockout.h b/desktop/knockout.h
index c4f1245fc..f7ff04553 100644
--- a/desktop/knockout.h
+++ b/desktop/knockout.h
@@ -26,9 +26,21 @@
#include "netsurf/plotters.h"
+/**
+ * Start a knockout plotting session
+ *
+ * \param ctx the redraw context with real plotter table
+ * \param knk_ctx updated to copy of ctx, with plotter table replaced
+ * \return true on success, false otherwise
+ */
bool knockout_plot_start(const struct redraw_context *ctx,
struct redraw_context *knk_ctx);
-bool knockout_plot_end(void);
+/**
+ * End a knockout plotting session
+ *
+ * \return true on success, false otherwise
+ */
+bool knockout_plot_end(const struct redraw_context *ctx);
extern const struct plotter_table knockout_plotters;
diff --git a/desktop/local_history.c b/desktop/local_history.c
new file mode 100644
index 000000000..75da4aff1
--- /dev/null
+++ b/desktop/local_history.c
@@ -0,0 +1,446 @@
+/*
+ * Copyright 2017 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
+ * Local history viewer implementation
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "utils/errors.h"
+#include "utils/nsurl.h"
+#include "netsurf/types.h"
+#include "netsurf/layout.h"
+#include "netsurf/core_window.h"
+#include "netsurf/plotters.h"
+
+#include "desktop/gui_internal.h"
+#include "desktop/system_colour.h"
+#include "desktop/browser_private.h"
+#include "desktop/browser_history.h"
+#include "desktop/local_history.h"
+
+#define WIDTH 100
+#define HEIGHT 86
+
+/**
+ * local history viewer context
+ */
+struct local_history_session {
+ struct browser_window *bw;
+ struct core_window_callback_table *cw_t;
+ void *core_window_handle;
+};
+
+
+/**
+ * plot style for drawing lines between nodes
+ */
+static plot_style_t pstyle_line = {
+ .stroke_type = PLOT_OP_TYPE_SOLID,
+ .stroke_width = plot_style_int_to_fixed(2),
+};
+
+
+/**
+ * plot style for drawing background
+ */
+static plot_style_t pstyle_bg = {
+ .fill_type = PLOT_OP_TYPE_SOLID,
+};
+
+
+/**
+ * plot style for drawing rectangle round unselected nodes
+ */
+static plot_style_t pstyle_rect = {
+ .stroke_type = PLOT_OP_TYPE_SOLID,
+ .stroke_width = plot_style_int_to_fixed(1),
+};
+
+
+/**
+ * plot style for drawing rectangle round selected nodes
+ */
+static plot_style_t pstyle_rect_sel = {
+ .stroke_type = PLOT_OP_TYPE_SOLID,
+ .stroke_width = plot_style_int_to_fixed(3),
+};
+
+
+/**
+ * plot style for font on unselected nodes
+ */
+static plot_font_style_t pfstyle_node = {
+ .family = PLOT_FONT_FAMILY_SANS_SERIF,
+ .size = 8 * PLOT_STYLE_SCALE,
+ .weight = 400,
+ .flags = FONTF_NONE,
+};
+
+
+/**
+ * plot style for font on unselected nodes
+ */
+static plot_font_style_t pfstyle_node_sel = {
+ .family = PLOT_FONT_FAMILY_SANS_SERIF,
+ .size = 8 * PLOT_STYLE_SCALE,
+ .weight = 900,
+ .flags = FONTF_NONE,
+};
+
+
+/**
+ * Recursively redraw a history entry.
+ *
+ * \param history history containing the entry
+ * \param entry entry to render
+ * \param clip redraw area
+ * \param x window x offset
+ * \param y window y offset
+ * \param ctx current redraw context
+ */
+static nserror
+redraw_entry(struct history *history,
+ struct history_entry *entry,
+ struct rect *clip,
+ int x, int y,
+ const struct redraw_context *ctx)
+{
+ size_t char_offset;
+ int actual_x;
+ struct history_entry *child;
+ int tailsize = 5;
+
+ plot_style_t *pstyle;
+ plot_font_style_t *pfstyle;
+ struct rect rect;
+ nserror res;
+
+ /* setup plot styles */
+ if (entry == history->current) {
+ pstyle = &pstyle_rect_sel;
+ pfstyle = &pfstyle_node_sel;
+ } else {
+ pstyle = &pstyle_rect;
+ pfstyle = &pfstyle_node;
+ }
+
+ /* Only attempt to plot bitmap if it is present */
+ if (entry->page.bitmap != NULL) {
+ res = ctx->plot->bitmap(ctx,
+ entry->page.bitmap,
+ entry->x + x,
+ entry->y + y,
+ WIDTH, HEIGHT,
+ 0xffffff,
+ 0);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+ }
+
+ rect.x0 = entry->x - 1 + x;
+ rect.y0 = entry->y - 1 + y;
+ rect.x1 = entry->x + x + WIDTH;
+ rect.y1 = entry->y + y + HEIGHT;
+ res = ctx->plot->rectangle(ctx, pstyle, &rect);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ res = guit->layout->position(plot_style_font, entry->page.title,
+ strlen(entry->page.title), WIDTH,
+ &char_offset, &actual_x);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ res = ctx->plot->text(ctx,
+ pfstyle,
+ entry->x + x,
+ entry->y + HEIGHT + 12 + y,
+ entry->page.title,
+ char_offset);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ /* for each child node draw a line and recurse redraw into it */
+ for (child = entry->forward; child; child = child->next) {
+ rect.x0 = entry->x + WIDTH + x;
+ rect.y0 = entry->y + HEIGHT / 2 + y;
+ rect.x1 = entry->x + WIDTH + tailsize + x;
+ rect.y1 = entry->y + HEIGHT / 2 + y;
+ res = ctx->plot->line(ctx, &pstyle_line, &rect);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ rect.x0 = entry->x + WIDTH + tailsize + x;
+ rect.y0 = entry->y + HEIGHT / 2 + y;
+ rect.x1 = child->x - tailsize + x;
+ rect.y1 = child->y + HEIGHT / 2 + y;
+ res = ctx->plot->line(ctx, &pstyle_line, &rect);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ rect.x0 = child->x - tailsize + x;
+ rect.y0 = child->y + HEIGHT / 2 + y;
+ rect.x1 = child->x + x;
+ rect.y1 = child->y + HEIGHT / 2 + y;
+ res = ctx->plot->line(ctx, &pstyle_line, &rect);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ res = redraw_entry(history, child, clip, x, y, ctx);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+ }
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * 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 *
+find_entry_position(struct history_entry *entry, int x, int y)
+{
+ struct history_entry *child;
+ struct history_entry *found;
+
+ if (!entry) {
+ return NULL;
+ }
+
+ 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 = find_entry_position(child, x, y);
+ if (found) {
+ return found;
+ }
+ }
+
+ return NULL;
+}
+
+
+/* exported interface documented in desktop/local_history.h */
+nserror
+local_history_init(struct core_window_callback_table *cw_t,
+ void *core_window_handle,
+ struct browser_window *bw,
+ struct local_history_session **session)
+{
+ nserror res;
+ struct local_history_session *nses;
+
+ res = ns_system_colour_char("Window", &pstyle_bg.fill_colour);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+ pfstyle_node.background = pstyle_bg.fill_colour;
+ pfstyle_node_sel.background = pstyle_bg.fill_colour;
+
+ res = ns_system_colour_char("GrayText", &pstyle_line.stroke_colour);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+ pstyle_rect.stroke_colour = pstyle_line.stroke_colour;
+ pfstyle_node.foreground = pstyle_line.stroke_colour;
+
+ res = ns_system_colour_char("Highlight", &pstyle_rect_sel.stroke_colour);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+ pfstyle_node_sel.foreground = pstyle_rect_sel.stroke_colour;
+
+ nses = calloc(1, sizeof(struct local_history_session));
+ if (nses == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ nses->cw_t = cw_t;
+ nses->core_window_handle = core_window_handle;
+
+ local_history_set(nses, bw);
+
+ *session = nses;
+
+ return NSERROR_OK;
+}
+
+/* exported interface documented in desktop/local_history.h */
+nserror local_history_fini(struct local_history_session *session)
+{
+ free(session);
+
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in desktop/local_history.h */
+nserror
+local_history_redraw(struct local_history_session *session,
+ int x,
+ int y,
+ struct rect *clip,
+ const struct redraw_context *ctx)
+{
+ struct rect r = {
+ .x0 = clip->x0 + x,
+ .y0 = clip->y0 + y,
+ .x1 = clip->x1 + x,
+ .y1 = clip->y1 + y,
+ };
+
+ if (session->bw == NULL) {
+ return NSERROR_OK;
+ }
+
+ if (session->bw->history->start == NULL) {
+ return NSERROR_OK;
+ }
+
+ ctx->plot->clip(ctx, &r);
+ ctx->plot->rectangle(ctx, &pstyle_bg, &r);
+
+ return redraw_entry(session->bw->history,
+ session->bw->history->start,
+ clip,
+ x, y,
+ ctx);
+}
+
+/* exported interface documented in desktop/local_history.h */
+nserror
+local_history_mouse_action(struct local_history_session *session,
+ enum browser_mouse_state mouse,
+ int x,
+ int y)
+{
+ struct history_entry *entry;
+ bool new_window;
+
+ if (session->bw == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ if ((mouse & (BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_PRESS_2)) == 0) {
+ return NSERROR_NOT_IMPLEMENTED;
+ }
+
+ entry = find_entry_position(session->bw->history->start, x, y);
+ if (entry == NULL) {
+ return NSERROR_NOT_FOUND;
+ }
+
+ if (entry == session->bw->history->current) {
+ return NSERROR_PERMISSION;
+ }
+
+ if (mouse & BROWSER_MOUSE_PRESS_1) {
+ new_window = false;
+ } else if (mouse & BROWSER_MOUSE_PRESS_2) {
+ new_window = true;
+ } else {
+ new_window = false;
+ }
+
+ browser_window_history_go(session->bw, entry, new_window);
+
+ return NSERROR_OK;
+}
+
+/* exported interface documented in desktop/local_history.h */
+bool
+local_history_keypress(struct local_history_session *session, uint32_t key)
+{
+ return false;
+}
+
+/* exported interface documented in desktop/local_history.h */
+nserror
+local_history_set(struct local_history_session *session,
+ struct browser_window *bw)
+{
+ session->bw = bw;
+ if (bw != NULL) {
+ assert(session->bw->history != NULL);
+
+ session->cw_t->update_size(session->core_window_handle,
+ session->bw->history->width,
+ session->bw->history->height);
+ }
+
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in desktop/local_history.h */
+nserror
+local_history_get_size(struct local_history_session *session,
+ int *width,
+ int *height)
+{
+ *width = session->bw->history->width + 20;
+ *height = session->bw->history->height + 20;
+
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in desktop/local_history.h */
+nserror
+local_history_get_url(struct local_history_session *session,
+ int x, int y,
+ nsurl **url_out)
+{
+ struct history_entry *entry;
+
+ if (session->bw == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ entry = find_entry_position(session->bw->history->start, x, y);
+ if (entry == NULL) {
+ return NSERROR_NOT_FOUND;
+ }
+
+ *url_out = nsurl_ref(entry->page.url);
+
+ return NSERROR_OK;
+}
diff --git a/desktop/local_history.h b/desktop/local_history.h
new file mode 100644
index 000000000..7f85a633e
--- /dev/null
+++ b/desktop/local_history.h
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2017 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NETSURF_DESKTOP_LOCAL_HISTORY_H
+#define NETSURF_DESKTOP_LOCAL_HISTORY_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "utils/errors.h"
+#include "netsurf/mouse.h"
+
+struct core_window_callback_table;
+struct redraw_context;
+struct nsurl;
+struct rect;
+struct local_history_session;
+struct browser_window;
+
+/**
+ * Initialise the local history.
+ *
+ * This iterates through the history object of a browser window and
+ * creates tree of visited pages with thumbnails which may be selected
+ * to cause navigation.
+ *
+ * This must be called before any other local_history_* function.
+ *
+ * \param[in] cw_t Callback table for core_window containing the treeview.
+ * \param[in] core_window_handle The core_window in which the treeview is shown.
+ * \param[in] bw browser window to show history of.
+ * \param[out] session The created local history session context.
+ * \return NSERROR_OK on success and session set, appropriate error code otherwise
+ */
+nserror local_history_init(struct core_window_callback_table *cw_t,
+ void *core_window_handle,
+ struct browser_window *bw,
+ struct local_history_session **session);
+
+/**
+ * Finalise the local history.
+ *
+ * This destroys the local history view and the local history module's
+ * internal data. After calling this if local history is required again,
+ * local_history_init must be called to create a new session.
+ *
+ * \param session The local history session to finalise.
+ * \return NSERROR_OK on success and session freed appropriate error otherwise
+ */
+nserror local_history_fini(struct local_history_session *session);
+
+
+/**
+ * Redraw the local history.
+ *
+ * Causes the local history viewer to issue plot operations to redraw
+ * the specified area of the viewport.
+ *
+ * \param[in] session The local history session context.
+ * \param[in] x X coordinate to render history at
+ * \param[in] y Y coordinate to render history at
+ * \param[in] clip Current clip rectangle (wrt tree origin)
+ * \param[in] ctx Current redraw context
+ */
+nserror local_history_redraw(struct local_history_session *session, int x, int y, struct rect *clip, const struct redraw_context *ctx);
+
+
+/**
+ * Handles all kinds of mouse action
+ *
+ * \param[in] session The local history session context.
+ * \param[in] mouse The current mouse state
+ * \param[in] x The current mouse X coordinate
+ * \param[in] y The current mouse Y coordinate
+ * \return NSERROR_OK if mouse action was processed.
+ * NSERROR_NOT_FOUND if nothing under the pointer where it was clicked
+ * NSERROR_NOT_IMPLEMENTED if the action was not processed.
+ * NSERROR_PERMISSION if the clicked item was the current page
+ */
+nserror local_history_mouse_action(struct local_history_session *session, enum browser_mouse_state mouse, int x, int y);
+
+
+/**
+ * Key press handling.
+ *
+ * \param[in] session The local history session context.
+ * \param[in] key The ucs4 character codepoint
+ * \return true if the keypress is dealt with, false otherwise.
+ */
+bool local_history_keypress(struct local_history_session *session, uint32_t key);
+
+
+/**
+ * Change the browser window to draw local history for.
+ *
+ * \param[in] session The local history session context.
+ * \param bw browser window to show history of.
+ * \return NSERROR_OK or appropriate error code.
+ */
+nserror local_history_set(struct local_history_session *session, struct browser_window *bw);
+
+
+/**
+ * get size of local history content area.
+ *
+ * \param[in] session The local history session context.
+ * \param[out] width on sucessful return the width of the localhistory content
+ * \param[out] height on sucessful return the height of the localhistory content
+ * \return NSERROR_OK or appropriate error code.
+ */
+nserror local_history_get_size(struct local_history_session *session, int *width, int *height);
+
+
+/**
+ * get url of entry at position in local history content area.
+ *
+ * \todo the returned url should be a referenced nsurl.
+ *
+ * \param[in] session The local history session context.
+ * \param[in] x The x coordinate to get url of.
+ * \param[in] y The y coordinate to get url of.
+ * \param[out] url_out referenced url.
+ * \return NSERROR_OK and url_out updated or NSERROR_NOT_FOUND if no url at
+ * location.
+ */
+nserror local_history_get_url(struct local_history_session *session, int x, int y, struct nsurl **url_out);
+
+
+#endif
diff --git a/desktop/mouse.c b/desktop/mouse.c
index 6d22fd461..d22910582 100644
--- a/desktop/mouse.c
+++ b/desktop/mouse.c
@@ -30,5 +30,5 @@
*/
void browser_mouse_state_dump(browser_mouse_state mouse)
{
- LOG("mouse state: %s %s %s %s %s %s %s %s %s %s %s %s %s %s", mouse & BROWSER_MOUSE_PRESS_1 ? "P1" : " ", mouse & BROWSER_MOUSE_PRESS_2 ? "P2" : " ", mouse & BROWSER_MOUSE_CLICK_1 ? "C1" : " ", mouse & BROWSER_MOUSE_CLICK_2 ? "C2" : " ", mouse & BROWSER_MOUSE_DOUBLE_CLICK ? "DC" : " ", mouse & BROWSER_MOUSE_TRIPLE_CLICK ? "TC" : " ", mouse & BROWSER_MOUSE_DRAG_1 ? "D1" : " ", mouse & BROWSER_MOUSE_DRAG_2 ? "D2" : " ", mouse & BROWSER_MOUSE_DRAG_ON ? "DO" : " ", mouse & BROWSER_MOUSE_HOLDING_1 ? "H1" : " ", mouse & BROWSER_MOUSE_HOLDING_2 ? "H2" : " ", mouse & BROWSER_MOUSE_MOD_1 ? "M1" : " ", mouse & BROWSER_MOUSE_MOD_2 ? "M2" : " ", mouse & BROWSER_MOUSE_MOD_3 ? "M3" : " ");
+ NSLOG(netsurf, INFO, "mouse state: %s %s %s %s %s %s %s %s %s %s %s %s %s %s", mouse & BROWSER_MOUSE_PRESS_1 ? "P1" : " ", mouse & BROWSER_MOUSE_PRESS_2 ? "P2" : " ", mouse & BROWSER_MOUSE_CLICK_1 ? "C1" : " ", mouse & BROWSER_MOUSE_CLICK_2 ? "C2" : " ", mouse & BROWSER_MOUSE_DOUBLE_CLICK ? "DC" : " ", mouse & BROWSER_MOUSE_TRIPLE_CLICK ? "TC" : " ", mouse & BROWSER_MOUSE_DRAG_1 ? "D1" : " ", mouse & BROWSER_MOUSE_DRAG_2 ? "D2" : " ", mouse & BROWSER_MOUSE_DRAG_ON ? "DO" : " ", mouse & BROWSER_MOUSE_HOLDING_1 ? "H1" : " ", mouse & BROWSER_MOUSE_HOLDING_2 ? "H2" : " ", mouse & BROWSER_MOUSE_MOD_1 ? "M1" : " ", mouse & BROWSER_MOUSE_MOD_2 ? "M2" : " ", mouse & BROWSER_MOUSE_MOD_3 ? "M3" : " ");
}
diff --git a/desktop/netsurf.c b/desktop/netsurf.c
index 0f597aa9d..76ff4b19a 100644
--- a/desktop/netsurf.c
+++ b/desktop/netsurf.c
@@ -41,8 +41,8 @@
#include "image/image.h"
#include "image/image_cache.h"
#include "javascript/js.h"
-#include "render/html.h"
-#include "render/textplain.h"
+#include "html/html.h"
+#include "text/textplain.h"
#include "netsurf/browser_window.h"
#include "desktop/system_colour.h"
@@ -89,7 +89,8 @@
static void netsurf_lwc_iterator(lwc_string *str, void *pw)
{
- LOG("[%3u] %.*s", str->refcnt, (int)lwc_string_length(str), lwc_string_data(str));
+ NSLOG(netsurf, INFO, "[%3u] %.*s", str->refcnt,
+ (int)lwc_string_length(str), lwc_string_data(str));
}
/**
@@ -165,8 +166,9 @@ nserror netsurf_init(const char *store_path)
if (hlcache_parameters.llcache.limit < MINIMUM_MEMORY_CACHE_SIZE) {
hlcache_parameters.llcache.limit = MINIMUM_MEMORY_CACHE_SIZE;
- LOG("Setting minimum memory cache size %" PRIsizet,
- hlcache_parameters.llcache.limit);
+ NSLOG(netsurf, INFO,
+ "Setting minimum memory cache size %"PRIsizet,
+ hlcache_parameters.llcache.limit);
}
/* Set up the max attempts made to fetch a timing out resource */
@@ -212,10 +214,6 @@ nserror netsurf_init(const char *store_path)
if (ret != NSERROR_OK)
return ret;
- ret = mimesniff_init();
- if (ret != NSERROR_OK)
- return ret;
-
setlocale(LC_ALL, "");
/* initialise the fetchers */
@@ -247,44 +245,42 @@ void netsurf_exit(void)
{
hlcache_stop();
- LOG("Closing GUI");
+ NSLOG(netsurf, INFO, "Closing GUI");
guit->misc->quit();
- LOG("Finalising JavaScript");
+ NSLOG(netsurf, INFO, "Finalising JavaScript");
js_finalise();
- LOG("Finalising Web Search");
+ NSLOG(netsurf, INFO, "Finalising Web Search");
search_web_finalise();
- LOG("Finalising high-level cache");
+ NSLOG(netsurf, INFO, "Finalising high-level cache");
hlcache_finalise();
- LOG("Closing fetches");
+ NSLOG(netsurf, INFO, "Closing fetches");
fetcher_quit();
- mimesniff_fini();
-
/* dump any remaining cache entries */
image_cache_fini();
/* Clean up after content handlers */
content_factory_fini();
- LOG("Closing utf8");
+ NSLOG(netsurf, INFO, "Closing utf8");
utf8_finalise();
- LOG("Destroying URLdb");
+ NSLOG(netsurf, INFO, "Destroying URLdb");
urldb_destroy();
- LOG("Destroying System colours");
+ NSLOG(netsurf, INFO, "Destroying System colours");
ns_system_colour_finalize();
- LOG("Destroying Messages");
+ NSLOG(netsurf, INFO, "Destroying Messages");
messages_destroy();
corestrings_fini();
- LOG("Remaining lwc strings:");
+ NSLOG(netsurf, INFO, "Remaining lwc strings:");
lwc_iterate_strings(netsurf_lwc_iterator, NULL);
- LOG("Exited successfully");
+ NSLOG(netsurf, INFO, "Exited successfully");
}
diff --git a/desktop/options.h b/desktop/options.h
index d91898c6e..9b7064efa 100644
--- a/desktop/options.h
+++ b/desktop/options.h
@@ -289,3 +289,8 @@ NSOPTION_COLOUR(sys_colour_ThreeDShadow, 0x00d5d5d5)
NSOPTION_COLOUR(sys_colour_Window, 0x00f1f1f1)
NSOPTION_COLOUR(sys_colour_WindowFrame, 0x004e4e4e)
NSOPTION_COLOUR(sys_colour_WindowText, 0x00000000)
+
+/** Filter for non-verbose logging */
+NSOPTION_STRING(log_filter, "level:WARNING")
+/** Filter for verbose logging */
+NSOPTION_STRING(verbose_filter, "level:VERBOSE")
diff --git a/desktop/plot_style.c b/desktop/plot_style.c
index 1f0ac39cf..05954144a 100644
--- a/desktop/plot_style.c
+++ b/desktop/plot_style.c
@@ -47,7 +47,7 @@ plot_style_t *plot_style_fill_red = &plot_style_fill_red_static;
static const plot_style_t plot_style_content_edge_static = {
.stroke_type = PLOT_OP_TYPE_SOLID,
.stroke_colour = 0x00ff0000,
- .stroke_width = 1,
+ .stroke_width = plot_style_int_to_fixed(1),
};
plot_style_t const * const plot_style_content_edge =
&plot_style_content_edge_static;
@@ -55,7 +55,7 @@ plot_style_t const * const plot_style_content_edge =
static const plot_style_t plot_style_padding_edge_static = {
.stroke_type = PLOT_OP_TYPE_SOLID,
.stroke_colour = 0x000000ff,
- .stroke_width = 1,
+ .stroke_width = plot_style_int_to_fixed(1),
};
plot_style_t const * const plot_style_padding_edge =
&plot_style_padding_edge_static;
@@ -63,7 +63,7 @@ plot_style_t const * const plot_style_padding_edge =
static const plot_style_t plot_style_margin_edge_static = {
.stroke_type = PLOT_OP_TYPE_SOLID,
.stroke_colour = 0x0000ffff,
- .stroke_width = 1,
+ .stroke_width = plot_style_int_to_fixed(1),
};
plot_style_t const * const plot_style_margin_edge =
&plot_style_margin_edge_static;
@@ -74,14 +74,14 @@ static const plot_style_t plot_style_broken_object_static = {
.fill_colour = 0x008888ff,
.stroke_type = PLOT_OP_TYPE_SOLID,
.stroke_colour = 0x000000ff,
- .stroke_width = 1,
+ .stroke_width = plot_style_int_to_fixed(1),
};
plot_style_t const * const plot_style_broken_object =
&plot_style_broken_object_static;
static const plot_font_style_t plot_fstyle_broken_object_static = {
.family = PLOT_FONT_FAMILY_SANS_SERIF,
- .size = 16 * FONT_SIZE_SCALE,
+ .size = 16 * PLOT_STYLE_SCALE,
.weight = 400,
.flags = FONTF_NONE,
.background = 0x8888ff,
@@ -134,7 +134,7 @@ plot_style_t *plot_style_fill_wblobc = &plot_style_fill_wblobc_static;
static plot_style_t plot_style_stroke_wblobc_static = {
.stroke_type = PLOT_OP_TYPE_SOLID,
.stroke_colour = WIDGET_BLOBC,
- .stroke_width = 2,
+ .stroke_width = plot_style_int_to_fixed(2),
};
plot_style_t *plot_style_stroke_wblobc = &plot_style_stroke_wblobc_static;
@@ -156,7 +156,7 @@ plot_style_t *plot_style_stroke_lightwbasec = &plot_style_stroke_lightwbasec_sta
/* Generic font style */
static const plot_font_style_t plot_style_font_static = {
.family = PLOT_FONT_FAMILY_SANS_SERIF,
- .size = 8 * FONT_SIZE_SCALE,
+ .size = 8 * PLOT_STYLE_SCALE,
.weight = 400,
.flags = FONTF_NONE,
.background = 0xffffff,
diff --git a/desktop/print.c b/desktop/print.c
index e7c8cf2fa..de579dcf2 100644
--- a/desktop/print.c
+++ b/desktop/print.c
@@ -34,7 +34,7 @@
#include "netsurf/plotters.h"
#include "content/hlcache.h"
#include "css/utils.h"
-#include "render/box.h"
+#include "html/box.h"
#include "desktop/print.h"
#include "desktop/printer.h"
@@ -126,8 +126,10 @@ print_apply_settings(hlcache_handle *content, struct print_settings *settings)
content_reformat(content, false, page_content_width, 0);
- LOG("New layout applied.New height = %d ; New width = %d ",
- content_get_height(content), content_get_width(content));
+ NSLOG(netsurf, INFO,
+ "New layout applied.New height = %d ; New width = %d ",
+ content_get_height(content),
+ content_get_width(content));
return true;
}
@@ -179,7 +181,8 @@ bool print_draw_next_page(const struct printer *printer,
struct redraw_context ctx = {
.interactive = false,
.background_images = !nsoption_bool(remove_backgrounds),
- .plot = printer->plotter
+ .plot = printer->plotter,
+ .priv = settings->priv
};
html_redraw_printing_top_cropped = INT_MAX;
@@ -254,6 +257,11 @@ struct print_settings *print_make_settings(print_configuration configuration,
struct print_settings *settings;
css_fixed length = 0;
css_unit unit = CSS_UNIT_MM;
+ nscss_len_ctx len_ctx = {
+ .vw = DEFAULT_PAGE_WIDTH,
+ .vh = DEFAULT_PAGE_HEIGHT,
+ .root_style = NULL,
+ };
switch (configuration){
case PRINT_DEFAULT:
@@ -269,17 +277,17 @@ struct print_settings *print_make_settings(print_configuration configuration,
settings->scale = DEFAULT_EXPORT_SCALE;
length = INTTOFIX(DEFAULT_MARGIN_LEFT_MM);
- settings->margins[MARGINLEFT] =
- nscss_len2px(length, unit, NULL);
+ settings->margins[MARGINLEFT] = nscss_len2px(
+ &len_ctx, length, unit, NULL);
length = INTTOFIX(DEFAULT_MARGIN_RIGHT_MM);
- settings->margins[MARGINRIGHT] =
- nscss_len2px(length, unit, NULL);
+ settings->margins[MARGINRIGHT] = nscss_len2px(
+ &len_ctx, length, unit, NULL);
length = INTTOFIX(DEFAULT_MARGIN_TOP_MM);
- settings->margins[MARGINTOP] =
- nscss_len2px(length, unit, NULL);
+ settings->margins[MARGINTOP] = nscss_len2px(
+ &len_ctx, length, unit, NULL);
length = INTTOFIX(DEFAULT_MARGIN_BOTTOM_MM);
- settings->margins[MARGINBOTTOM] =
- nscss_len2px(length, unit, NULL);
+ settings->margins[MARGINBOTTOM] = nscss_len2px(
+ &len_ctx, length, unit, NULL);
break;
/* use settings from the Export options tab */
case PRINT_OPTIONS:
@@ -295,17 +303,17 @@ struct print_settings *print_make_settings(print_configuration configuration,
settings->scale = (float)nsoption_int(export_scale) / 100;
length = INTTOFIX(nsoption_int(margin_left));
- settings->margins[MARGINLEFT] =
- nscss_len2px(length, unit, NULL);
+ settings->margins[MARGINLEFT] = nscss_len2px(
+ &len_ctx, length, unit, NULL);
length = INTTOFIX(nsoption_int(margin_right));
- settings->margins[MARGINRIGHT] =
- nscss_len2px(length, unit, NULL);
+ settings->margins[MARGINRIGHT] = nscss_len2px(
+ &len_ctx, length, unit, NULL);
length = INTTOFIX(nsoption_int(margin_top));
- settings->margins[MARGINTOP] =
- nscss_len2px(length, unit, NULL);
+ settings->margins[MARGINTOP] = nscss_len2px(
+ &len_ctx, length, unit, NULL);
length = INTTOFIX(nsoption_int(margin_bottom));
- settings->margins[MARGINBOTTOM] =
- nscss_len2px(length, unit, NULL);
+ settings->margins[MARGINBOTTOM] = nscss_len2px(
+ &len_ctx, length, unit, NULL);
break;
default:
return NULL;
diff --git a/desktop/print.h b/desktop/print.h
index fb1fd63ac..4d178aa8a 100644
--- a/desktop/print.h
+++ b/desktop/print.h
@@ -61,6 +61,9 @@ struct print_settings{
/*the functions used to measure fonts*/
const struct gui_layout_table *font_func;
+
+ /* Private data for the plotter context */
+ void *priv;
};
diff --git a/desktop/save_complete.c b/desktop/save_complete.c
index f8f005743..ef794d4d7 100644
--- a/desktop/save_complete.c
+++ b/desktop/save_complete.c
@@ -43,8 +43,9 @@
#include "netsurf/content.h"
#include "content/hlcache.h"
#include "css/css.h"
-#include "render/box.h"
-#include "render/html.h"
+#include "html/box.h"
+#include "html/html_save.h"
+#include "html/html.h"
#include "netsurf/misc.h"
#include "desktop/gui_internal.h"
@@ -168,7 +169,7 @@ static bool save_complete_save_buffer(save_complete_ctx *ctx,
fp = fopen(fname, "wb");
if (fp == NULL) {
free(fname);
- LOG("fopen(): errno = %i", errno);
+ NSLOG(netsurf, INFO, "fopen(): errno = %i", errno);
guit->misc->warning("SaveError", strerror(errno));
return false;
}
@@ -195,10 +196,12 @@ static bool save_complete_save_buffer(save_complete_ctx *ctx,
* \param osize updated with the size of the result.
* \return converted source, or NULL on out of memory.
*/
-
-static char *save_complete_rewrite_stylesheet_urls(save_complete_ctx *ctx,
- const char *source, unsigned long size, const nsurl *base,
- unsigned long *osize)
+static char *
+save_complete_rewrite_stylesheet_urls(save_complete_ctx *ctx,
+ const char *source,
+ unsigned long size,
+ const nsurl *base,
+ unsigned long *osize)
{
char *rewritten;
unsigned long offset = 0;
@@ -207,8 +210,9 @@ static char *save_complete_rewrite_stylesheet_urls(save_complete_ctx *ctx,
/* count number occurrences of @import to (over)estimate result size */
/* can't use strstr because source is not 0-terminated string */
- for (offset = 0; SLEN("@import") < size &&
- offset <= size - SLEN("@import"); offset++) {
+ for (offset = 0;
+ (SLEN("@import") < size) && (offset <= (size - SLEN("@import")));
+ offset++) {
if (source[offset] == '@' &&
ascii_to_lower(source[offset + 1]) == 'i' &&
ascii_to_lower(source[offset + 2]) == 'm' &&
@@ -637,9 +641,9 @@ static bool save_complete_handle_attr_value(save_complete_ctx *ctx,
*
* Attribute: Elements:
*
- * 1) data <object>
- * 2) href <a> <area> <link>
- * 3) src <script> <input> <frame> <iframe> <img>
+ * 1) data object
+ * 2) href a, area, link
+ * 3) src script, input, frame, iframe, img
* 4) background any (except those above)
*/
/* 1 */
@@ -1044,7 +1048,7 @@ static bool save_complete_node_handler(dom_node *node,
} else if (type == DOM_DOCUMENT_NODE) {
/* Do nothing */
} else {
- LOG("Unhandled node type: %d", type);
+ NSLOG(netsurf, INFO, "Unhandled node type: %d", type);
}
return true;
@@ -1075,7 +1079,7 @@ static bool save_complete_save_html_document(save_complete_ctx *ctx,
fp = fopen(fname, "wb");
if (fp == NULL) {
free(fname);
- LOG("fopen(): errno = %i", errno);
+ NSLOG(netsurf, INFO, "fopen(): errno = %i", errno);
guit->misc->warning("SaveError", strerror(errno));
return false;
}
@@ -1154,7 +1158,7 @@ static bool save_complete_inventory(save_complete_ctx *ctx)
fp = fopen(fname, "w");
free(fname);
if (fp == NULL) {
- LOG("fopen(): errno = %i", errno);
+ NSLOG(netsurf, INFO, "fopen(): errno = %i", errno);
guit->misc->warning("SaveError", strerror(errno));
return false;
}
@@ -1182,7 +1186,8 @@ static nserror regcomp_wrapper(regex_t *preg, const char *regex, int cflags)
if (r) {
char errbuf[200];
regerror(r, preg, errbuf, sizeof errbuf);
- LOG("Failed to compile regexp '%s': %s\n", regex, errbuf);
+ NSLOG(netsurf, INFO, "Failed to compile regexp '%s': %s\n",
+ regex, errbuf);
return NSERROR_INIT_FAILED;
}
return NSERROR_OK;
diff --git a/desktop/save_pdf.c b/desktop/save_pdf.c
index d303eca7c..889190089 100644
--- a/desktop/save_pdf.c
+++ b/desktop/save_pdf.c
@@ -171,7 +171,8 @@ bool pdf_plot_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *psty
{
DashPattern_e dash;
#ifdef PDF_DEBUG
- LOG("%d %d %d %d %f %X", x0, y0, x1, y1, page_height - y0, pstyle->fill_colour);
+ NSLOG(netsurf, INFO, "%d %d %d %d %f %X", x0, y0, x1, y1,
+ page_height - y0, pstyle->fill_colour);
#endif
if (pstyle->fill_type != PLOT_OP_TYPE_NONE) {
@@ -212,10 +213,10 @@ bool pdf_plot_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *psty
}
apply_clip_and_mode(false,
- NS_TRANSPARENT,
- pstyle->stroke_colour,
- pstyle->stroke_width,
- dash);
+ NS_TRANSPARENT,
+ pstyle->stroke_colour,
+ plot_style_int_to_fixed(pstyle->stroke_width),
+ dash);
HPDF_Page_Rectangle(pdf_page, x0, page_height - y0, x1 - x0, -(y1 - y0));
HPDF_Page_Stroke(pdf_page);
@@ -244,10 +245,10 @@ bool pdf_plot_line(int x0, int y0, int x1, int y1, const plot_style_t *pstyle)
}
apply_clip_and_mode(false,
- NS_TRANSPARENT,
- pstyle->stroke_colour,
- pstyle->stroke_width,
- dash);
+ NS_TRANSPARENT,
+ pstyle->stroke_colour,
+ plot_style_int_to_fixed(pstyle->stroke_width),
+ dash);
HPDF_Page_MoveTo(pdf_page, x0, page_height - y0);
HPDF_Page_LineTo(pdf_page, x1, page_height - y1);
@@ -262,7 +263,7 @@ bool pdf_plot_polygon(const int *p, unsigned int n, const plot_style_t *style)
#ifdef PDF_DEBUG
int pmaxx = p[0], pmaxy = p[1];
int pminx = p[0], pminy = p[1];
- LOG(".");
+ NSLOG(netsurf, INFO, ".");
#endif
if (n == 0)
return true;
@@ -281,7 +282,8 @@ bool pdf_plot_polygon(const int *p, unsigned int n, const plot_style_t *style)
}
#ifdef PDF_DEBUG
- LOG("%d %d %d %d %f", pminx, pminy, pmaxx, pmaxy, page_height - pminy);
+ NSLOG(netsurf, INFO, "%d %d %d %d %f", pminx, pminy, pmaxx, pmaxy,
+ page_height - pminy);
#endif
HPDF_Page_Fill(pdf_page);
@@ -294,7 +296,8 @@ bool pdf_plot_polygon(const int *p, unsigned int n, const plot_style_t *style)
bool pdf_plot_clip(const struct rect *clip)
{
#ifdef PDF_DEBUG
- LOG("%d %d %d %d", clip->x0, clip->y0, clip->x1, clip->y1);
+ NSLOG(netsurf, INFO, "%d %d %d %d", clip->x0, clip->y0, clip->x1,
+ clip->y1);
#endif
/*Normalize cllipping area - to prevent overflows.
@@ -314,7 +317,7 @@ bool pdf_plot_text(int x, int y, const char *text, size_t length,
const plot_font_style_t *fstyle)
{
#ifdef PDF_DEBUG
- LOG(". %d %d %.*s", x, y, (int)length, text);
+ NSLOG(netsurf, INFO, ". %d %d %.*s", x, y, (int)length, text);
#endif
char *word;
HPDF_Font pdf_font;
@@ -347,7 +350,7 @@ bool pdf_plot_text(int x, int y, const char *text, size_t length,
bool pdf_plot_disc(int x, int y, int radius, const plot_style_t *style)
{
#ifdef PDF_DEBUG
- LOG(".");
+ NSLOG(netsurf, INFO, ".");
#endif
if (style->fill_type != PLOT_OP_TYPE_NONE) {
apply_clip_and_mode(false,
@@ -378,7 +381,8 @@ bool pdf_plot_disc(int x, int y, int radius, const plot_style_t *style)
bool pdf_plot_arc(int x, int y, int radius, int angle1, int angle2, const plot_style_t *style)
{
#ifdef PDF_DEBUG
- LOG("%d %d %d %d %d %X", x, y, radius, angle1, angle2, style->stroke_colour);
+ NSLOG(netsurf, INFO, "%d %d %d %d %d %X", x, y, radius, angle1,
+ angle2, style->stroke_colour);
#endif
/* FIXME: line width 1 is ok ? */
@@ -406,7 +410,8 @@ bool pdf_plot_bitmap_tile(int x, int y, int width, int height,
HPDF_REAL max_width, max_height;
#ifdef PDF_DEBUG
- LOG("%d %d %d %d %p 0x%x", x, y, width, height, bitmap, bg);
+ NSLOG(netsurf, INFO, "%d %d %d %d %p 0x%x", x, y, width, height,
+ bitmap, bg);
#endif
if (width == 0 || height == 0)
return true;
@@ -483,7 +488,8 @@ HPDF_Image pdf_extract_image(struct bitmap *bitmap)
rgb_buffer = (unsigned char *)malloc(3 * img_width * img_height);
alpha_buffer = (unsigned char *)malloc(img_width * img_height);
if (rgb_buffer == NULL || alpha_buffer == NULL) {
- LOG("Not enough memory to create RGB buffer");
+ NSLOG(netsurf, INFO,
+ "Not enough memory to create RGB buffer");
free(rgb_buffer);
free(alpha_buffer);
return NULL;
@@ -607,7 +613,7 @@ bool pdf_plot_path(const float *p, unsigned int n, colour fill, float width,
bool empty_path;
#ifdef PDF_DEBUG
- LOG(".");
+ NSLOG(netsurf, INFO, ".");
#endif
if (n == 0)
@@ -649,7 +655,7 @@ bool pdf_plot_path(const float *p, unsigned int n, colour fill, float width,
i += 7;
empty_path = false;
} else {
- LOG("bad path command %f", p[i]);
+ NSLOG(netsurf, INFO, "bad path command %f", p[i]);
return false;
}
}
@@ -685,7 +691,7 @@ bool pdf_begin(struct print_settings *print_settings)
HPDF_Free(pdf_doc);
pdf_doc = HPDF_New(error_handler, NULL);
if (!pdf_doc) {
- LOG("Error creating pdf_doc");
+ NSLOG(netsurf, INFO, "Error creating pdf_doc");
return false;
}
@@ -708,7 +714,7 @@ bool pdf_begin(struct print_settings *print_settings)
pdf_page = NULL;
#ifdef PDF_DEBUG
- LOG("pdf_begin finishes");
+ NSLOG(netsurf, INFO, "pdf_begin finishes");
#endif
return true;
}
@@ -717,7 +723,7 @@ bool pdf_begin(struct print_settings *print_settings)
bool pdf_next_page(void)
{
#ifdef PDF_DEBUG
- LOG("pdf_next_page begins");
+ NSLOG(netsurf, INFO, "pdf_next_page begins");
#endif
clip_update_needed = false;
if (pdf_page != NULL) {
@@ -745,7 +751,7 @@ bool pdf_next_page(void)
pdfw_gs_save(pdf_page);
#ifdef PDF_DEBUG
- LOG("%f %f", page_width, page_height);
+ NSLOG(netsurf, INFO, "%f %f", page_width, page_height);
#endif
return true;
@@ -755,7 +761,7 @@ bool pdf_next_page(void)
void pdf_end(void)
{
#ifdef PDF_DEBUG
- LOG("pdf_end begins");
+ NSLOG(netsurf, INFO, "pdf_end begins");
#endif
clip_update_needed = false;
if (pdf_page != NULL) {
@@ -780,7 +786,7 @@ void pdf_end(void)
else
save_pdf(settings->output);
#ifdef PDF_DEBUG
- LOG("pdf_end finishes");
+ NSLOG(netsurf, INFO, "pdf_end finishes");
#endif
}
@@ -819,7 +825,8 @@ nserror save_pdf(const char *path)
static void error_handler(HPDF_STATUS error_no, HPDF_STATUS detail_no,
void *user_data)
{
- LOG("ERROR:\n\terror_no=%x\n\tdetail_no=%d\n", (HPDF_UINT)error_no, (HPDF_UINT)detail_no);
+ NSLOG(netsurf, INFO, "ERROR:\n\terror_no=%x\n\tdetail_no=%d\n",
+ (HPDF_UINT)error_no, (HPDF_UINT)detail_no);
#ifdef PDF_DEBUG
exit(1);
#endif
diff --git a/desktop/save_text.c b/desktop/save_text.c
index e63c96eb9..a86f173b0 100644
--- a/desktop/save_text.c
+++ b/desktop/save_text.c
@@ -32,8 +32,8 @@
#include "utils/utf8.h"
#include "utils/utils.h"
#include "netsurf/content.h"
-#include "render/box.h"
-#include "render/html.h"
+#include "html/box.h"
+#include "html/html_save.h"
#include "netsurf/utf8.h"
#include "desktop/gui_internal.h"
@@ -75,7 +75,8 @@ void save_as_text(struct hlcache_handle *c, char *path)
free(save.block);
if (ret != NSERROR_OK) {
- LOG("failed to convert to local encoding, return %d", ret);
+ NSLOG(netsurf, INFO,
+ "failed to convert to local encoding, return %d", ret);
return;
}
@@ -84,12 +85,13 @@ void save_as_text(struct hlcache_handle *c, char *path)
int res = fputs(result, out);
if (res < 0) {
- LOG("Warning: write failed");
+ NSLOG(netsurf, INFO, "Warning: write failed");
}
res = fputs("\n", out);
if (res < 0) {
- LOG("Warning: failed writing trailing newline");
+ NSLOG(netsurf, INFO,
+ "Warning: failed writing trailing newline");
}
fclose(out);
diff --git a/desktop/scrollbar.c b/desktop/scrollbar.c
index 9a4d70fe4..af5536ba4 100644
--- a/desktop/scrollbar.c
+++ b/desktop/scrollbar.c
@@ -18,8 +18,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- * Scrollbar widget (implementation).
+/**
+ * \file
+ * implementation of scrollbar widget.
*/
#include <stdbool.h>
@@ -36,44 +37,65 @@
#include "desktop/system_colour.h"
#include "desktop/scrollbar.h"
+/**
+ * Scrollbar context
+ */
struct scrollbar {
- bool horizontal; /* Horizontal scrollbar if true, else vertical
- */
- int length; /* Length of the scrollbar widget */
-
- int full_size; /* Length of the full scrollable area */
- int visible_size; /* Length visible part of the scrollable area */
-
- int offset; /* Current scroll offset to visible area */
-
- int bar_pos; /* Position of the scrollbar */
- int bar_len; /* Length of the scrollbar */
-
- scrollbar_client_callback client_callback; /* Callback receiving
- * scrollbar events */
- void *client_data; /* User data passed to the callback */
-
- bool dragging; /* Flag indicating drag at progess */
- int drag_start_coord; /* Coordinate value at drag start */
- int drag_start_pos; /* Scrollbar offset or bar_pos at drag start */
- bool drag_content; /* Flag indicating that the drag corresponds to
- * a dragged content area, rather than a dragged
- * scrollbar. */
+ /** Horizontal scrollbar if true, else vertical */
+ bool horizontal;
+ /** Length of the scrollbar widget */
+ int length;
+
+ /** Length of the full scrollable area */
+ int full_size;
+ /** Length visible part of the scrollable area */
+ int visible_size;
+
+ /** Current scroll offset to visible area */
+ int offset;
+
+ /** Position of the scrollbar */
+ int bar_pos;
+ /** Length of the scrollbar */
+ int bar_len;
+
+ /** Callback receiving scrollbar events */
+ scrollbar_client_callback client_callback;
+ /** User data passed to the callback */
+ void *client_data;
+
+ /** Flag indicating drag at progess */
+ bool dragging;
+ /** Coordinate value at drag start */
+ int drag_start_coord;
+ /** Scrollbar offset or bar_pos at drag start */
+ int drag_start_pos;
+ /** Flag indicating that the drag corresponds to a dragged
+ * content area, rather than a dragged scrollbar.
+ */
+ bool drag_content;
- struct scrollbar *pair; /* Parpendicular scrollbar, or NULL */
- bool pair_drag; /* Flag indicating that the current drag affects
- the perpendicular scrollbar too */
+ /** Parpendicular scrollbar, or NULL */
+ struct scrollbar *pair;
+ /** Flag indicating that the current drag affects the
+ * perpendicular scrollbar too
+ */
+ bool pair_drag;
};
/*
- * Exported function. Documented in desktop/scrollbar.h
+ * Exported interface. Documented in desktop/scrollbar.h
*/
-nserror scrollbar_create(bool horizontal, int length, int full_size,
- int visible_size, void *client_data,
- scrollbar_client_callback client_callback,
- struct scrollbar **s)
+nserror
+scrollbar_create(bool horizontal,
+ int length,
+ int full_size,
+ int visible_size,
+ void *client_data,
+ scrollbar_client_callback client_callback,
+ struct scrollbar **s)
{
struct scrollbar *scrollbar;
int well_length;
@@ -95,7 +117,7 @@ nserror scrollbar_create(bool horizontal, int length, int full_size,
well_length = length - 2 * SCROLLBAR_WIDTH;
scrollbar->bar_len = (full_size == 0) ? 0 :
- ((well_length * visible_size) / full_size);
+ ((well_length * visible_size) / full_size);
scrollbar->client_callback = client_callback;
scrollbar->client_data = client_data;
@@ -110,49 +132,49 @@ nserror scrollbar_create(bool horizontal, int length, int full_size,
/*
- * Exported function. Documented in scrollbar.h
+ * Exported interface. Documented in scrollbar.h
*/
void scrollbar_destroy(struct scrollbar *s)
{
- if (s->pair != NULL)
+ if (s->pair != NULL) {
s->pair->pair = NULL;
+ }
free(s);
}
/**
- * Draw an outline rectangle common to a several scrollbar elements.
+ * Draw an outline rectangle common to several scrollbar elements.
*
- * \param x0 left border of the outline
- * \param y0 top border of the outline
- * \param x1 right border of the outline
- * \param y1 bottom border of the outline
- * \param c base colour of the outline, the other colours are created by
- * lightening or darkening this one
- * \param ctx current redraw context
+ * \param ctx current redraw context
+ * \param area the area of the scrollbar
+ * \param c base colour of the outline, the other colours are created by
+ * lightening or darkening this one
* \param inset true for inset outline, false for an outset one
- * \return
+ * \return NSERROR_OK on success else error code
*/
-
-static inline bool scrollbar_redraw_scrollbar_rectangle(int x0, int y0,
- int x1, int y1, colour c, bool inset,
- const struct redraw_context *ctx)
+static inline nserror
+scrollbar_rectangle(const struct redraw_context *ctx,
+ struct rect *area,
+ colour c,
+ bool inset)
{
- const struct plotter_table *plot = ctx->plot;
+ struct rect line;
+ nserror res;
static plot_style_t c0 = {
.stroke_type = PLOT_OP_TYPE_SOLID,
- .stroke_width = 1,
+ .stroke_width = plot_style_int_to_fixed(1),
};
static plot_style_t c1 = {
.stroke_type = PLOT_OP_TYPE_SOLID,
- .stroke_width = 1,
+ .stroke_width = plot_style_int_to_fixed(1),
};
static plot_style_t c2 = {
.stroke_type = PLOT_OP_TYPE_SOLID,
- .stroke_width = 1,
+ .stroke_width = plot_style_int_to_fixed(1),
};
if (inset) {
@@ -165,225 +187,338 @@ static inline bool scrollbar_redraw_scrollbar_rectangle(int x0, int y0,
c2.stroke_colour = blend_colour(c0.stroke_colour, c1.stroke_colour);
/* Plot the outline */
- if (!plot->line(x0, y0, x1, y0, &c0)) return false;
- if (!plot->line(x1, y0, x1, y1 + 1, &c1)) return false;
- if (!plot->line(x1, y0, x1, y0 + 1, &c2)) return false;
- if (!plot->line(x1, y1, x0, y1, &c1)) return false;
- if (!plot->line(x0, y1, x0, y0, &c0)) return false;
- if (!plot->line(x0, y1, x0, y1 + 1, &c2)) return false;
- return true;
+ line.x0 = area->x0; line.y0 = area->y0;
+ line.x1 = area->x1; line.y1 = area->y0;
+ res = ctx->plot->line(ctx, &c0, &line);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ line.x0 = area->x1; line.y0 = area->y0;
+ line.x1 = area->x1; line.y1 = area->y1 + 1;
+ res = ctx->plot->line(ctx, &c1, &line);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ line.x0 = area->x1; line.y0 = area->y0;
+ line.x1 = area->x1; line.y1 = area->y0 + 1;
+ res = ctx->plot->line(ctx, &c2, &line);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ line.x0 = area->x1; line.y0 = area->y1;
+ line.x1 = area->x0; line.y1 = area->y1;
+ res = ctx->plot->line(ctx, &c1, &line);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ line.x0 = area->x0; line.y0 = area->y1;
+ line.x1 = area->x0; line.y1 = area->y0;
+ res = ctx->plot->line(ctx, &c0, &line);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ line.x0 = area->x0; line.y0 = area->y1;
+ line.x1 = area->x0; line.y1 = area->y1 + 1;
+ res = ctx->plot->line(ctx, &c2, &line);
+
+ return res;
}
/*
- * Exported function. Documented in scrollbar.h
+ * Exported interface. Documented in scrollbar.h
*/
-bool scrollbar_redraw(struct scrollbar *s, int x, int y,
- const struct rect *clip, float scale,
- const struct redraw_context *ctx)
+nserror
+scrollbar_redraw(struct scrollbar *s,
+ int x, int y,
+ const struct rect *clip,
+ float scale,
+ const struct redraw_context *ctx)
{
- const struct plotter_table *plot = ctx->plot;
int w = SCROLLBAR_WIDTH;
int bar_pos, bar_c0, bar_c1;
int v[6]; /* array of triangle vertices */
- int x0, y0, x1, y1;
-
- 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");
+ struct rect area;
+ struct rect rect;
+ nserror res;
plot_style_t bg_fill_style = {
.fill_type = PLOT_OP_TYPE_SOLID,
- .fill_colour = bg_fill_colour
};
plot_style_t fg_fill_style = {
.fill_type = PLOT_OP_TYPE_SOLID,
- .fill_colour = fg_fill_colour
};
plot_style_t arrow_fill_style = {
.fill_type = PLOT_OP_TYPE_SOLID,
- .fill_colour = arrow_fill_colour
};
- x0 = x;
- y0 = y;
- x1 = x + (s->horizontal ? s->length : SCROLLBAR_WIDTH) - 1;
- y1 = y + (s->horizontal ? SCROLLBAR_WIDTH : s->length) - 1;
+ res = ns_system_colour_char("Scrollbar", &bg_fill_style.fill_colour);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ res = ns_system_colour_char("ButtonFace", &fg_fill_style.fill_colour);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ res = ns_system_colour_char("ButtonText", &arrow_fill_style.fill_colour);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ area.x0 = x;
+ area.y0 = y;
+ area.x1 = x + (s->horizontal ? s->length : SCROLLBAR_WIDTH) - 1;
+ area.y1 = y + (s->horizontal ? SCROLLBAR_WIDTH : s->length) - 1;
bar_pos = s->bar_pos;
- bar_c1 = (s->horizontal ? x0 : y0) + SCROLLBAR_WIDTH +
- s->bar_pos + s->bar_len - 1;
+ bar_c1 = (s->horizontal ? area.x0 : area.y0) + SCROLLBAR_WIDTH +
+ s->bar_pos + s->bar_len - 1;
if (scale != 1.0) {
w *= scale;
- x0 *= scale;
- y0 *= scale;
- x1 *= scale;
- y1 *= scale;
+ area.x0 *= scale;
+ area.y0 *= scale;
+ area.x1 *= scale;
+ area.y1 *= scale;
bar_pos *= scale;
bar_c1 *= scale;
}
- bar_c0 = (s->horizontal ? x0 : y0) + w + bar_pos;
+ bar_c0 = (s->horizontal ? area.x0 : area.y0) + w + bar_pos;
- if (x1 < clip->x0 || y1 < clip->y0 || clip->x1 < x0 || clip->y1 < y0)
- /* scrollbar is outside the clipping rectangle, nothing to
- * render */
- return true;
+ /* if scrollbar is outside the clipping rectangle, nothing to render */
+ if ((area.x1 < clip->x0) ||
+ (area.y1 < clip->y0) ||
+ (clip->x1 < area.x0) ||
+ (clip->y1 < area.y0)) {
+ return NSERROR_OK;
+ }
-
if (s->horizontal) {
/* scrollbar is horizontal */
-
+
/* scrollbar outline */
- if (!scrollbar_redraw_scrollbar_rectangle(x0, y0, x1, y1,
- bg_fill_colour, true, ctx))
- return false;
+ res = scrollbar_rectangle(ctx, &area,
+ bg_fill_style.fill_colour, true);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
/* left arrow icon border */
- if (!scrollbar_redraw_scrollbar_rectangle(x0 + 1,
- y0 + 1,
- x0 + w - 2,
- y1 - 1,
- fg_fill_colour, false, ctx))
- return false;
+ rect.x0 = area.x0 + 1;
+ rect.y0 = area.y0 + 1;
+ rect.x1 = area.x0 + w - 2;
+ rect.y1 = area.y1 - 1;
+ res = scrollbar_rectangle(ctx, &rect,
+ fg_fill_style.fill_colour, false);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
/* left arrow icon background */
- if (!plot->rectangle(x0 + 2,
- y0 + 2,
- x0 + w - 2,
- y1 - 1,
- &fg_fill_style))
- return false;
+ rect.x0 = area.x0 + 2;
+ rect.y0 = area.y0 + 2;
+ rect.x1 = area.x0 + w - 2;
+ rect.y1 = area.y1 - 1;
+ res = ctx->plot->rectangle(ctx, &fg_fill_style, &rect);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
/* left arrow */
- v[0] = x0 + w / 4;
- v[1] = y0 + w / 2;
- v[2] = x0 + w * 3 / 4;
- v[3] = y0 + w / 4;
- v[4] = x0 + w * 3 / 4;
- v[5] = y0 + w * 3 / 4;
- if (!plot->polygon(v, 3, &arrow_fill_style))
- return false;
+ v[0] = area.x0 + w / 4;
+ v[1] = area.y0 + w / 2;
+ v[2] = area.x0 + w * 3 / 4;
+ v[3] = area.y0 + w / 4;
+ v[4] = area.x0 + w * 3 / 4;
+ v[5] = area.y0 + w * 3 / 4;
+ res = ctx->plot->polygon(ctx, &arrow_fill_style, v, 3);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
/* scrollbar well background */
- if (!plot->rectangle(x0 + w - 1,
- y0 + 1,
- x1 - w + 2,
- y1,
- &bg_fill_style))
- return false;
+ rect.x0 = area.x0 + w - 1;
+ rect.y0 = area.y0 + 1;
+ rect.x1 = area.x1 - w + 2;
+ rect.y1 = area.y1;
+ res = ctx->plot->rectangle(ctx, &bg_fill_style, &rect);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
/* scrollbar position indicator bar */
- if (!scrollbar_redraw_scrollbar_rectangle(bar_c0,
- y0 + 1,
- bar_c1,
- y1 - 1,
- fg_fill_colour, false, ctx))
- return false;
- if (!plot->rectangle(bar_c0 + 1,
- y0 + 2,
- bar_c1,
- y1 - 1,
- &fg_fill_style))
- return false;
+ rect.x0 = bar_c0;
+ rect.y0 = area.y0 + 1;
+ rect.x1 = bar_c1;
+ rect.y1 = area.y1 - 1;
+ res = scrollbar_rectangle(ctx, &rect,
+ fg_fill_style.fill_colour, false);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ rect.x0 = bar_c0 + 1;
+ rect.y0 = area.y0 + 2;
+ rect.x1 = bar_c1;
+ rect.y1 = area.y1 - 1;
+ res = ctx->plot->rectangle(ctx, &fg_fill_style, &rect);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
/* right arrow icon border */
- if (!scrollbar_redraw_scrollbar_rectangle(x1 - w + 2,
- y0 + 1,
- x1 - 1,
- y1 - 1,
- fg_fill_colour, false, ctx))
- return false;
+ rect.x0 = area.x1 - w + 2;
+ rect.y0 = area.y0 + 1;
+ rect.x1 = area.x1 - 1;
+ rect.y1 = area.y1 - 1;
+ res = scrollbar_rectangle(ctx, &rect,
+ fg_fill_style.fill_colour, false);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
/* right arrow icon background */
- if (!plot->rectangle(x1 - w + 3,
- y0 + 2,
- x1 - 1,
- y1 - 1,
- &fg_fill_style))
- return false;
+ rect.x0 = area.x1 - w + 3;
+ rect.y0 = area.y0 + 2;
+ rect.x1 = area.x1 - 1;
+ rect.y1 = area.y1 - 1;
+ res = ctx->plot->rectangle(ctx, &fg_fill_style, &rect);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
/* right arrow */
- v[0] = x1 - w / 4 + 1;
- v[1] = y0 + w / 2;
- v[2] = x1 - w * 3 / 4 + 1;
- v[3] = y0 + w / 4;
- v[4] = x1 - w * 3 / 4 + 1;
- v[5] = y0 + w * 3 / 4;
- if (!plot->polygon(v, 3, &arrow_fill_style))
- return false;
+ v[0] = rect.x1 - w / 4 + 1;
+ v[1] = rect.y0 + w / 2;
+ v[2] = rect.x1 - w * 3 / 4 + 1;
+ v[3] = rect.y0 + w / 4;
+ v[4] = rect.x1 - w * 3 / 4 + 1;
+ v[5] = rect.y0 + w * 3 / 4;
+ res = ctx->plot->polygon(ctx, &arrow_fill_style, v, 3);
+ if (res != NSERROR_OK) {
+ return res;
+ }
} else {
/* scrollbar is vertical */
-
+
/* outline */
- if (!scrollbar_redraw_scrollbar_rectangle(x0, y0, x1, y1,
- bg_fill_colour, true, ctx))
- return false;
- /* top arrow background */
- if (!scrollbar_redraw_scrollbar_rectangle(x0 + 1,
- y0 + 1,
- x1 - 1,
- y0 + w - 2,
- fg_fill_colour, false, ctx))
- return false;
- if (!plot->rectangle(x0 + 2,
- y0 + 2,
- x1 - 1,
- y0 + w - 2,
- &fg_fill_style))
- return false;
+ res = scrollbar_rectangle(ctx, &area,
+ bg_fill_style.fill_colour, true);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ /* top arrow border */
+ rect.x0 = area.x0 + 1;
+ rect.y0 = area.y0 + 1;
+ rect.x1 = area.x1 - 1;
+ rect.y1 = area.y0 + w - 2;
+ res = scrollbar_rectangle(ctx, &rect,
+ fg_fill_style.fill_colour, false);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ /* top arrow background */
+ rect.x0 = area.x0 + 2;
+ rect.y0 = area.y0 + 2;
+ rect.x1 = area.x1 - 1;
+ rect.y1 = area.y0 + w - 2;
+ res = ctx->plot->rectangle(ctx, &fg_fill_style, &rect);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
/* up arrow */
- v[0] = x0 + w / 2;
- v[1] = y0 + w / 4;
- v[2] = x0 + w / 4;
- v[3] = y0 + w * 3 / 4;
- v[4] = x0 + w * 3 / 4;
- v[5] = y0 + w * 3 / 4;
- if (!plot->polygon(v, 3, &arrow_fill_style))
- return false;
+ v[0] = area.x0 + w / 2;
+ v[1] = area.y0 + w / 4;
+ v[2] = area.x0 + w / 4;
+ v[3] = area.y0 + w * 3 / 4;
+ v[4] = area.x0 + w * 3 / 4;
+ v[5] = area.y0 + w * 3 / 4;
+ res = ctx->plot->polygon(ctx, &arrow_fill_style, v, 3);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
/* scrollbar well background */
- if (!plot->rectangle(x0 + 1,
- y0 + w - 1,
- x1,
- y1 - w + 2,
- &bg_fill_style))
- return false;
+ rect.x0 = area.x0 + 1;
+ rect.y0 = area.y0 + w - 1;
+ rect.x1 = area.x1;
+ rect.y1 = area.y1 - w + 2;
+ res = ctx->plot->rectangle(ctx, &bg_fill_style, &rect);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
/* scrollbar position indicator bar */
- if (!scrollbar_redraw_scrollbar_rectangle(x0 + 1,
- bar_c0,
- x1 - 1,
- bar_c1,
- fg_fill_colour, false, ctx))
- return false;
- if (!plot->rectangle(x0 + 2,
- bar_c0 + 1,
- x1 - 1,
- bar_c1,
- &fg_fill_style))
- return false;
- /* bottom arrow background */
- if (!scrollbar_redraw_scrollbar_rectangle(x0 + 1,
- y1 - w + 2,
- x1 - 1,
- y1 - 1,
- fg_fill_colour, false, ctx))
- return false;
- if (!plot->rectangle(x0 + 2,
- y1 - w + 3,
- x1 - 1,
- y1 - 1,
- &fg_fill_style))
- return false;
+ rect.x0 = area.x0 + 1;
+ rect.y0 = bar_c0;
+ rect.x1 = area.x1 - 1;
+ rect.y1 = bar_c1;
+ res = scrollbar_rectangle(ctx, &rect,
+ fg_fill_style.fill_colour, false);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ rect.x0 = area.x0 + 2;
+ rect.y0 = bar_c0 + 1;
+ rect.x1 = area.x1 - 1;
+ rect.y1 = bar_c1;
+ res = ctx->plot->rectangle(ctx, &fg_fill_style, &rect);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ /* down arrow icon border */
+ rect.x0 = area.x0 + 1;
+ rect.y0 = area.y1 - w + 2;
+ rect.x1 = area.x1 - 1;
+ rect.y1 = area.y1 - 1;
+ res = scrollbar_rectangle(ctx, &rect,
+ fg_fill_style.fill_colour, false);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ /* down arrow icon background */
+ rect.x0 = area.x0 + 2;
+ rect.y0 = area.y1 - w + 3;
+ rect.x1 = area.x1 - 1;
+ rect.y1 = area.y1 - 1;
+ res = ctx->plot->rectangle(ctx, &fg_fill_style, &rect);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
/* down arrow */
- v[0] = x0 + w / 2;
- v[1] = y1 - w / 4 + 1;
- v[2] = x0 + w / 4;
- v[3] = y1 - w * 3 / 4 + 1;
- v[4] = x0 + w * 3 / 4;
- v[5] = y1 - w * 3 / 4 + 1;
- if (!plot->polygon(v, 3, &arrow_fill_style))
- return false;
+ v[0] = area.x0 + w / 2;
+ v[1] = area.y1 - w / 4 + 1;
+ v[2] = area.x0 + w / 4;
+ v[3] = area.y1 - w * 3 / 4 + 1;
+ v[4] = area.x0 + w * 3 / 4;
+ v[5] = area.y1 - w * 3 / 4 + 1;
+ res = ctx->plot->polygon(ctx, &arrow_fill_style, v, 3);
+ if (res != NSERROR_OK) {
+ return res;
+ }
}
- return true;
+ return NSERROR_OK;
}
/*
- * Exported function. Documented in scrollbar.h
+ * Exported interface. Documented in scrollbar.h
*/
void scrollbar_set(struct scrollbar *s, int value, bool bar_pos)
{
@@ -391,46 +526,49 @@ void scrollbar_set(struct scrollbar *s, int value, bool bar_pos)
int old_offset = s->offset;
struct scrollbar_msg_data msg;
- if (value < 0)
+ if (value < 0) {
value = 0;
+ }
- if (s->full_size == s->visible_size)
+ if (s->full_size == s->visible_size) {
return;
+ }
well_length = s->length - 2 * SCROLLBAR_WIDTH;
if (bar_pos) {
- if (value > well_length - s->bar_len)
+ if (value > well_length - s->bar_len) {
s->bar_pos = well_length - s->bar_len;
- else
+ } else {
s->bar_pos = value;
+ }
s->offset = ((well_length - s->bar_len) < 1) ? 0 :
- (((s->full_size - s->visible_size) *
- s->bar_pos) / (well_length - s->bar_len));
+ (((s->full_size - s->visible_size) *
+ s->bar_pos) / (well_length - s->bar_len));
} else {
- if (value > s->full_size - s->visible_size)
+ if (value > s->full_size - s->visible_size) {
s->offset = s->full_size - s->visible_size;
- else
+ } else {
s->offset = value;
+ }
s->bar_pos = (s->full_size < 1) ? 0 :
- ((well_length * s->offset) / s->full_size);
+ ((well_length * s->offset) / s->full_size);
}
- if (s->offset == old_offset)
- /* Nothing happened */
- return;
-
- msg.scrollbar = s;
- msg.msg = SCROLLBAR_MSG_MOVED;
- msg.scroll_offset = s->offset;
- s->client_callback(s->client_data, &msg);
+ if (s->offset != old_offset) {
+ /* client callback if there was a chnage */
+ msg.scrollbar = s;
+ msg.msg = SCROLLBAR_MSG_MOVED;
+ msg.scroll_offset = s->offset;
+ s->client_callback(s->client_data, &msg);
+ }
}
/*
- * Exported function. Documented in scrollbar.h
+ * Exported interface. Documented in scrollbar.h
*/
bool scrollbar_scroll(struct scrollbar *s, int change)
{
@@ -438,9 +576,10 @@ bool scrollbar_scroll(struct scrollbar *s, int change)
int old_offset = s->offset;
struct scrollbar_msg_data msg;
- if (change == 0 || s->full_size <= s->visible_size)
+ if (change == 0 || s->full_size <= s->visible_size) {
/* zero scroll step, or unscrollable */
return false;
+ }
/* Convert named change values to appropriate pixel offset value */
switch (change) {
@@ -466,21 +605,23 @@ bool scrollbar_scroll(struct scrollbar *s, int change)
}
/* Get new offset */
- if (s->offset + change > s->full_size - s->visible_size)
+ if (s->offset + change > s->full_size - s->visible_size) {
s->offset = s->full_size - s->visible_size;
- else if (s->offset + change < 0)
+ } else if (s->offset + change < 0) {
s->offset = 0;
- else
+ } else {
s->offset += change;
+ }
- if (s->offset == old_offset)
+ if (s->offset == old_offset) {
/* Nothing happened */
return false;
+ }
/* Update scrollbar */
well_length = s->length - 2 * SCROLLBAR_WIDTH;
s->bar_pos = (s->full_size < 1) ? 0 :
- ((well_length * s->offset) / s->full_size);
+ ((well_length * s->offset) / s->full_size);
msg.scrollbar = s;
msg.msg = SCROLLBAR_MSG_MOVED;
@@ -492,41 +633,47 @@ bool scrollbar_scroll(struct scrollbar *s, int change)
/*
- * Exported function. Documented in scrollbar.h
+ * Exported interface. Documented in scrollbar.h
*/
int scrollbar_get_offset(struct scrollbar *s)
{
- if (s == NULL)
+ if (s == NULL) {
return 0;
+ }
return s->offset;
}
/*
- * Exported function. Documented in scrollbar.h
+ * Exported interface. Documented in scrollbar.h
*/
void scrollbar_set_extents(struct scrollbar *s, int length,
- int visible_size, int full_size)
+ int visible_size, int full_size)
{
int cur_excess = s->full_size - s->visible_size;
int well_length;
struct scrollbar_msg_data msg;
- if (length == s->length && visible_size == s->visible_size &&
- full_size == s->full_size) {
+ if (length == s->length &&
+ visible_size == s->visible_size &&
+ full_size == s->full_size) {
/* Nothing's changed. */
return;
}
- if (length != -1)
+ if (length != -1) {
s->length = length;
- if (visible_size != -1)
+ }
+ if (visible_size != -1) {
s->visible_size = visible_size;
- if (full_size != -1)
+ }
+ if (full_size != -1) {
s->full_size = full_size;
+ }
- if (s->full_size < s->visible_size)
+ if (s->full_size < s->visible_size) {
s->full_size = s->visible_size;
+ }
/* Update scroll offset (scaled in proportion with change in excess) */
if (cur_excess <= 0) {
@@ -553,7 +700,7 @@ void scrollbar_set_extents(struct scrollbar *s, int length,
/*
- * Exported function. Documented in scrollbar.h
+ * Exported interface. Documented in scrollbar.h
*/
bool scrollbar_is_horizontal(struct scrollbar *s)
{
@@ -568,12 +715,14 @@ bool scrollbar_is_horizontal(struct scrollbar *s)
* \param x the X coordinate of the drag start
* \param y the Y coordinate of the drag start
* \param content_drag whether this should be a reverse drag (used when the
- * user drags the content area, rather than the scrollbar)
+ * user drags the content area, rather than the scrollbar)
* \param pair whether the drag is a '2D' scroll
*/
-
-static void scrollbar_drag_start_internal(struct scrollbar *s, int x, int y,
- bool content_drag, bool pair)
+static void
+scrollbar_drag_start_internal(struct scrollbar *s,
+ int x, int y,
+ bool content_drag,
+ bool pair)
{
struct scrollbar_msg_data msg;
@@ -585,7 +734,7 @@ static void scrollbar_drag_start_internal(struct scrollbar *s, int x, int y,
msg.scrollbar = s;
- /* \todo - some proper numbers please! */
+ /** \todo some proper numbers please! */
if (s->horizontal) {
msg.x0 = -2048;
msg.x1 = 2048;
@@ -602,10 +751,10 @@ static void scrollbar_drag_start_internal(struct scrollbar *s, int x, int y,
s->pair_drag = true;
s->pair->drag_start_coord =
- s->pair->horizontal ? x : y;
+ s->pair->horizontal ? x : y;
s->pair->drag_start_pos = (content_drag) ? s->pair->offset :
- s->pair->bar_pos;
+ s->pair->bar_pos;
s->pair->dragging = true;
s->pair->drag_content = content_drag;
@@ -624,10 +773,12 @@ static void scrollbar_drag_start_internal(struct scrollbar *s, int x, int y,
/*
- * Exported function. Documented in scrollbar.h
+ * Exported interface. Documented in scrollbar.h
*/
-scrollbar_mouse_status scrollbar_mouse_action(struct scrollbar *s,
- browser_mouse_state mouse, int x, int y)
+scrollbar_mouse_status
+scrollbar_mouse_action(struct scrollbar *s,
+ browser_mouse_state mouse,
+ int x, int y)
{
int x0, y0, x1, y1;
int val;
@@ -638,13 +789,13 @@ scrollbar_mouse_status scrollbar_mouse_action(struct scrollbar *s,
* scrollbar indication bar to be launching actions on the scroll area
*/
bool but1 = ((mouse & BROWSER_MOUSE_PRESS_1) ||
- ((mouse & BROWSER_MOUSE_HOLDING_1) &&
- (mouse & BROWSER_MOUSE_DRAG_ON) &&
- !s->dragging));
+ ((mouse & BROWSER_MOUSE_HOLDING_1) &&
+ (mouse & BROWSER_MOUSE_DRAG_ON) &&
+ !s->dragging));
bool but2 = ((mouse & BROWSER_MOUSE_PRESS_2) ||
- ((mouse & BROWSER_MOUSE_HOLDING_2) &&
- (mouse & BROWSER_MOUSE_DRAG_ON) &&
- !s->dragging));
+ ((mouse & BROWSER_MOUSE_HOLDING_2) &&
+ (mouse & BROWSER_MOUSE_DRAG_ON) &&
+ !s->dragging));
h = s->horizontal;
@@ -659,88 +810,91 @@ scrollbar_mouse_status scrollbar_mouse_action(struct scrollbar *s,
}
- if (h)
+ if (h) {
val = x;
- else
+ } else {
val = y;
+ }
if (s->dragging) {
val -= s->drag_start_coord;
- if (s->drag_content)
+ if (s->drag_content) {
val = -val;
- if (val != 0)
+ }
+ if (val != 0) {
scrollbar_set(s, s->drag_start_pos + val,
- !(s->drag_content));
+ !(s->drag_content));
+ }
if (s->pair_drag) {
scrollbar_mouse_action(s->pair, mouse, x, y);
status = SCROLLBAR_MOUSE_BOTH;
- } else
+ } else {
status = h ? SCROLLBAR_MOUSE_HRZ : SCROLLBAR_MOUSE_VRT;
-
+ }
return status;
}
if (val < SCROLLBAR_WIDTH) {
/* left/up arrow */
-
+
status = h ? SCROLLBAR_MOUSE_LFT : SCROLLBAR_MOUSE_UP;
- if (but1)
+ if (but1) {
scrollbar_set(s, s->offset - SCROLLBAR_WIDTH, false);
- else if (but2)
+ } else if (but2) {
scrollbar_set(s, s->offset + SCROLLBAR_WIDTH, false);
-
+ }
} else if (val < SCROLLBAR_WIDTH + s->bar_pos) {
/* well between left/up arrow and bar */
status = h ? SCROLLBAR_MOUSE_PLFT : SCROLLBAR_MOUSE_PUP;
- if (but1)
+ if (but1) {
scrollbar_set(s, s->offset - s->length, false);
- else if (but2)
+ } else if (but2) {
scrollbar_set(s, s->offset + s->length, false);
-
+ }
} else if (val > s->length - SCROLLBAR_WIDTH) {
/* right/down arrow */
status = h ? SCROLLBAR_MOUSE_RGT : SCROLLBAR_MOUSE_DWN;
- if (but1)
+ if (but1) {
scrollbar_set(s, s->offset + SCROLLBAR_WIDTH, false);
- else if (but2)
+ } else if (but2) {
scrollbar_set(s, s->offset - SCROLLBAR_WIDTH, false);
-
- } else if (val > SCROLLBAR_WIDTH + s->bar_pos +
- s->bar_len) {
+ }
+ } else if (val > SCROLLBAR_WIDTH + s->bar_pos + s->bar_len) {
/* well between right/down arrow and bar */
status = h ? SCROLLBAR_MOUSE_PRGT : SCROLLBAR_MOUSE_PDWN;
- if (but1)
+ if (but1) {
scrollbar_set(s, s->offset + s->length, false);
- else if (but2)
+ } else if (but2) {
scrollbar_set(s, s->offset - s->length, false);
- }
- else {
+ }
+ } else {
/* scrollbar position indication bar */
-
+
status = h ? SCROLLBAR_MOUSE_HRZ : SCROLLBAR_MOUSE_VRT;
}
-
+
if (mouse & (BROWSER_MOUSE_DRAG_1 | BROWSER_MOUSE_DRAG_2) &&
- (val >= SCROLLBAR_WIDTH + s->bar_pos
- && val < SCROLLBAR_WIDTH + s->bar_pos +
- s->bar_len))
+ (val >= SCROLLBAR_WIDTH + s->bar_pos
+ && val < SCROLLBAR_WIDTH + s->bar_pos +
+ s->bar_len)) {
/* The mouse event is a drag start on the scrollbar position
* indication bar. */
scrollbar_drag_start_internal(s, x, y, false,
- (mouse & BROWSER_MOUSE_DRAG_2) ? true : false);
+ (mouse & BROWSER_MOUSE_DRAG_2) ? true : false);
+ }
return status;
}
/*
- * Exported function. Documented in scrollbar.h
+ * Exported interface. Documented in scrollbar.h
*/
const char *scrollbar_mouse_status_to_message(scrollbar_mouse_status status)
{
@@ -784,10 +938,10 @@ const char *scrollbar_mouse_status_to_message(scrollbar_mouse_status status)
/*
- * Exported function. Documented in scrollbar.h
+ * Exported interface. Documented in scrollbar.h
*/
void scrollbar_mouse_drag_end(struct scrollbar *s,
- browser_mouse_state mouse, int x, int y)
+ browser_mouse_state mouse, int x, int y)
{
struct scrollbar_msg_data msg;
int val, drag_start_pos;
@@ -797,10 +951,12 @@ void scrollbar_mouse_drag_end(struct scrollbar *s,
drag_start_pos = s->drag_start_pos;
val = (s->horizontal ? x : y) - s->drag_start_coord;
- if (s->drag_content)
+ if (s->drag_content) {
val = -val;
- if (val != 0)
+ }
+ if (val != 0) {
scrollbar_set(s, drag_start_pos + val, !(s->drag_content));
+ }
s->dragging = false;
s->drag_content = false;
@@ -811,11 +967,13 @@ void scrollbar_mouse_drag_end(struct scrollbar *s,
drag_start_pos = s->pair->drag_start_pos;
val = (s->pair->horizontal ? x : y) - s->pair->drag_start_coord;
- if (s->pair->drag_content)
+ if (s->pair->drag_content) {
val = -val;
- if (val != 0)
+ }
+ if (val != 0) {
scrollbar_set(s->pair, drag_start_pos + val,
- !(s->pair->drag_content));
+ !(s->pair->drag_content));
+ }
s->pair->dragging = false;
s->pair->drag_content = false;
@@ -828,7 +986,7 @@ void scrollbar_mouse_drag_end(struct scrollbar *s,
/*
- * Exported function. Documented in scrollbar.h
+ * Exported interface. Documented in scrollbar.h
*/
void scrollbar_start_content_drag(struct scrollbar *s, int x, int y)
{
@@ -837,13 +995,13 @@ void scrollbar_start_content_drag(struct scrollbar *s, int x, int y)
/*
- * Exported function. Documented in scrollbar.h
+ * Exported interface. Documented in scrollbar.h
*/
void scrollbar_make_pair(struct scrollbar *horizontal,
- struct scrollbar *vertical)
+ struct scrollbar *vertical)
{
assert(horizontal->horizontal &&
- !vertical->horizontal);
+ !vertical->horizontal);
horizontal->pair = vertical;
vertical->pair = horizontal;
@@ -851,10 +1009,9 @@ void scrollbar_make_pair(struct scrollbar *horizontal,
/*
- * Exported function. Documented in scrollbar.h
+ * Exported interface. Documented in scrollbar.h
*/
void *scrollbar_get_data(struct scrollbar *s)
{
return s->client_data;
}
-
diff --git a/desktop/scrollbar.h b/desktop/scrollbar.h
index d277be26c..fa5e167f2 100644
--- a/desktop/scrollbar.h
+++ b/desktop/scrollbar.h
@@ -16,12 +16,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- * Scrollbar widget (interface).
+/**
+ * \file
+ * Scrollbar widget interface.
+ *
+ * Scrollbar widgets used in frames code, not for frontend use
*/
-#ifndef _NETSURF_DESKTOP_SCROLLBAR_H_
-#define _NETSURF_DESKTOP_SCROLLBAR_H_
+#ifndef NETSURF_DESKTOP_SCROLLBAR_H
+#define NETSURF_DESKTOP_SCROLLBAR_H
#include <stdbool.h>
#include <limits.h>
@@ -29,23 +32,29 @@
#define SCROLLBAR_WIDTH 16
/* Region dependent values for scrollbar_scroll function */
-#define SCROLL_TOP INT_MIN
-#define SCROLL_PAGE_UP INT_MIN + 1
-#define SCROLL_PAGE_DOWN INT_MAX - 1
-#define SCROLL_BOTTOM INT_MAX
+#define SCROLL_TOP INT_MIN
+#define SCROLL_PAGE_UP (INT_MIN + 1)
+#define SCROLL_PAGE_DOWN (INT_MAX - 1)
+#define SCROLL_BOTTOM INT_MAX
struct scrollbar;
+/**
+ * scrollbar message types
+ */
typedef enum {
- SCROLLBAR_MSG_MOVED, /* the scroll value has changed */
- SCROLLBAR_MSG_SCROLL_START, /* a scrollbar drag has started, all
- * mouse events should be passed to
+ SCROLLBAR_MSG_MOVED, /**< the scroll value has changed */
+ SCROLLBAR_MSG_SCROLL_START, /**< a scrollbar drag has started, all
+ * mouse events should be passed to
* the scrollbar regardless of the
* coordinates
*/
- SCROLLBAR_MSG_SCROLL_FINISHED, /* cancel the above */
+ SCROLLBAR_MSG_SCROLL_FINISHED, /**< cancel a scrollbar drag */
} scrollbar_msg;
+/**
+ * scrollbar message context data
+ */
struct scrollbar_msg_data {
struct scrollbar *scrollbar;
scrollbar_msg msg;
@@ -53,9 +62,30 @@ struct scrollbar_msg_data {
int x0, y0, x1, y1;
};
+
+/**
+ * Scrollbar mouse input status flags
+ */
+typedef enum {
+ SCROLLBAR_MOUSE_NONE = 0, /**< Not relevant */
+ SCROLLBAR_MOUSE_USED = (1 << 0), /**< Took action with input */
+ SCROLLBAR_MOUSE_BOTH = (1 << 1), /**< Scrolling both bars */
+ SCROLLBAR_MOUSE_UP = (1 << 2), /**< Hover: scroll up */
+ SCROLLBAR_MOUSE_PUP = (1 << 3), /**< Hover: scroll page up */
+ SCROLLBAR_MOUSE_VRT = (1 << 4), /**< Hover: vert. drag bar */
+ SCROLLBAR_MOUSE_PDWN = (1 << 5), /**< Hover: scroll page down */
+ SCROLLBAR_MOUSE_DWN = (1 << 6), /**< Hover: scroll down */
+ SCROLLBAR_MOUSE_LFT = (1 << 7), /**< Hover: scroll left */
+ SCROLLBAR_MOUSE_PLFT = (1 << 8), /**< Hover: scroll page left */
+ SCROLLBAR_MOUSE_HRZ = (1 << 9), /**< Hover: horiz. drag bar */
+ SCROLLBAR_MOUSE_PRGT = (1 << 10), /**< Hover: scroll page right */
+ SCROLLBAR_MOUSE_RGT = (1 << 11) /**< Hover: scroll right */
+} scrollbar_mouse_status;
+
+
/**
* Client callback for the scrollbar.
- *
+ *
* \param client_data user data passed at scroll creation
* \param scrollbar_data scrollbar message data
*/
@@ -84,7 +114,7 @@ nserror scrollbar_create(bool horizontal, int length, int full_size,
/**
* Destroy a scrollbar.
*
- * \param s the scrollbar to be destroyed
+ * \param s the scrollbar to be destroyed
*/
void scrollbar_destroy(struct scrollbar *s);
@@ -97,9 +127,9 @@ void scrollbar_destroy(struct scrollbar *s);
* \param clip the clipping rectangle
* \param scale scale for the redraw
* \param ctx current redraw context
- * \return true on succes false otherwise
+ * \return NSERROR_OK on success otherwise error code
*/
-bool scrollbar_redraw(struct scrollbar *s, int x, int y,
+nserror scrollbar_redraw(struct scrollbar *s, int x, int y,
const struct rect *clip, float scale,
const struct redraw_context *ctx);
@@ -125,8 +155,8 @@ bool scrollbar_scroll(struct scrollbar *s, int change);
/**
* Get the current scroll offset to the visible part of the full area.
*
- * \param s the scrollbar to get the scroll offset value from
- * \return current scroll offset
+ * \param s the scrollbar to get the scroll offset value from
+ * \return current scroll offset
*/
int scrollbar_get_offset(struct scrollbar *s);
@@ -150,22 +180,6 @@ void scrollbar_set_extents(struct scrollbar *s, int length,
*/
bool scrollbar_is_horizontal(struct scrollbar *s);
-/* Scrollbar mouse input status flags */
-typedef enum {
- SCROLLBAR_MOUSE_NONE = 0, /**< Not relevant */
- SCROLLBAR_MOUSE_USED = (1 << 0), /**< Took action with input */
- SCROLLBAR_MOUSE_BOTH = (1 << 1), /**< Scrolling both bars */
- SCROLLBAR_MOUSE_UP = (1 << 2), /**< Hover: scroll up */
- SCROLLBAR_MOUSE_PUP = (1 << 3), /**< Hover: scroll page up */
- SCROLLBAR_MOUSE_VRT = (1 << 4), /**< Hover: vert. drag bar */
- SCROLLBAR_MOUSE_PDWN = (1 << 5), /**< Hover: scroll page down */
- SCROLLBAR_MOUSE_DWN = (1 << 6), /**< Hover: scroll down */
- SCROLLBAR_MOUSE_LFT = (1 << 7), /**< Hover: scroll left */
- SCROLLBAR_MOUSE_PLFT = (1 << 8), /**< Hover: scroll page left */
- SCROLLBAR_MOUSE_HRZ = (1 << 9), /**< Hover: horiz. drag bar */
- SCROLLBAR_MOUSE_PRGT = (1 << 10), /**< Hover: scroll page right */
- SCROLLBAR_MOUSE_RGT = (1 << 11) /**< Hover: scroll right */
-} scrollbar_mouse_status;
/**
* Handle mouse actions other then drag ends.
@@ -179,6 +193,7 @@ typedef enum {
scrollbar_mouse_status scrollbar_mouse_action(struct scrollbar *s,
browser_mouse_state mouse, int x, int y);
+
/**
* Get a status bar message from a scrollbar mouse input status.
*
@@ -187,6 +202,7 @@ scrollbar_mouse_status scrollbar_mouse_action(struct scrollbar *s,
*/
const char *scrollbar_mouse_status_to_message(scrollbar_mouse_status status);
+
/**
* Handle end of mouse drags.
*
@@ -198,18 +214,21 @@ const char *scrollbar_mouse_status_to_message(scrollbar_mouse_status status);
void scrollbar_mouse_drag_end(struct scrollbar *s,
browser_mouse_state mouse, int x, int y);
+
/**
* Called when the content is being dragged to the scrollbars have to adjust.
+ *
* If the content has both scrollbars, and scrollbar_make_pair has beed called
* before, only the one scroll which will receive further mouse events has to be
* passed.
*
- * \param s one of the the scrollbars owned by the dragged content
- * \param x X coordinate of mouse during drag start
- * \param y Y coordinate of mouse during drag start
+ * \param s one of the the scrollbars owned by the dragged content
+ * \param x X coordinate of mouse during drag start
+ * \param y Y coordinate of mouse during drag start
*/
void scrollbar_start_content_drag(struct scrollbar *s, int x, int y);
+
/**
* Connect a horizontal and a vertical scrollbar into a pair so that they
* co-operate during 2D drags.
@@ -220,11 +239,12 @@ void scrollbar_start_content_drag(struct scrollbar *s, int x, int y);
void scrollbar_make_pair(struct scrollbar *horizontal,
struct scrollbar *vertical);
+
/**
* Get the scrollbar's client data
*
- * \param s the scrollbar to get the client data from
- * \return client data
+ * \param s the scrollbar to get the client data from
+ * \return client data
*/
void *scrollbar_get_data(struct scrollbar *s);
diff --git a/desktop/searchweb.c b/desktop/searchweb.c
index 29a998eb2..c07cac9d5 100644
--- a/desktop/searchweb.c
+++ b/desktop/searchweb.c
@@ -289,13 +289,19 @@ search_web_ico_callback(hlcache_handle *ico,
switch (event->type) {
case CONTENT_MSG_DONE:
- LOG("icon '%s' retrieved", nsurl_access(hlcache_handle_get_url(ico)));
+ NSLOG(netsurf, INFO, "icon '%s' retrieved",
+ 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);
+ NSLOG(netsurf, INFO, "icon %s error: %s",
+ nsurl_access(hlcache_handle_get_url(ico)),
+ event->data.error);
+ /* fall through */
+
+ case CONTENT_MSG_ERRORCODE:
hlcache_handle_release(ico);
/* clear reference to released handle */
provider->ico_handle = NULL;
@@ -438,7 +444,8 @@ default_ico_callback(hlcache_handle *ico,
switch (event->type) {
case CONTENT_MSG_DONE:
- LOG("default icon '%s' retrieved", nsurl_access(hlcache_handle_get_url(ico)));
+ NSLOG(netsurf, INFO, "default icon '%s' retrieved",
+ 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) {
@@ -449,7 +456,12 @@ default_ico_callback(hlcache_handle *ico,
break;
case CONTENT_MSG_ERROR:
- LOG("icon %s error: %s", nsurl_access(hlcache_handle_get_url(ico)), event->data.error);
+ NSLOG(netsurf, INFO, "icon %s error: %s",
+ nsurl_access(hlcache_handle_get_url(ico)),
+ event->data.error);
+ /* fall through */
+
+ case CONTENT_MSG_ERRORCODE:
hlcache_handle_release(ico);
/* clear reference to released handle */
ctx->default_ico_handle = NULL;
diff --git a/desktop/selection.c b/desktop/selection.c
index 7506af0ef..35eabb2a9 100644
--- a/desktop/selection.c
+++ b/desktop/selection.c
@@ -32,10 +32,10 @@
#include "utils/utf8.h"
#include "utils/utils.h"
#include "netsurf/form.h"
-#include "render/box.h"
-#include "render/html_internal.h"
-#include "render/font.h"
-#include "render/textplain.h"
+#include "html/box.h"
+#include "html/html_internal.h"
+#include "html/font.h"
+#include "text/textplain.h"
#include "netsurf/mouse.h"
#include "desktop/browser_private.h"
@@ -70,18 +70,20 @@ struct selection_string {
typedef bool (*seln_traverse_handler)(const char *text, size_t length,
- struct box *box, void *handle, const char *whitespace_text,
- size_t whitespace_length);
+ struct box *box, const nscss_len_ctx *len_ctx, void *handle,
+ const char *whitespace_text, size_t whitespace_length);
-static bool redraw_handler(const char *text, size_t length, struct box *box,
+static bool redraw_handler(const char *text, size_t length,
+ struct box *box, const nscss_len_ctx *len_ctx,
void *handle, const char *whitespace_text,
size_t whitespace_length);
static void selection_redraw(struct selection *s, unsigned start_idx,
unsigned end_idx);
static bool selected_part(struct box *box, unsigned start_idx, unsigned end_idx,
unsigned *start_offset, unsigned *end_offset);
-static bool traverse_tree(struct box *box, unsigned start_idx, unsigned end_idx,
+static bool traverse_tree(struct box *box, const nscss_len_ctx *len_ctx,
+ unsigned start_idx, unsigned end_idx,
seln_traverse_handler handler,
void *handle, save_text_whitespace *before, bool *first,
bool do_marker);
@@ -198,7 +200,10 @@ void selection_reinit(struct selection *s, struct box *root)
* \param root the root box for html document or NULL for text/plain
*/
-void selection_init(struct selection *s, struct box *root)
+void selection_init(
+ struct selection *s,
+ struct box *root,
+ const nscss_len_ctx *len_ctx)
{
if (s->defined)
selection_clear(s, true);
@@ -207,6 +212,13 @@ void selection_init(struct selection *s, struct box *root)
s->start_idx = 0;
s->end_idx = 0;
s->drag_state = DRAG_NONE;
+ if (len_ctx != NULL) {
+ s->len_ctx = *len_ctx;
+ } else {
+ s->len_ctx.vw = 0;
+ s->len_ctx.vh = 0;
+ s->len_ctx.root_style = NULL;
+ }
selection_reinit(s, root);
}
@@ -442,6 +454,7 @@ bool selected_part(struct box *box, unsigned start_idx, unsigned end_idx,
* for all boxes that lie (partially) within the given range
*
* \param box box subtree
+ * \param len_ctx Length conversion context.
* \param start_idx start of range within textual representation (bytes)
* \param end_idx end of range
* \param handler handler function to call
@@ -452,7 +465,9 @@ bool selected_part(struct box *box, unsigned start_idx, unsigned end_idx,
* \return false iff traversal abandoned part-way through
*/
-bool traverse_tree(struct box *box, unsigned start_idx, unsigned end_idx,
+bool traverse_tree(
+ struct box *box, const nscss_len_ctx *len_ctx,
+ unsigned start_idx, unsigned end_idx,
seln_traverse_handler handler,
void *handle, save_text_whitespace *before, bool *first,
bool do_marker)
@@ -473,9 +488,9 @@ bool traverse_tree(struct box *box, unsigned start_idx, unsigned end_idx,
if (box->list_marker) {
/* do the marker box before continuing with the rest of the
* list element */
- if (!traverse_tree(box->list_marker, start_idx, end_idx,
- handler, handle, before, first,
- true))
+ if (!traverse_tree(box->list_marker, len_ctx,
+ start_idx, end_idx, handler, handle,
+ before, first, true))
return false;
}
@@ -506,7 +521,7 @@ bool traverse_tree(struct box *box, unsigned start_idx, unsigned end_idx,
&end_offset)) {
if (!handler(box->text + start_offset, min(box->length,
end_offset) - start_offset,
- box, handle, whitespace_text,
+ box, len_ctx, handle, whitespace_text,
whitespace_length))
return false;
if (before) {
@@ -533,7 +548,7 @@ bool traverse_tree(struct box *box, unsigned start_idx, unsigned end_idx,
* the tree */
struct box *next = child->next;
- if (!traverse_tree(child, start_idx, end_idx,
+ if (!traverse_tree(child, len_ctx, start_idx, end_idx,
handler, handle, before, first, false))
return false;
@@ -568,14 +583,16 @@ static bool selection_traverse(struct selection *s,
if (s->root) {
/* HTML */
- return traverse_tree(s->root, s->start_idx, s->end_idx,
- handler, handle, &before, &first, false);
+ return traverse_tree(s->root, &s->len_ctx,
+ s->start_idx, s->end_idx,
+ handler, handle,
+ &before, &first, false);
}
/* Text */
text = textplain_get_raw_data(s->c, s->start_idx, s->end_idx, &length);
- if (text && !handler(text, length, NULL, handle, NULL, 0))
+ if (text && !handler(text, length, NULL, NULL, handle, NULL, 0))
return false;
return true;
@@ -597,8 +614,8 @@ static bool selection_traverse(struct selection *s,
*/
bool redraw_handler(const char *text, size_t length, struct box *box,
- void *handle, const char *whitespace_text,
- size_t whitespace_length)
+ const nscss_len_ctx *len_ctx, void *handle,
+ const char *whitespace_text, size_t whitespace_length)
{
if (box) {
struct rdw_info *r = (struct rdw_info*)handle;
@@ -606,7 +623,7 @@ bool redraw_handler(const char *text, size_t length, struct box *box,
int x, y;
plot_font_style_t fstyle;
- font_plot_style_from_css(box->style, &fstyle);
+ font_plot_style_from_css(len_ctx, box->style, &fstyle);
/* \todo - it should be possible to reduce the redrawn area by
* considering the 'text', 'length' and 'space' parameters */
@@ -652,7 +669,7 @@ void selection_redraw(struct selection *s, unsigned start_idx, unsigned end_idx)
rdw.inited = false;
if (s->root) {
- if (!traverse_tree(s->root, start_idx, end_idx,
+ if (!traverse_tree(s->root, &s->len_ctx, start_idx, end_idx,
redraw_handler, &rdw,
NULL, NULL, false))
return;
@@ -739,10 +756,11 @@ static bool selection_string_append(const char *text, size_t length, bool space,
/**
* Selection traversal routine for appending text to a string
*
- * \param text pointer to text being added, or NULL for newline
- * \param length length of text to be appended (bytes)
- * \param box pointer to text box, or NULL if from textplain
- * \param handle selection string to append to
+ * \param text pointer to text being added, or NULL for newline
+ * \param length length of text to be appended (bytes)
+ * \param box pointer to text box, or NULL if from textplain
+ * \param len_ctx Length conversion context
+ * \param handle selection string to append to
* \param whitespace_text whitespace to place before text for formatting
* may be NULL
* \param whitespace_length length of whitespace_text
@@ -750,7 +768,8 @@ static bool selection_string_append(const char *text, size_t length, bool space,
*/
static bool selection_copy_handler(const char *text, size_t length,
- struct box *box, void *handle, const char *whitespace_text,
+ struct box *box, const nscss_len_ctx *len_ctx,
+ void *handle, const char *whitespace_text,
size_t whitespace_length)
{
bool add_space = false;
@@ -771,7 +790,7 @@ static bool selection_copy_handler(const char *text, size_t length,
if (box->style != NULL) {
/* Override default font style */
- font_plot_style_from_css(box->style, &style);
+ font_plot_style_from_css(len_ctx, box->style, &style);
pstyle = &style;
} else {
/* If there's no style, there must be no text */
diff --git a/desktop/selection.h b/desktop/selection.h
index e2bc3b31d..2f3f6dcfe 100644
--- a/desktop/selection.h
+++ b/desktop/selection.h
@@ -25,6 +25,7 @@
#include <stdbool.h>
#include "netsurf/mouse.h"
+#include "content/handlers/css/utils.h"
struct box;
@@ -43,6 +44,7 @@ struct selection
{
struct content *c;
struct box *root;
+ nscss_len_ctx len_ctx;
unsigned max_idx; /* total bytes in text representation */
@@ -60,7 +62,10 @@ struct selection *selection_create(struct content *c, bool is_html);
void selection_prepare(struct selection *s, struct content *c, bool is_html);
void selection_destroy(struct selection *s);
-void selection_init(struct selection *s, struct box *root);
+void selection_init(
+ struct selection *s,
+ struct box *root,
+ const nscss_len_ctx *len_ctx);
void selection_reinit(struct selection *s, struct box *root);
/* struct box *selection_root(struct selection *s); */
diff --git a/desktop/sslcert_viewer.c b/desktop/sslcert_viewer.c
index 09a281c1c..f40af5968 100644
--- a/desktop/sslcert_viewer.c
+++ b/desktop/sslcert_viewer.c
@@ -17,8 +17,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- * SSL Certificate verification UI (implementation)
+/**
+ * \file
+ * SSL Certificate verification UI implementation
*/
#include <assert.h>
@@ -33,6 +34,9 @@
#include "utils/log.h"
#include "utils/utils.h"
+/**
+ * ssl certificate viewer data fields
+ */
enum sslcert_viewer_field {
SSLCERT_V_SUBJECT,
SSLCERT_V_SERIAL,
@@ -45,7 +49,10 @@ enum sslcert_viewer_field {
SSLCERT_V_N_FIELDS
};
-/** ssl certificate verification context. */
+
+/**
+ * ssl certificate verification context.
+ */
struct sslcert_session_data {
struct ssl_cert_info *certs; /**< Certificates */
unsigned long num; /**< Number of certificates in chain */
@@ -57,6 +64,10 @@ struct sslcert_session_data {
struct treeview_field_desc fields[SSLCERT_V_N_FIELDS];
};
+
+/**
+ * ssl certificate tree entry
+ */
struct sslcert_entry {
treeview_node *entry;
char version[24];
@@ -67,12 +78,11 @@ struct sslcert_entry {
/**
- * Free a sll certificate viewer entry's treeview field data.
+ * Free a ssl certificate viewer entry's treeview field data.
*
- * \param e Entry to free data from
+ * \param e Entry to free data from
*/
-static void sslcert_viewer_free_treeview_field_data(
- struct sslcert_entry *e)
+static void sslcert_viewer_free_treeview_field_data(struct sslcert_entry *e)
{
}
@@ -80,17 +90,17 @@ static void sslcert_viewer_free_treeview_field_data(
/**
* Build a sslcert viewer treeview field from given text
*
- * \param field SSL certificate treeview field to build
- * \param data SSL certificate entry field data to set
- * \param value Text to set in field, ownership yielded
- * \param ssl_d SSL certificate session data
+ * \param field SSL certificate treeview field to build
+ * \param data SSL certificate entry field data to set
+ * \param value Text to set in field, ownership yielded
+ * \param ssl_d SSL certificate session data
* \return NSERROR_OK on success, appropriate error otherwise
*/
-static inline nserror sslcert_viewer_field_builder(
- enum sslcert_viewer_field field,
- struct treeview_field_data *data,
- const char *value,
- struct sslcert_session_data *ssl_d)
+static inline nserror
+sslcert_viewer_field_builder(enum sslcert_viewer_field field,
+ struct treeview_field_data *data,
+ const char *value,
+ struct sslcert_session_data *ssl_d)
{
data->field = ssl_d->fields[field].field;
data->value = value;
@@ -103,15 +113,15 @@ static inline nserror sslcert_viewer_field_builder(
/**
* Set a sslcert viewer entry's data from the certificate.
*
- * \param e Entry to set up
- * \param cert Data associated with entry's certificate
- * \param ssl_d SSL certificate session data
+ * \param e Entry to set up
+ * \param cert Data associated with entry's certificate
+ * \param ssl_d SSL certificate session data
* \return NSERROR_OK on success, appropriate error otherwise
*/
-static nserror sslcert_viewer_set_treeview_field_data(
- struct sslcert_entry *e,
- const struct ssl_cert_info *cert,
- struct sslcert_session_data *ssl_d)
+static nserror
+sslcert_viewer_set_treeview_field_data(struct sslcert_entry *e,
+ const struct ssl_cert_info *cert,
+ struct sslcert_session_data *ssl_d)
{
unsigned int written;
@@ -121,39 +131,39 @@ static nserror sslcert_viewer_set_treeview_field_data(
/* Set the fields up */
sslcert_viewer_field_builder(SSLCERT_V_SUBJECT,
- &e->data[SSLCERT_V_SUBJECT],
- cert->subject, ssl_d);
+ &e->data[SSLCERT_V_SUBJECT],
+ cert->subject, ssl_d);
written = snprintf(e->serial, sizeof(e->serial), "%li", cert->serial);
assert(written < sizeof(e->serial));
sslcert_viewer_field_builder(SSLCERT_V_SERIAL,
- &e->data[SSLCERT_V_SERIAL],
- e->serial, ssl_d);
+ &e->data[SSLCERT_V_SERIAL],
+ e->serial, ssl_d);
written = snprintf(e->type, sizeof(e->type), "%i", cert->cert_type);
assert(written < sizeof(e->type));
sslcert_viewer_field_builder(SSLCERT_V_TYPE,
- &e->data[SSLCERT_V_TYPE],
- e->type, ssl_d);
+ &e->data[SSLCERT_V_TYPE],
+ e->type, ssl_d);
sslcert_viewer_field_builder(SSLCERT_V_VALID_UNTIL,
- &e->data[SSLCERT_V_VALID_UNTIL],
- cert->not_after, ssl_d);
+ &e->data[SSLCERT_V_VALID_UNTIL],
+ cert->not_after, ssl_d);
sslcert_viewer_field_builder(SSLCERT_V_VALID_FROM,
- &e->data[SSLCERT_V_VALID_FROM],
- cert->not_before, ssl_d);
+ &e->data[SSLCERT_V_VALID_FROM],
+ cert->not_before, ssl_d);
written = snprintf(e->version, sizeof(e->version),
- "%li", cert->version);
+ "%li", cert->version);
assert(written < sizeof(e->version));
sslcert_viewer_field_builder(SSLCERT_V_VERSION,
- &e->data[SSLCERT_V_VERSION],
- e->version, ssl_d);
+ &e->data[SSLCERT_V_VERSION],
+ e->version, ssl_d);
sslcert_viewer_field_builder(SSLCERT_V_ISSUER,
- &e->data[SSLCERT_V_ISSUER],
- cert->issuer, ssl_d);
+ &e->data[SSLCERT_V_ISSUER],
+ cert->issuer, ssl_d);
return NSERROR_OK;
}
@@ -162,12 +172,12 @@ static nserror sslcert_viewer_set_treeview_field_data(
/**
* Create a treeview node for a certificate
*
- * \param ssl_d SSL certificate session data
- * \param n Number of SSL certificate in chain, to make node for
- * \return true on success, false on memory exhaustion
+ * \param ssl_d SSL certificate session data
+ * \param n Number of SSL certificate in chain, to make node for
+ * \return NSERROR_OK on success otherwise error code.
*/
-static nserror sslcert_viewer_create_node(
- struct sslcert_session_data *ssl_d, int n)
+static nserror
+sslcert_viewer_create_node(struct sslcert_session_data *ssl_d, int n)
{
struct sslcert_entry *e;
const struct ssl_cert_info *cert = &(ssl_d->certs[n]);
@@ -187,8 +197,8 @@ static nserror sslcert_viewer_create_node(
/* Create the new treeview node */
err = treeview_create_node_entry(ssl_d->tree, &(e->entry),
- NULL, TREE_REL_FIRST_CHILD,
- e->data, e, TREE_OPTION_NONE);
+ NULL, TREE_REL_FIRST_CHILD,
+ e->data, e, TREE_OPTION_NONE);
if (err != NSERROR_OK) {
sslcert_viewer_free_treeview_field_data(e);
free(e);
@@ -200,10 +210,10 @@ static nserror sslcert_viewer_create_node(
/**
- * Initialise the treeview entry feilds
+ * Initialise the treeview entry fields
*
- * \param ssl_d SSL certificate session data
- * \return true on success, false on memory exhaustion
+ * \param ssl_d SSL certificate session data
+ * \return NSERROR_OK on success otherwise error code.
*/
static nserror sslcert_init_entry_fields(struct sslcert_session_data *ssl_d)
{
@@ -217,8 +227,8 @@ static nserror sslcert_init_entry_fields(struct sslcert_session_data *ssl_d)
label = "TreeviewLabelSubject";
label = messages_get(label);
if (lwc_intern_string(label, strlen(label),
- &ssl_d->fields[SSLCERT_V_SUBJECT].field) !=
- lwc_error_ok) {
+ &ssl_d->fields[SSLCERT_V_SUBJECT].field) !=
+ lwc_error_ok) {
goto error;
}
@@ -226,8 +236,8 @@ static nserror sslcert_init_entry_fields(struct sslcert_session_data *ssl_d)
label = "TreeviewLabelSerial";
label = messages_get(label);
if (lwc_intern_string(label, strlen(label),
- &ssl_d->fields[SSLCERT_V_SERIAL].field) !=
- lwc_error_ok) {
+ &ssl_d->fields[SSLCERT_V_SERIAL].field) !=
+ lwc_error_ok) {
goto error;
}
@@ -235,8 +245,8 @@ static nserror sslcert_init_entry_fields(struct sslcert_session_data *ssl_d)
label = "TreeviewLabelType";
label = messages_get(label);
if (lwc_intern_string(label, strlen(label),
- &ssl_d->fields[SSLCERT_V_TYPE].field) !=
- lwc_error_ok) {
+ &ssl_d->fields[SSLCERT_V_TYPE].field) !=
+ lwc_error_ok) {
goto error;
}
@@ -244,8 +254,8 @@ static nserror sslcert_init_entry_fields(struct sslcert_session_data *ssl_d)
label = "TreeviewLabelValidUntil";
label = messages_get(label);
if (lwc_intern_string(label, strlen(label),
- &ssl_d->fields[SSLCERT_V_VALID_UNTIL].field) !=
- lwc_error_ok) {
+ &ssl_d->fields[SSLCERT_V_VALID_UNTIL].field) !=
+ lwc_error_ok) {
goto error;
}
@@ -253,8 +263,8 @@ static nserror sslcert_init_entry_fields(struct sslcert_session_data *ssl_d)
label = "TreeviewLabelValidFrom";
label = messages_get(label);
if (lwc_intern_string(label, strlen(label),
- &ssl_d->fields[SSLCERT_V_VALID_FROM].field) !=
- lwc_error_ok) {
+ &ssl_d->fields[SSLCERT_V_VALID_FROM].field) !=
+ lwc_error_ok) {
goto error;
}
@@ -262,8 +272,8 @@ static nserror sslcert_init_entry_fields(struct sslcert_session_data *ssl_d)
label = "TreeviewLabelVersion";
label = messages_get(label);
if (lwc_intern_string(label, strlen(label),
- &ssl_d->fields[SSLCERT_V_VERSION].field) !=
- lwc_error_ok) {
+ &ssl_d->fields[SSLCERT_V_VERSION].field) !=
+ lwc_error_ok) {
goto error;
}
@@ -271,8 +281,8 @@ static nserror sslcert_init_entry_fields(struct sslcert_session_data *ssl_d)
label = "TreeviewLabelIssuer";
label = messages_get(label);
if (lwc_intern_string(label, strlen(label),
- &ssl_d->fields[SSLCERT_V_ISSUER].field) !=
- lwc_error_ok) {
+ &ssl_d->fields[SSLCERT_V_ISSUER].field) !=
+ lwc_error_ok) {
goto error;
}
@@ -280,8 +290,8 @@ static nserror sslcert_init_entry_fields(struct sslcert_session_data *ssl_d)
label = "TreeviewLabelCertificates";
label = messages_get(label);
if (lwc_intern_string(label, strlen(label),
- &ssl_d->fields[SSLCERT_V_CERTIFICATES].field) !=
- lwc_error_ok) {
+ &ssl_d->fields[SSLCERT_V_CERTIFICATES].field) !=
+ lwc_error_ok) {
return false;
}
@@ -299,7 +309,7 @@ error:
/**
* Delete ssl certificate viewer entries
*
- * \param e Entry to delete.
+ * \param e Entry to delete.
*/
static void sslcert_viewer_delete_entry(struct sslcert_entry *e)
{
@@ -308,8 +318,15 @@ static void sslcert_viewer_delete_entry(struct sslcert_entry *e)
}
-static nserror sslcert_viewer_tree_node_folder_cb(
- struct treeview_node_msg msg, void *data)
+/**
+ * folder operation callback
+ *
+ * \param msg treeview message
+ * \param data message context
+ * \return NSERROR_OK on success
+ */
+static nserror
+sslcert_viewer_tree_node_folder_cb(struct treeview_node_msg msg, void *data)
{
switch (msg.msg) {
case TREE_MSG_NODE_DELETE:
@@ -320,8 +337,17 @@ static nserror sslcert_viewer_tree_node_folder_cb(
return NSERROR_OK;
}
-static nserror sslcert_viewer_tree_node_entry_cb(
- struct treeview_node_msg msg, void *data)
+
+
+/**
+ * node entry callback
+ *
+ * \param msg treeview message
+ * \param data message context
+ * \return NSERROR_OK on success
+ */
+static nserror
+sslcert_viewer_tree_node_entry_cb(struct treeview_node_msg msg, void *data)
{
struct sslcert_entry *e = data;
@@ -338,6 +364,11 @@ static nserror sslcert_viewer_tree_node_entry_cb(
return NSERROR_OK;
}
+
+
+/**
+ * ssl certificate treeview callbacks
+ */
struct treeview_callback_table sslv_tree_cb_t = {
.folder = sslcert_viewer_tree_node_folder_cb,
.entry = sslcert_viewer_tree_node_entry_cb
@@ -345,8 +376,10 @@ struct treeview_callback_table sslv_tree_cb_t = {
/* Exported interface, documented in sslcert_viewer.h */
-nserror sslcert_viewer_init(struct core_window_callback_table *cw_t,
- void *core_window_handle, struct sslcert_session_data *ssl_d)
+nserror
+sslcert_viewer_init(struct core_window_callback_table *cw_t,
+ void *core_window_handle,
+ struct sslcert_session_data *ssl_d)
{
nserror err;
int cert_loop;
@@ -358,7 +391,7 @@ nserror sslcert_viewer_init(struct core_window_callback_table *cw_t,
return err;
}
- LOG("Building certificate viewer");
+ NSLOG(netsurf, INFO, "Building certificate viewer");
/* Init. certificate chain treeview entry fields */
err = sslcert_init_entry_fields(ssl_d);
@@ -369,8 +402,8 @@ nserror sslcert_viewer_init(struct core_window_callback_table *cw_t,
/* Create the certificate treeview */
err = treeview_create(&ssl_d->tree, &sslv_tree_cb_t,
- SSLCERT_V_N_FIELDS, ssl_d->fields,
- cw_t, core_window_handle, TREEVIEW_READ_ONLY);
+ SSLCERT_V_N_FIELDS, ssl_d->fields,
+ cw_t, core_window_handle, TREEVIEW_READ_ONLY);
if (err != NSERROR_OK) {
ssl_d->tree = NULL;
return err;
@@ -384,7 +417,7 @@ nserror sslcert_viewer_init(struct core_window_callback_table *cw_t,
}
}
- LOG("Built certificate viewer");
+ NSLOG(netsurf, INFO, "Built certificate viewer");
return NSERROR_OK;
}
@@ -393,7 +426,7 @@ nserror sslcert_viewer_init(struct core_window_callback_table *cw_t,
/**
* Free SSL certificate session data
*
- * \param ssl_d SSL certificate session data
+ * \param ssl_d SSL certificate session data
*/
static void sslcert_cleanup_session(struct sslcert_session_data *ssl_d)
{
@@ -419,7 +452,7 @@ nserror sslcert_viewer_fini(struct sslcert_session_data *ssl_d)
int i;
nserror err;
- LOG("Finalising ssl certificate viewer");
+ NSLOG(netsurf, INFO, "Finalising ssl certificate viewer");
/* Destroy the treeview */
err = treeview_destroy(ssl_d->tree);
@@ -437,17 +470,20 @@ nserror sslcert_viewer_fini(struct sslcert_session_data *ssl_d)
return err;
}
- LOG("Finalised ssl certificate viewer");
+ NSLOG(netsurf, INFO, "Finalised ssl certificate viewer");
return err;
}
/* Exported interface, documented in sslcert_viewer.h */
-nserror sslcert_viewer_create_session_data(unsigned long num, nsurl *url,
- llcache_query_response cb, void *cbpw,
- const struct ssl_cert_info *certs,
- struct sslcert_session_data **ssl_d)
+nserror
+sslcert_viewer_create_session_data(unsigned long num,
+ nsurl *url,
+ llcache_query_response cb,
+ void *cbpw,
+ const struct ssl_cert_info *certs,
+ struct sslcert_session_data **ssl_d)
{
struct sslcert_session_data *data;
@@ -506,9 +542,11 @@ nserror sslcert_viewer_accept(struct sslcert_session_data *ssl_d)
/* Exported interface, documented in sslcert_viewer.h */
-void sslcert_viewer_redraw(struct sslcert_session_data *ssl_d,
- int x, int y, struct rect *clip,
- const struct redraw_context *ctx)
+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");
@@ -518,8 +556,10 @@ void sslcert_viewer_redraw(struct sslcert_session_data *ssl_d,
/* Exported interface, documented in sslcert_viewer.h */
-void sslcert_viewer_mouse_action(struct sslcert_session_data *ssl_d,
- browser_mouse_state mouse, int x, int y)
+void
+sslcert_viewer_mouse_action(struct sslcert_session_data *ssl_d,
+ browser_mouse_state mouse,
+ int x, int y)
{
treeview_mouse_action(ssl_d->tree, mouse, x, y);
}
diff --git a/desktop/sslcert_viewer.h b/desktop/sslcert_viewer.h
index 9b21cd1b6..9a57b965c 100644
--- a/desktop/sslcert_viewer.h
+++ b/desktop/sslcert_viewer.h
@@ -17,9 +17,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+/**
+ * \file
+ * SSL Certificate verification UI interface
+ */
-#ifndef _NETSURF_DESKTOP_SSLCERT_VIEWER_H_
-#define _NETSURF_DESKTOP_SSLCERT_VIEWER_H_
+#ifndef NETSURF_DESKTOP_SSLCERT_VIEWER_H
+#define NETSURF_DESKTOP_SSLCERT_VIEWER_H
#include "content/llcache.h"
#include "netsurf/mouse.h"
@@ -48,6 +52,7 @@ nserror sslcert_viewer_create_session_data(
void *cbpw, const struct ssl_cert_info *certs,
struct sslcert_session_data **ssl_d);
+
/**
* Initialise a ssl certificate viewer from session data.
*
@@ -61,6 +66,7 @@ nserror sslcert_viewer_create_session_data(
nserror sslcert_viewer_init(struct core_window_callback_table *cw_t,
void *core_window_handle, struct sslcert_session_data *ssl_d);
+
/**
* Finalise a ssl certificate viewer.
*
@@ -72,6 +78,7 @@ nserror sslcert_viewer_init(struct core_window_callback_table *cw_t,
*/
nserror sslcert_viewer_fini(struct sslcert_session_data *ssl_d);
+
/**
* Reject a certificate chain.
*
@@ -80,6 +87,7 @@ nserror sslcert_viewer_fini(struct sslcert_session_data *ssl_d);
*/
nserror sslcert_viewer_reject(struct sslcert_session_data *ssl_d);
+
/**
* Accept a certificate chain.
*
@@ -88,6 +96,7 @@ nserror sslcert_viewer_reject(struct sslcert_session_data *ssl_d);
*/
nserror sslcert_viewer_accept(struct sslcert_session_data *ssl_d);
+
/**
* Redraw the ssl certificate viewer.
*
@@ -101,6 +110,7 @@ void sslcert_viewer_redraw(struct sslcert_session_data *ssl_d,
int x, int y, struct rect *clip,
const struct redraw_context *ctx);
+
/**
* Handles all kinds of mouse action
*
@@ -112,6 +122,7 @@ void sslcert_viewer_redraw(struct sslcert_session_data *ssl_d,
void sslcert_viewer_mouse_action(struct sslcert_session_data *ssl_d,
browser_mouse_state mouse, int x, int y);
+
/**
* Key press handling.
*
diff --git a/desktop/system_colour.c b/desktop/system_colour.c
index f33b57a37..42a51eaea 100644
--- a/desktop/system_colour.c
+++ b/desktop/system_colour.c
@@ -16,9 +16,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- * System colour handling
- *
+/**
+ * \file
+ * System colour handling implementation.
*/
#include <string.h>
@@ -38,6 +38,7 @@ static lwc_string *colour_list[colour_list_len];
static lwc_string **ns_system_colour_pw = NULL;
+/* exported interface documented in desktop/system_colour.h */
nserror ns_system_colour_init(void)
{
unsigned int ccount;
@@ -61,6 +62,8 @@ nserror ns_system_colour_init(void)
return NSERROR_OK;
}
+
+/* exported interface documented in desktop/system_colour.h */
void ns_system_colour_finalize(void)
{
unsigned int ccount;
@@ -70,21 +73,25 @@ void ns_system_colour_finalize(void)
}
}
-colour ns_system_colour_char(const char *name)
+
+/* exported interface documented in desktop/system_colour.h */
+nserror ns_system_colour_char(const char *name, colour *colour_out)
{
- colour ret = 0;
unsigned int ccount;
for (ccount = 0; ccount < colour_list_len; ccount++) {
if (strcmp(name,
nsoptions[ccount + NSOPTION_SYS_COLOUR_START].key + SLEN("sys_colour_")) == 0) {
- ret = nsoptions[ccount + NSOPTION_SYS_COLOUR_START].value.c;
- break;
+ *colour_out = nsoptions[ccount + NSOPTION_SYS_COLOUR_START].value.c;
+ return NSERROR_OK;
}
}
- return ret;
+
+ return NSERROR_INVALID;
}
+
+/* exported interface documented in desktop/system_colour.h */
css_error ns_system_colour(void *pw, lwc_string *name, css_color *colour)
{
unsigned int ccount;
diff --git a/desktop/system_colour.h b/desktop/system_colour.h
index 8e82818aa..0b7553003 100644
--- a/desktop/system_colour.h
+++ b/desktop/system_colour.h
@@ -16,25 +16,59 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
+/**
+ * \file
* Interface to system colour values.
+ *
+ * Netsurf has a list of user configurable colours with frontend
+ * specific defaults. These colours are used for the css system
+ * colours and to colour and style internally rendered widgets
+ * (e.g. cookies treeview or local file directory views.
*/
-#ifndef _NETSURF_DESKTOP_SYSTEM_COLOUR_H_
-#define _NETSURF_DESKTOP_SYSTEM_COLOUR_H_
+#ifndef NETSURF_DESKTOP_SYSTEM_COLOUR_H
+#define NETSURF_DESKTOP_SYSTEM_COLOUR_H
#include <libcss/libcss.h>
#include "utils/errors.h"
#include "netsurf/types.h"
-/** css callback to obtain named system colours. */
+/**
+ * css callback to obtain named system colour.
+ *
+ * \param[in] pw context unused in implementation
+ * \param[in] name The name of the colour being looked up
+ * \param[out] color The system colour associated with the name.
+ * \return CSS_OK and \a color updated on success else CSS_INVALID if
+ * the \a name is unrecognised
+ */
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);
+/**
+ * Obtain a system colour from a name.
+ *
+ * \param[in] name The name of the colour being looked up
+ * \param[out] color The system colour associated with the name in the
+ * netsurf colour representation.
+ * \return NSERROR_OK and \a color updated on success else appropriate
+ * error code.
+ */
+nserror ns_system_colour_char(const char *name, colour *color);
+
+
+/**
+ * Initialise the system colours
+ *
+ * \return NSERROR_OK on success else appropriate error code.
+ */
nserror ns_system_colour_init(void);
+
+
+/**
+ * release any resources associated with the system colours.
+ */
void ns_system_colour_finalize(void);
#endif
diff --git a/desktop/textarea.c b/desktop/textarea.c
index 203c28e93..5bae27a5c 100644
--- a/desktop/textarea.c
+++ b/desktop/textarea.c
@@ -45,9 +45,9 @@
#define TA_ALLOC_STEP 512
static plot_style_t pstyle_stroke_caret = {
- .stroke_type = PLOT_OP_TYPE_SOLID,
- .stroke_colour = CARET_COLOR,
- .stroke_width = 1,
+ .stroke_type = PLOT_OP_TYPE_SOLID,
+ .stroke_colour = CARET_COLOR,
+ .stroke_width = plot_style_int_to_fixed(1),
};
struct line_info {
@@ -828,7 +828,7 @@ static bool textarea_reflow_singleline(struct textarea *ta, size_t b_off,
ta->lines =
malloc(LINE_CHUNK_SIZE * sizeof(struct line_info));
if (ta->lines == NULL) {
- LOG("malloc failed");
+ NSLOG(netsurf, INFO, "malloc failed");
return false;
}
ta->lines_alloc_size = LINE_CHUNK_SIZE;
@@ -852,7 +852,7 @@ static bool textarea_reflow_singleline(struct textarea *ta, size_t b_off,
char *temp = realloc(ta->password.data,
b_len + TA_ALLOC_STEP);
if (temp == NULL) {
- LOG("realloc failed");
+ NSLOG(netsurf, INFO, "realloc failed");
return false;
}
@@ -936,7 +936,8 @@ static bool textarea_reflow_multiline(struct textarea *ta,
if (ta->lines == NULL) {
ta->lines = calloc(sizeof(struct line_info), LINE_CHUNK_SIZE);
if (ta->lines == NULL) {
- LOG("Failed to allocate memory for textarea lines");
+ NSLOG(netsurf, INFO,
+ "Failed to allocate memory for textarea lines");
return false;
}
ta->lines_alloc_size = LINE_CHUNK_SIZE;
@@ -1053,7 +1054,7 @@ static bool textarea_reflow_multiline(struct textarea *ta,
(line + 2 + LINE_CHUNK_SIZE) *
sizeof(struct line_info));
if (temp == NULL) {
- LOG("realloc failed");
+ NSLOG(netsurf, INFO, "realloc failed");
return false;
}
@@ -1334,7 +1335,7 @@ static bool textarea_insert_text(struct textarea *ta, const char *text,
char *temp = realloc(ta->text.data, b_len + ta->text.len +
TA_ALLOC_STEP);
if (temp == NULL) {
- LOG("realloc failed");
+ NSLOG(netsurf, INFO, "realloc failed");
return false;
}
@@ -1484,7 +1485,7 @@ static bool textarea_replace_text_internal(struct textarea *ta, size_t b_start,
rep_len + ta->text.len - (b_end - b_start) +
TA_ALLOC_STEP);
if (temp == NULL) {
- LOG("realloc failed");
+ NSLOG(netsurf, INFO, "realloc failed");
return false;
}
@@ -1561,7 +1562,7 @@ static bool textarea_copy_to_undo_buffer(struct textarea *ta,
char *temp = realloc(undo->text.data,
b_offset + len + TA_ALLOC_STEP);
if (temp == NULL) {
- LOG("realloc failed");
+ NSLOG(netsurf, INFO, "realloc failed");
return false;
}
@@ -1575,7 +1576,7 @@ static bool textarea_copy_to_undo_buffer(struct textarea *ta,
(undo->next_detail + 128) *
sizeof(struct textarea_undo_detail));
if (temp == NULL) {
- LOG("realloc failed");
+ NSLOG(netsurf, INFO, "realloc failed");
return false;
}
@@ -1802,6 +1803,10 @@ static void textarea_setup_text_offsets(struct textarea *ta)
{
int text_y_offset, text_y_offset_baseline;
+ ta->line_height = FIXTOINT(FMUL(FLTTOFIX(1.3), FDIV(FMUL(
+ nscss_screen_dpi, FDIV(INTTOFIX(ta->fstyle.size),
+ INTTOFIX(PLOT_STYLE_SCALE))), F_72)));
+
text_y_offset = text_y_offset_baseline = ta->border_width;
if (ta->flags & TEXTAREA_MULTILINE) {
/* Multiline textarea */
@@ -1821,6 +1826,27 @@ static void textarea_setup_text_offsets(struct textarea *ta)
}
+/**
+ * Set font styles up for a textarea.
+ *
+ * \param[in] ta Textarea to update.
+ * \param[in] fstyle Font style to set in textarea.
+ * \param[in] selected_text Textarea selected text colour.
+ * \param[in] selected_bg Textarea selection background colour.
+ */
+static void textarea_set_text_style(
+ struct textarea *ta,
+ const plot_font_style_t *fstyle,
+ colour selected_text,
+ colour selected_bg)
+{
+ ta->fstyle = *fstyle;
+
+ ta->sel_fstyle = *fstyle;
+ ta->sel_fstyle.foreground = selected_text;
+ ta->sel_fstyle.background = selected_bg;
+}
+
/* exported interface, documented in textarea.h */
struct textarea *textarea_create(const textarea_flags flags,
@@ -1835,13 +1861,13 @@ struct textarea *textarea_create(const textarea_flags flags,
flags & TEXTAREA_PASSWORD));
if (callback == NULL) {
- LOG("no callback provided");
+ NSLOG(netsurf, INFO, "no callback provided");
return NULL;
}
ret = malloc(sizeof(struct textarea));
if (ret == NULL) {
- LOG("malloc failed");
+ NSLOG(netsurf, INFO, "malloc failed");
return NULL;
}
@@ -1860,11 +1886,10 @@ struct textarea *textarea_create(const textarea_flags flags,
ret->border_width = setup->border_width;
ret->border_col = setup->border_col;
- ret->fstyle = setup->text;
-
- ret->sel_fstyle = setup->text;
- ret->sel_fstyle.foreground = setup->selected_text;
- ret->sel_fstyle.background = setup->selected_bg;
+ textarea_set_text_style(ret,
+ &setup->text,
+ setup->selected_text,
+ setup->selected_bg);
ret->scroll_x = 0;
ret->scroll_y = 0;
@@ -1888,7 +1913,7 @@ struct textarea *textarea_create(const textarea_flags flags,
ret->text.data = malloc(TA_ALLOC_STEP);
if (ret->text.data == NULL) {
- LOG("malloc failed");
+ NSLOG(netsurf, INFO, "malloc failed");
free(ret);
return NULL;
}
@@ -1900,7 +1925,7 @@ struct textarea *textarea_create(const textarea_flags flags,
if (flags & TEXTAREA_PASSWORD) {
ret->password.data = malloc(TA_ALLOC_STEP);
if (ret->password.data == NULL) {
- LOG("malloc failed");
+ NSLOG(netsurf, INFO, "malloc failed");
free(ret->text.data);
free(ret);
return NULL;
@@ -1923,7 +1948,7 @@ struct textarea *textarea_create(const textarea_flags flags,
ret->line_height = FIXTOINT(FMUL(FLTTOFIX(1.3), FDIV(FMUL(
nscss_screen_dpi, FDIV(INTTOFIX(setup->text.size),
- INTTOFIX(FONT_SIZE_SCALE))), F_72)));
+ INTTOFIX(PLOT_STYLE_SCALE))), F_72)));
ret->caret_pos.line = ret->caret_pos.byte_off = -1;
ret->caret_x = 0;
@@ -1975,7 +2000,7 @@ bool textarea_set_text(struct textarea *ta, const char *text)
if (len >= ta->text.alloc) {
char *temp = realloc(ta->text.data, len + TA_ALLOC_STEP);
if (temp == NULL) {
- LOG("realloc failed");
+ NSLOG(netsurf, INFO, "realloc failed");
return false;
}
ta->text.data = temp;
@@ -2062,7 +2087,7 @@ int textarea_get_text(struct textarea *ta, char *buf, unsigned int len)
}
if (len < ta->text.len) {
- LOG("buffer too small");
+ NSLOG(netsurf, INFO, "buffer too small");
return -1;
}
@@ -2073,6 +2098,17 @@ int textarea_get_text(struct textarea *ta, char *buf, unsigned int len)
/* exported interface, documented in textarea.h */
+const char * textarea_data(struct textarea *ta, unsigned int *len)
+{
+ if (len != NULL) {
+ *len = ta->text.len;
+ }
+
+ return ta->text.data;
+}
+
+
+/* exported interface, documented in textarea.h */
bool textarea_set_caret(struct textarea *ta, int caret)
{
int b_off;
@@ -2095,13 +2131,13 @@ bool textarea_set_caret(struct textarea *ta, int caret)
void textarea_redraw(struct textarea *ta, int x, int y, colour bg, float scale,
const struct rect *clip, const struct redraw_context *ctx)
{
- const struct plotter_table *plot = ctx->plot;
int line0, line1, line, left, right, line_y;
int text_y_offset, text_y_offset_baseline;
unsigned int b_pos, b_len, b_len_part, b_end;
unsigned int sel_start, sel_end;
char *line_text;
struct rect r, s;
+ struct rect rect;
bool selected = false;
plot_font_style_t fstyle;
int fsize = ta->fstyle.size;
@@ -2162,20 +2198,24 @@ void textarea_redraw(struct textarea *ta, int x, int y, colour bg, float scale,
r.y1 = y + ta->vis_height * scale;
}
- plot->clip(&r);
+ ctx->plot->clip(ctx, &r);
if (ta->border_col != NS_TRANSPARENT &&
ta->border_width > 0) {
/* Plot border */
- plot->rectangle(x, y, x + ta->vis_width, y + ta->vis_height,
- &plot_style_fill_bg);
+ rect.x0 = x;
+ rect.y0 = y;
+ rect.x1 = x + ta->vis_width;
+ rect.y1 = y + ta->vis_height;
+ ctx->plot->rectangle(ctx, &plot_style_fill_bg, &rect);
}
if (ta->fstyle.background != NS_TRANSPARENT) {
/* Plot background */
plot_style_fill_bg.fill_colour = ta->fstyle.background;
- plot->rectangle(x + ta->border_width, y + ta->border_width,
- x + ta->vis_width - ta->border_width,
- y + ta->vis_height - ta->border_width,
- &plot_style_fill_bg);
+ rect.x0 = x + ta->border_width;
+ rect.y0 = y + ta->border_width;
+ rect.x1 = x + ta->vis_width - ta->border_width;
+ rect.y1 = y + ta->vis_height - ta->border_width;
+ ctx->plot->rectangle(ctx, &plot_style_fill_bg, &rect);
}
if (scale == 1.0) {
@@ -2223,16 +2263,16 @@ void textarea_redraw(struct textarea *ta, int x, int y, colour bg, float scale,
plot_style_fill_bg.fill_colour = ta->sel_fstyle.background;
- for (line = line0; (line <= line1) &&
- (y + line * ta->line_height <= r.y1 + ta->scroll_y);
- line++) {
+ for (line = line0;
+ (line <= line1) && (y + line * ta->line_height <= r.y1 + ta->scroll_y);
+ line++) {
if (ta->lines[line].b_length == 0) {
b_pos++;
continue;
}
/* reset clip rectangle */
- plot->clip(&r);
+ ctx->plot->clip(ctx, &r);
b_len = ta->lines[line].b_length;
@@ -2256,12 +2296,12 @@ void textarea_redraw(struct textarea *ta, int x, int y, colour bg, float scale,
fstyle = ta->fstyle;
fstyle.size = fsize;
- plot->text(x + ta->border_width + ta->pad_left -
- ta->scroll_x,
+ ctx->plot->text(ctx,
+ &fstyle,
+ x + ta->border_width + ta->pad_left - ta->scroll_x,
y + line_y + text_y_offset_baseline,
- ta->show->data +
- ta->lines[line].b_start,
- ta->lines[line].b_length, &fstyle);
+ ta->show->data + ta->lines[line].b_start,
+ ta->lines[line].b_length);
b_pos += b_len;
@@ -2338,24 +2378,24 @@ void textarea_redraw(struct textarea *ta, int x, int y, colour bg, float scale,
continue;
}
- plot->clip(&s);
+ ctx->plot->clip(ctx, &s);
if (selected) {
/* draw selection fill */
- plot->rectangle(s.x0, y + line_y +
- text_y_offset,
- s.x1, y + line_y + line_height +
- text_y_offset,
- &plot_style_fill_bg);
+ rect.x0 = s.x0;
+ rect.y0 = y + line_y + text_y_offset;
+ rect.x1 = s.x1;
+ rect.y1 = y + line_y + line_height + text_y_offset;
+ ctx->plot->rectangle(ctx, &plot_style_fill_bg, &rect);
}
/* draw text */
- plot->text(x + ta->border_width + ta->pad_left -
- ta->scroll_x,
+ ctx->plot->text(ctx,
+ &fstyle,
+ x + ta->border_width + ta->pad_left - ta->scroll_x,
y + line_y + text_y_offset_baseline,
- ta->show->data +
- ta->lines[line].b_start,
- ta->lines[line].b_length, &fstyle);
+ ta->show->data + ta->lines[line].b_start,
+ ta->lines[line].b_length);
b_pos += b_len_part;
b_len -= b_len_part;
@@ -2376,30 +2416,33 @@ void textarea_redraw(struct textarea *ta, int x, int y, colour bg, float scale,
/* No native caret, there is no selection, and caret visible */
int caret_y = y - ta->scroll_y + ta->caret_y;
- plot->clip(&r);
+ ctx->plot->clip(ctx, &r);
/* Render our own caret */
- plot->line(x - ta->scroll_x + ta->caret_x, caret_y,
- x - ta->scroll_x + ta->caret_x,
- caret_y + ta->line_height,
- &pstyle_stroke_caret);
+ rect.x0 = x - ta->scroll_x + ta->caret_x;
+ rect.y0 = caret_y;
+ rect.x1 = x - ta->scroll_x + ta->caret_x;
+ rect.y1 = caret_y + ta->line_height;
+ ctx->plot->line(ctx, &pstyle_stroke_caret, &rect);
}
- plot->clip(clip);
+ ctx->plot->clip(ctx, clip);
- if (ta->bar_x != NULL)
+ if (ta->bar_x != NULL) {
scrollbar_redraw(ta->bar_x,
x / scale + ta->border_width,
y / scale + ta->vis_height - ta->border_width -
SCROLLBAR_WIDTH,
clip, scale, ctx);
+ }
- if (ta->bar_y != NULL)
+ if (ta->bar_y != NULL) {
scrollbar_redraw(ta->bar_y,
x / scale + ta->vis_width - ta->border_width -
SCROLLBAR_WIDTH,
y / scale + ta->border_width,
clip, scale, ctx);
+ }
}
@@ -2842,7 +2885,7 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
return false;
}
- redraw &= ~textarea_set_caret_internal(ta, caret);
+ redraw &= !textarea_set_caret_internal(ta, caret);
/* TODO: redraw only the bit that changed */
msg.ta = ta;
@@ -3201,8 +3244,12 @@ void textarea_set_dimensions(struct textarea *ta, int width, int height)
/* exported interface, documented in textarea.h */
-void textarea_set_layout(struct textarea *ta, int width, int height,
- int top, int right, int bottom, int left)
+void textarea_set_layout(
+ struct textarea *ta,
+ const plot_font_style_t *fstyle,
+ int width, int height,
+ int top, int right,
+ int bottom, int left)
{
struct rect r = {0, 0, 0, 0};
@@ -3213,6 +3260,10 @@ void textarea_set_layout(struct textarea *ta, int width, int height,
ta->pad_bottom = bottom + ((ta->bar_x == NULL) ? 0 : SCROLLBAR_WIDTH);
ta->pad_left = left;
+ textarea_set_text_style(ta, fstyle,
+ ta->sel_fstyle.foreground,
+ ta->sel_fstyle.background);
+
textarea_setup_text_offsets(ta);
if (ta->flags & TEXTAREA_MULTILINE) {
diff --git a/desktop/textarea.h b/desktop/textarea.h
index 65e2594c7..82e0de95b 100644
--- a/desktop/textarea.h
+++ b/desktop/textarea.h
@@ -1,6 +1,6 @@
/*
* Copyright 2006 John-Mark Bell <jmb@netsurf-browser.org>
- * Copyright 2009 Paul Blokus <paul_pl@users.sourceforge.net>
+ * Copyright 2009 Paul Blokus <paul_pl@users.sourceforge.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -17,12 +17,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- * Single/Multi-line UTF-8 text area (interface)
+/**
+ * \file
+ * Single/Multi-line UTF-8 text area interface
*/
-#ifndef _NETSURF_DESKTOP_TEXTAREA_H_
-#define _NETSURF_DESKTOP_TEXTAREA_H_
+#ifndef NETSURF_DESKTOP_TEXTAREA_H
+#define NETSURF_DESKTOP_TEXTAREA_H
#include <stdint.h>
#include <stdbool.h>
@@ -33,21 +34,31 @@
struct textarea;
struct redraw_context;
-/* Text area flags */
+/**
+ * Text area flags
+ */
typedef enum {
- TEXTAREA_DEFAULT = (1 << 0), /**< Standard input */
- TEXTAREA_MULTILINE = (1 << 1), /**< Multiline area */
- TEXTAREA_READONLY = (1 << 2), /**< Non-editable */
- TEXTAREA_INTERNAL_CARET = (1 << 3), /**< Render own caret */
- TEXTAREA_PASSWORD = (1 << 4) /**< Obscured display */
+ TEXTAREA_DEFAULT = (1 << 0), /**< Standard input */
+ TEXTAREA_MULTILINE = (1 << 1), /**< Multiline area */
+ TEXTAREA_READONLY = (1 << 2), /**< Non-editable */
+ TEXTAREA_INTERNAL_CARET = (1 << 3), /**< Render own caret */
+ TEXTAREA_PASSWORD = (1 << 4) /**< Obscured display */
} textarea_flags;
+
+/**
+ * Textarea drag status
+ */
typedef enum {
TEXTAREA_DRAG_NONE,
TEXTAREA_DRAG_SCROLLBAR,
TEXTAREA_DRAG_SELECTION
-} textarea_drag_type; /**< Textarea drag status */
+} textarea_drag_type;
+
+/**
+ * textarea message types
+ */
typedef enum {
TEXTAREA_MSG_DRAG_REPORT, /**< Textarea drag start/end report */
TEXTAREA_MSG_SELECTION_REPORT, /**< Textarea text selection presence */
@@ -56,6 +67,10 @@ typedef enum {
TEXTAREA_MSG_TEXT_MODIFIED /**< Textarea text modified */
} textarea_msg_type;
+
+/**
+ * textarea message
+ */
struct textarea_msg {
struct textarea *ta; /**< The textarea widget */
@@ -73,10 +88,10 @@ struct textarea_msg {
TEXTAREA_CARET_HIDE /**< Hide */
} type;
struct {
- int x; /**< Carret x-coord */
- int y; /**< Carret y-coord */
- int height; /**< Carret height */
- struct rect *clip; /**< Carret clip rect */
+ int x; /**< Caret x-coord */
+ int y; /**< Caret y-coord */
+ int height; /**< Caret height */
+ struct rect *clip; /**< Caret clip rect */
} pos; /**< With _CARET_SET_POS */
} caret; /**< With _CARET_UPDATE */
struct {
@@ -86,6 +101,10 @@ struct textarea_msg {
} data; /**< Depends on msg type */
};
+
+/**
+ * textarea setup parameters
+ */
typedef struct textarea_setup {
int width; /**< Textarea width */
int height; /**< Textarea height */
@@ -104,14 +123,39 @@ typedef struct textarea_setup {
} textarea_setup;
+
+/**
+ * Text area mouse input status flags
+ */
+typedef enum {
+ TEXTAREA_MOUSE_NONE = 0, /**< Not relevant */
+ TEXTAREA_MOUSE_USED = (1 << 0), /**< Took action with input */
+ TEXTAREA_MOUSE_EDITOR = (1 << 1), /**< Hover: caret pointer */
+ TEXTAREA_MOUSE_SELECTION= (1 << 2), /**< Hover: selection */
+ TEXTAREA_MOUSE_SCR_USED = (1 << 3), /**< Scrollbar action */
+ TEXTAREA_MOUSE_SCR_BOTH = (1 << 4), /**< Scrolling both bars */
+ TEXTAREA_MOUSE_SCR_UP = (1 << 5), /**< Hover: scroll up */
+ TEXTAREA_MOUSE_SCR_PUP = (1 << 6), /**< Hover: scroll page up */
+ TEXTAREA_MOUSE_SCR_VRT = (1 << 7), /**< Hover: vert. drag bar */
+ TEXTAREA_MOUSE_SCR_PDWN = (1 << 8), /**< Hover: scroll page down */
+ TEXTAREA_MOUSE_SCR_DWN = (1 << 9), /**< Hover: scroll down */
+ TEXTAREA_MOUSE_SCR_LFT = (1 << 10), /**< Hover: scroll left */
+ TEXTAREA_MOUSE_SCR_PLFT = (1 << 11), /**< Hover: scroll page left */
+ TEXTAREA_MOUSE_SCR_HRZ = (1 << 12), /**< Hover: horiz. drag bar */
+ TEXTAREA_MOUSE_SCR_PRGT = (1 << 13), /**< Hover: scroll page right */
+ TEXTAREA_MOUSE_SCR_RGT = (1 << 14) /**< Hover: scroll right */
+} textarea_mouse_status;
+
+
/**
* Client callback for the textarea
*
- * \param data user data passed at textarea creation
- * \param textarea_msg textarea message data
+ * \param data user data passed at textarea creation
+ * \param msg textarea message data
*/
typedef void(*textarea_client_callback)(void *data, struct textarea_msg *msg);
+
/**
* Create a text area.
*
@@ -125,6 +169,7 @@ struct textarea *textarea_create(const textarea_flags flags,
const textarea_setup *setup,
textarea_client_callback callback, void *data);
+
/**
* Destroy a text area
*
@@ -132,6 +177,7 @@ struct textarea *textarea_create(const textarea_flags flags,
*/
void textarea_destroy(struct textarea *ta);
+
/**
* Set the text in a text area, discarding any current text
*
@@ -141,6 +187,7 @@ void textarea_destroy(struct textarea *ta);
*/
bool textarea_set_text(struct textarea *ta, const char *text);
+
/**
* Insert the text in a text area at the caret, replacing any selection.
*
@@ -152,6 +199,7 @@ bool textarea_set_text(struct textarea *ta, const char *text);
bool textarea_drop_text(struct textarea *ta, const char *text,
size_t text_length);
+
/**
* Extract the text from a text area
*
@@ -163,16 +211,28 @@ bool textarea_drop_text(struct textarea *ta, const char *text,
*/
int textarea_get_text(struct textarea *ta, char *buf, unsigned int len);
+
+/**
+ * Access text data in a text area
+ *
+ * \param[in] ta Text area
+ * \param[out] len Returns byte length of returned text, if passed non-NULL.
+ * \return textarea string data.
+ */
+const char * textarea_data(struct textarea *ta, unsigned int *len);
+
+
/**
* Set the caret's position
*
- * \param ta Text area
- * \param caret 0-based character index to place caret at, -1 removes
- * the caret
+ * \param ta Text area
+ * \param caret 0-based character index to place caret at, -1 removes
+ * the caret
* \return true on success false otherwise
*/
bool textarea_set_caret(struct textarea *ta, int caret);
+
/**
* Handle redraw requests for text areas
*
@@ -187,34 +247,16 @@ bool textarea_set_caret(struct textarea *ta, int caret);
void textarea_redraw(struct textarea *ta, int x, int y, colour bg, float scale,
const struct rect *clip, const struct redraw_context *ctx);
+
/**
* Key press handling for text areas.
*
* \param ta The text area which got the keypress
* \param key The ucs4 character codepoint
- * \return true if the keypress is dealt with, false otherwise.
+ * \return true if the keypress is dealt with, false otherwise.
*/
bool textarea_keypress(struct textarea *ta, uint32_t key);
-/* Text area mouse input status flags */
-typedef enum {
- TEXTAREA_MOUSE_NONE = 0, /**< Not relevant */
- TEXTAREA_MOUSE_USED = (1 << 0), /**< Took action with input */
- TEXTAREA_MOUSE_EDITOR = (1 << 1), /**< Hover: caret pointer */
- TEXTAREA_MOUSE_SELECTION= (1 << 2), /**< Hover: selection */
- TEXTAREA_MOUSE_SCR_USED = (1 << 3), /**< Scrollbar action */
- TEXTAREA_MOUSE_SCR_BOTH = (1 << 4), /**< Scrolling both bars */
- TEXTAREA_MOUSE_SCR_UP = (1 << 5), /**< Hover: scroll up */
- TEXTAREA_MOUSE_SCR_PUP = (1 << 6), /**< Hover: scroll page up */
- TEXTAREA_MOUSE_SCR_VRT = (1 << 7), /**< Hover: vert. drag bar */
- TEXTAREA_MOUSE_SCR_PDWN = (1 << 8), /**< Hover: scroll page down */
- TEXTAREA_MOUSE_SCR_DWN = (1 << 9), /**< Hover: scroll down */
- TEXTAREA_MOUSE_SCR_LFT = (1 << 10), /**< Hover: scroll left */
- TEXTAREA_MOUSE_SCR_PLFT = (1 << 11), /**< Hover: scroll page left */
- TEXTAREA_MOUSE_SCR_HRZ = (1 << 12), /**< Hover: horiz. drag bar */
- TEXTAREA_MOUSE_SCR_PRGT = (1 << 13), /**< Hover: scroll page right */
- TEXTAREA_MOUSE_SCR_RGT = (1 << 14) /**< Hover: scroll right */
-} textarea_mouse_status;
/**
* Handles all kinds of mouse action
@@ -228,22 +270,28 @@ typedef enum {
textarea_mouse_status textarea_mouse_action(struct textarea *ta,
browser_mouse_state mouse, int x, int y);
+
/**
* Clear any selection in the textarea.
*
- * \param ta textarea widget
+ * \param ta textarea widget
* \return true if there was a selection to clear, false otherwise
*/
bool textarea_clear_selection(struct textarea *ta);
+
/**
- * Get selected text, ownership passed to caller, which needs to free() it.
+ * Get selected text.
*
- * \param ta Textarea widget
+ * ownership of the returned string is passed to caller which needs to
+ * free it.
+ *
+ * \param ta Textarea widget
* \return Selected text, or NULL if none.
*/
char *textarea_get_selection(struct textarea *ta);
+
/**
* Gets the dimensions of a textarea
*
@@ -253,34 +301,47 @@ char *textarea_get_selection(struct textarea *ta);
*/
void textarea_get_dimensions(struct textarea *ta, int *width, int *height);
+
/**
- * Set the dimensions of a textarea, causing a reflow and
- * Does not emit a redraw request. Up to client to call textarea_redraw.
+ * Set the dimensions of a textarea.
+ *
+ * This causes a reflow of the text and does not emit a redraw
+ * request. Up to client to call textarea_redraw.
*
* \param ta textarea widget
- * \param width the new width of the textarea
+ * \param width the new width of the textarea
* \param height the new height of the textarea
*/
void textarea_set_dimensions(struct textarea *ta, int width, int height);
+
/**
- * Set the dimensions and padding of a textarea, causing a reflow.
- * Does not emit a redraw request. Up to client to call textarea_redraw.
+ * Set the dimensions and padding of a textarea.
+ *
+ * This causes a reflow of the text. Does not emit a redraw request.
+ * Up to client to call textarea_redraw.
*
* \param ta textarea widget
- * \param width the new width of the textarea
+ * \param width the new width of the textarea
* \param height the new height of the textarea
* \param top the new top padding of the textarea
* \param right the new right padding of the textarea
* \param bottom the new bottom padding of the textarea
* \param left the new left padding of the textarea
*/
-void textarea_set_layout(struct textarea *ta, int width, int height,
- int top, int right, int bottom, int left);
+void textarea_set_layout(
+ struct textarea *ta,
+ const plot_font_style_t *fstyle,
+ int width, int height,
+ int top, int right,
+ int bottom, int left);
+
/**
- * Scroll a textarea by an amount. Only does anything if multi-line textarea
- * has scrollbars. If it scrolls, it will emit a redraw request.
+ * Scroll a textarea by an amount.
+ *
+ * Only does anything if multi-line textarea has scrollbars. If it
+ * scrolls, it will emit a redraw request.
*
* \param ta textarea widget
* \param scrx number of px try to scroll in x direction
@@ -288,5 +349,5 @@ void textarea_set_layout(struct textarea *ta, int width, int height,
* \return true iff the textarea was scrolled
*/
bool textarea_scroll(struct textarea *ta, int scrx, int scry);
-#endif
+#endif
diff --git a/desktop/textinput.c b/desktop/textinput.c
index c0e0ba8f7..7fc95f792 100644
--- a/desktop/textinput.c
+++ b/desktop/textinput.c
@@ -37,9 +37,9 @@
#include "netsurf/form.h"
#include "netsurf/window.h"
#include "netsurf/keypress.h"
-#include "render/box.h"
-#include "render/html_internal.h"
-#include "render/layout.h"
+#include "html/box.h"
+#include "html/html_internal.h"
+#include "html/layout.h"
#include "desktop/browser_private.h"
#include "desktop/textinput.h"
diff --git a/desktop/textinput.h b/desktop/textinput.h
index 5859ea8d6..7c6be9547 100644
--- a/desktop/textinput.h
+++ b/desktop/textinput.h
@@ -24,19 +24,19 @@
* Textual input handling interface
*/
-#ifndef _NETSURF_DESKTOP_TEXTINPUT_H_
-#define _NETSURF_DESKTOP_TEXTINPUT_H_
+#ifndef NETSURF_DESKTOP_TEXTINPUT_H
+#define NETSURF_DESKTOP_TEXTINPUT_H
struct browser_window;
/**
* Position the caret and assign a callback for key presses.
*
- * \param bw The browser window in which to place the caret
- * \param x X coordinate of the caret
- * \param y Y coordinate
- * \param height Height of caret
- * \param clip Clip rectangle for caret, or NULL if none
+ * \param bw The browser window in which to place the caret
+ * \param x X coordinate of the caret
+ * \param y Y coordinate
+ * \param height Height of caret
+ * \param clip Clip rectangle for caret, or NULL if none
*/
void browser_window_place_caret(struct browser_window *bw, int x, int y,
int height, const struct rect *clip);
diff --git a/desktop/treeview.c b/desktop/treeview.c
index 4d8fbaaeb..48422e8e3 100644
--- a/desktop/treeview.c
+++ b/desktop/treeview.c
@@ -22,10 +22,13 @@
* Treeview handling implementation.
*/
+#include <string.h>
+
#include "utils/utils.h"
#include "utils/log.h"
#include "utils/nsurl.h"
#include "utils/nsoption.h"
+#include "utils/config.h"
#include "netsurf/bitmap.h"
#include "netsurf/content.h"
#include "netsurf/plotters.h"
@@ -42,9 +45,17 @@
#include "desktop/treeview.h"
#include "desktop/gui_internal.h"
-/** @todo get rid of REDRAW_MAX -- need to be able to know window size */
+/**
+ * The maximum horizontal size a treeview can possibly be.
+ *
+ * \todo get rid of REDRAW_MAX -- need to be able to know window size
+ */
#define REDRAW_MAX 8000
+
+/**
+ * Treeview handling global context
+ */
struct treeview_globals {
unsigned initialised;
int line_height;
@@ -56,32 +67,54 @@ struct treeview_globals {
int move_offset;
} tree_g;
+
+/**
+ * Section type of a treeview at a point
+ */
enum treeview_node_part {
- TV_NODE_PART_TOGGLE, /**< Expansion toggle */
- TV_NODE_PART_ON_NODE, /**< Node content (text, icon) */
- TV_NODE_PART_NONE /**< Empty area */
-}; /**< Section type of a treeview at a point */
+ TV_NODE_PART_TOGGLE, /**< Expansion toggle */
+ TV_NODE_PART_ON_NODE, /**< Node content (text, icon) */
+ TV_NODE_PART_NONE /**< Empty area */
+};
+
+/**
+ * Text within a treeview field or node
+ */
struct treeview_text {
const char *data; /**< Text string */
uint32_t len; /**< Length of string in bytes */
int width; /**< Width of text in px */
};
+
+/**
+ * a treeview field
+ */
struct treeview_field {
+ /** flags controlling how field is interpreted */
enum treeview_field_flags flags;
- lwc_string *field;
- struct treeview_text value;
+ lwc_string *field; /**< field contents */
+ struct treeview_text value; /**< field text */
};
+
+/**
+ * flags indicating render state of node.
+ */
enum treeview_node_flags {
- 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 */
+ 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 */
+ TV_NFLAGS_MATCHED = (1 << 3), /**< Whether node matches search */
};
+
+/**
+ * Treeview target position
+ */
enum treeview_target_pos {
TV_TARGET_ABOVE,
TV_TARGET_INSIDE,
@@ -89,6 +122,10 @@ enum treeview_target_pos {
TV_TARGET_NONE
};
+
+/**
+ * Treeview node
+ */
struct treeview_node {
enum treeview_node_flags flags; /**< Node flags */
enum treeview_node_type type; /**< Node type */
@@ -96,49 +133,73 @@ struct treeview_node {
int height; /**< Includes height of any descendants (pixels) */
int inset; /**< Node's inset depending on tree depth (pixels) */
- treeview_node *parent;
- treeview_node *prev_sib;
- treeview_node *next_sib;
- treeview_node *children;
+ treeview_node *parent; /**< parent node */
+ treeview_node *prev_sib; /**< previous sibling node */
+ treeview_node *next_sib; /**< next sibling node */
+ treeview_node *children; /**< first child node */
void *client_data; /**< Passed to client on node event msg callback */
struct treeview_text text; /** Text to show for node (default field) */
-}; /**< Treeview node */
+};
+
+/**
+ * Node entry
+ *
+ * node entry contains a base node at the beginning allowing for
+ * trivial containerof by cast and some number of fields.
+ */
struct treeview_node_entry {
- treeview_node base;
+ treeview_node base; /**< Entry class inherits node base class */
struct treeview_field fields[FLEX_ARRAY_LEN_DECL];
-}; /**< Entry class inherits node base class */
+};
+
+/**
+ * A mouse position wrt treeview
+ */
struct treeview_pos {
int x; /**< Mouse X coordinate */
int y; /**< Mouse Y coordinate */
int node_y; /**< Top of node at y */
int node_h; /**< Height of node at y */
-}; /**< A mouse position wrt treeview */
+};
+
+/**
+ * Treeview drag state
+ */
struct treeview_drag {
enum {
TV_DRAG_NONE,
TV_DRAG_SELECTION,
TV_DRAG_MOVE,
- TV_DRAG_TEXTAREA
+ TV_DRAG_TEXTAREA,
+ TV_DRAG_SEARCH,
} type; /**< Drag type */
treeview_node *start_node; /**< Start node */
bool selected; /**< Start node is selected */
enum treeview_node_part part; /**< Node part at start */
struct treeview_pos start; /**< Start pos */
struct treeview_pos prev; /**< Previous pos */
-}; /**< Drag state */
+};
+
+/**
+ * Treeview node move details
+ */
struct treeview_move {
treeview_node *root; /**< Head of yanked node list */
treeview_node *target; /**< Move target */
struct rect target_area; /**< Pos/size of target indicator */
enum treeview_target_pos target_pos; /**< Pos wrt render node */
-}; /**< Move details */
+};
+
+/**
+ * Treeview node edit details
+ */
struct treeview_edit {
treeview_node *node; /**< Node being edited, or NULL */
struct textarea *textarea; /**< Textarea for edit, or NULL */
@@ -147,22 +208,39 @@ struct treeview_edit {
int y; /**< Textarea y position */
int w; /**< Textarea width */
int h; /**< Textarea height */
-}; /**< Edit details */
+};
+
+/**
+ * Treeview search box details
+ */
+struct treeview_search {
+ struct textarea *textarea; /**< Search box. */
+ bool active; /**< Whether the search box has focus. */
+ bool search; /**< Whether we have a search term. */
+ int height; /**< Current search display height. */
+};
+
+
+/**
+ * The treeview context
+ */
struct treeview {
- uint32_t view_width; /**< Viewport size */
+ uint32_t view_width; /**< Viewport horizontal size */
- treeview_flags flags; /**< Treeview behaviour settings */
+ treeview_flags flags; /**< Treeview behaviour settings */
- treeview_node *root; /**< Root node */
+ treeview_node *root; /**< Root node */
struct treeview_field *fields; /**< Array of fields */
int n_fields; /**< fields[n_fields] is folder, lower are entry fields */
int field_width; /**< Max width of shown field names */
- struct treeview_drag drag; /**< Drag state */
- struct treeview_move move; /**< Move drag details */
- struct treeview_edit edit; /**< Edit details */
+ struct treeview_drag drag; /**< Drag state */
+ struct treeview_move move; /**< Move drag details */
+ struct treeview_edit edit; /**< Edit details */
+
+ struct treeview_search search; /**< Treeview search box */
const struct treeview_callback_table *callbacks; /**< For node events */
@@ -171,38 +249,62 @@ struct treeview {
};
+/**
+ * Treeview furniture states.
+ */
enum treeview_furniture_id {
TREE_FURN_EXPAND = 0,
TREE_FURN_CONTRACT,
TREE_FURN_LAST
};
-struct treeview_furniture {
- int size;
- struct bitmap *bmp;
- struct bitmap *sel;
-};
+
+/**
+ * style for a node
+ */
struct treeview_node_style {
- plot_style_t bg; /**< Background */
- plot_font_style_t text; /**< Text */
- plot_font_style_t itext; /**< Entry field text */
+ plot_style_t bg; /**< Background */
+ plot_font_style_t text; /**< Text */
+ plot_font_style_t itext; /**< Entry field text */
+
+ plot_style_t sbg; /**< Selected background */
+ plot_font_style_t stext; /**< Selected text */
+ plot_font_style_t sitext; /**< Selected entry field text */
+
+ struct {
+ int size;
+ struct bitmap *bmp;
+ struct bitmap *sel;
+ } furn[TREE_FURN_LAST];
+};
- plot_style_t sbg; /**< Selected background */
- plot_font_style_t stext; /**< Selected text */
- plot_font_style_t sitext; /**< Selected entry field text */
- struct treeview_furniture furn[TREE_FURN_LAST];
-};
+/**
+ * Plot style for odd rows
+ */
+struct treeview_node_style plot_style_odd;
+
+
+/**
+ * Plot style for even rows
+ */
+struct treeview_node_style plot_style_even;
-struct treeview_node_style plot_style_odd; /**< Plot style for odd rows */
-struct treeview_node_style plot_style_even; /**< Plot style for even rows */
+/**
+ * Treeview content resource data
+ */
struct treeview_resource {
const char *url;
struct hlcache_handle *c;
int height;
bool ready;
-}; /**< Treeview content resource data */
+};
+
+
+/**
+ * treeview resource indexes
+ */
enum treeview_resource_id {
TREE_RES_ARROW = 0,
TREE_RES_CONTENT,
@@ -211,27 +313,46 @@ enum treeview_resource_id {
TREE_RES_SEARCH,
TREE_RES_LAST
};
+
+
+/**
+ * Treeview content resources
+ */
static struct treeview_resource treeview_res[TREE_RES_LAST] = {
{ "resource:icons/arrow-l.png", NULL, 0, false },
{ "resource:icons/content.png", NULL, 0, false },
{ "resource:icons/directory.png", NULL, 0, false },
{ "resource:icons/directory2.png", NULL, 0, false },
{ "resource:icons/search.png", NULL, 0, false }
-}; /**< Treeview content resources */
+};
+
+
+/**
+ * Get the display height of the treeview data component of the display.
+ *
+ * \param[in] tree Treeview to get the height of.
+ * \return the display height in pixels.
+ */
+static inline int treeview__get_display_height(const treeview *tree)
+{
+ return (tree->search.search == false) ?
+ tree->root->height :
+ tree->search.height;
+}
/**
* Corewindow callback wrapper: Request a redraw of the window
*
- * \param[in] cw the core window object
+ * \param[in] tree The treeview to request redraw on.
* \param[in] r rectangle to redraw
*/
-static inline void treeview__cw_redraw_request(
+static inline void treeview__cw_invalidate_area(
const struct treeview *tree,
const struct rect *r)
{
if (tree->cw_t != NULL) {
- tree->cw_t->redraw_request(tree->cw_h, r);
+ tree->cw_t->invalidate(tree->cw_h, r);
}
}
@@ -239,16 +360,41 @@ static inline void treeview__cw_redraw_request(
/**
* Corewindow callback wrapper: Update the limits of the window
*
- * \param[in] cw the core window object
+ * \param[in] tree The treeview to update size for.
* \param[in] width the width in px, or negative if don't care
* \param[in] height the height in px, or negative if don't care
*/
static inline void treeview__cw_update_size(
- const struct treeview *tree,
- int width, int height)
+ const struct treeview *tree,
+ int width, int height)
{
+ int search_height = (tree->flags & TREEVIEW_SEARCHABLE) ?
+ tree_g.line_height : 0;
+
if (tree->cw_t != NULL) {
- tree->cw_t->update_size(tree->cw_h, width, height);
+ tree->cw_t->update_size(tree->cw_h, width,
+ height + search_height);
+ }
+}
+
+
+/**
+ * Corewindow callback_wrapper: Scroll to top of window.
+ *
+ * \param[in] tree The treeview to scroll.
+ */
+static inline void treeview__cw_scroll_top(
+ const struct treeview *tree)
+{
+ struct rect r = {
+ .x0 = 0,
+ .y0 = 0,
+ .x1 = tree_g.window_padding,
+ .y1 = tree_g.line_height,
+ };
+
+ if (tree->cw_t != NULL) {
+ tree->cw_t->scroll_visible(tree->cw_h, &r);
}
}
@@ -256,13 +402,13 @@ static inline void treeview__cw_update_size(
/**
* Corewindow callback wrapper: Get window viewport dimensions
*
- * \param[in] cw the core window object
+ * \param[in] tree The treeview to get dimensions for.
* \param[out] width to be set to viewport width in px
* \param[out] height to be set to viewport height in px
*/
static inline void treeview__cw_get_window_dimensions(
- const struct treeview *tree,
- int *width, int *height)
+ const struct treeview *tree,
+ int *width, int *height)
{
if (tree->cw_t != NULL) {
tree->cw_t->get_window_dimensions(tree->cw_h, width, height);
@@ -273,12 +419,12 @@ static inline void treeview__cw_get_window_dimensions(
/**
* Corewindow callback wrapper: Inform corewindow owner of drag status
*
- * \param[in] cw the core window object
+ * \param[in] tree The treeview to report status on.
* \param[in] ds the current drag status
*/
static inline void treeview__cw_drag_status(
- const struct treeview *tree,
- core_window_drag_status ds)
+ const struct treeview *tree,
+ core_window_drag_status ds)
{
if (tree->cw_t != NULL) {
tree->cw_t->drag_status(tree->cw_h, ds);
@@ -286,15 +432,16 @@ static inline void treeview__cw_drag_status(
}
-/* Helper function to access the given field of a node
+/**
+ * Helper function to access the given field of a node
*
- * \param tree Treeview that node belongs to
- * \param n Node to get field from
- * \param i Index of field of interest
+ * \param tree Treeview that node belongs to
+ * \param n Node to get field from
+ * \param i Index of field of interest
* \return text entry for field or NULL.
*/
-static inline struct treeview_text * treeview_get_text_for_field(
- treeview *tree, treeview_node *n, int i)
+static inline struct treeview_text *
+treeview_get_text_for_field(treeview *tree, treeview_node *n, int i)
{
if (i == 0) {
return &n->text;
@@ -309,19 +456,19 @@ static inline struct treeview_text * treeview_get_text_for_field(
}
-/* Find the next node in depth first tree order
+/**
+ * Find the next node in depth first tree order
*
- * \param node Start node
- * \param full Iff true, visit children of collapsed nodes
- * \param next Updated to next node, or NULL if 'node' is last node
- * \return NSERROR_OK on success, or appropriate error otherwise
+ * \param node Start node
+ * \param full Iff true, visit children of collapsed nodes
+ * \return next node, or NULL if \a node is last node
*/
static inline treeview_node * treeview_node_next(treeview_node *node, bool full)
{
assert(node != NULL);
if ((full || (node->flags & TV_NFLAGS_EXPANDED)) &&
- node->children != NULL) {
+ node->children != NULL) {
/* Next node is child */
node = node->children;
} else {
@@ -345,17 +492,17 @@ static inline treeview_node * treeview_node_next(treeview_node *node, bool full)
}
-/* Find node at given y-position
+/**
+ * Find node at given y-position
*
- * \param tree Treeview object to delete node from
- * \param target_y Target y-position
+ * \param tree Treeview object to delete node from
+ * \param target_y Target y-position
* \return node at y_target
*/
static treeview_node * treeview_y_node(treeview *tree, int target_y)
{
+ int y = (tree->flags & TREEVIEW_SEARCHABLE) ? tree_g.line_height : 0;
treeview_node *n;
- int y = 0;
- int h;
assert(tree != NULL);
assert(tree->root != NULL);
@@ -363,8 +510,8 @@ static treeview_node * treeview_y_node(treeview *tree, int target_y)
n = treeview_node_next(tree->root, false);
while (n != NULL) {
- h = (n->type == TREE_NODE_ENTRY) ?
- n->height : tree_g.line_height;
+ int h = (n->type == TREE_NODE_ENTRY) ?
+ n->height : tree_g.line_height;
if (target_y >= y && target_y < y + h)
return n;
y += h;
@@ -376,16 +523,19 @@ static treeview_node * treeview_y_node(treeview *tree, int target_y)
}
-/* Find y position of the top of a node
+/**
+ * Find y position of the top of a node
*
- * \param tree Treeview object to delete node from
- * \param node Node to get position of
+ * \param tree Treeview object to delete node from
+ * \param node Node to get position of
* \return node's y position
*/
-static int treeview_node_y(treeview *tree, treeview_node *node)
+static int treeview_node_y(
+ const treeview *tree,
+ const treeview_node *node)
{
treeview_node *n;
- int y = 0;
+ int y = (tree->flags & TREEVIEW_SEARCHABLE) ? tree_g.line_height : 0;
assert(tree != NULL);
assert(tree->root != NULL);
@@ -394,7 +544,7 @@ static int treeview_node_y(treeview *tree, treeview_node *node)
while (n != NULL && n != node) {
y += (n->type == TREE_NODE_ENTRY) ?
- n->height : tree_g.line_height;
+ n->height : tree_g.line_height;
n = treeview_node_next(n, false);
}
@@ -403,40 +553,108 @@ static int treeview_node_y(treeview *tree, treeview_node *node)
}
-/* Walk a treeview subtree, calling a callback at each node (depth first)
+/**
+ * Redraw tree from given node to the bottom.
+ *
+ * \param[in] tree Tree to redraw from node in.
+ * \param[in] node Node to redraw from.
+ */
+static void treeview__redraw_from_node(
+ const treeview *tree,
+ const treeview_node *node)
+{
+ int search_height = (tree->flags & TREEVIEW_SEARCHABLE) ?
+ tree_g.line_height : 0;
+ struct rect r = {
+ .x0 = 0,
+ .y0 = treeview_node_y(tree, node),
+ .x1 = REDRAW_MAX,
+ .y1 = treeview__get_display_height(tree) + search_height,
+ };
+
+ assert(tree != NULL);
+
+ treeview__cw_invalidate_area(tree, &r);
+}
+
+
+/**
+ * The treeview walk mode. Controls which nodes are visited in a walk.
+ */
+enum treeview_walk_mode {
+ /**
+ * Walk to all nodes in the (sub)tree.
+ */
+ TREEVIEW_WALK_MODE_LOGICAL_COMPLETE,
+
+ /**
+ * Walk to expanded nodes in the (sub)tree only. Children of
+ * collapsed nodes are not visited.
+ */
+ TREEVIEW_WALK_MODE_LOGICAL_EXPANDED,
+
+ /**
+ * Walk displayed nodes. This differs from the
+ * `TREEVIEW_WALK_MODE_LOGICAL_EXPANDED` mode when there is
+ * an active search filter display.
+ */
+ TREEVIEW_WALK_MODE_DISPLAY,
+};
+
+
+/**
+ * Walk a treeview subtree, calling a callback at each node (depth first)
*
+ * \param tree Treeview being walked.
* \param root Root to walk tree from (doesn't get a callback call)
- * \param full Iff true, visit children of collapsed nodes
+ * \param mode The treeview walk mode to use.
* \param callback_bwd Function to call on each node in backwards order
* \param callback_fwd Function to call on each node in forwards order
* \param ctx Context to pass to callback
* \return NSERROR_OK on success, or appropriate error otherwise
*
- * Note: Any node deletion must happen in callback_bwd.
+ * \note Any node deletion must happen in callback_bwd.
*/
-static nserror treeview_walk_internal(treeview_node *root, bool full,
- nserror (*callback_bwd)(treeview_node *n, void *ctx, bool *end),
- nserror (*callback_fwd)(treeview_node *n, void *ctx,
- bool *skip_children, bool *end),
+static nserror treeview_walk_internal(
+ treeview *tree,
+ treeview_node *root,
+ enum treeview_walk_mode mode,
+ nserror (*callback_bwd)(
+ treeview_node *n,
+ void *ctx,
+ bool *end),
+ nserror (*callback_fwd)(
+ treeview_node *n,
+ void *ctx,
+ bool *skip_children,
+ bool *end),
void *ctx)
{
treeview_node *node, *child, *parent, *next_sibling;
- bool abort = false;
+ bool walking_search = (mode == TREEVIEW_WALK_MODE_DISPLAY &&
+ tree->search.search == true);
bool skip_children = false;
+ bool abort = false;
+ bool full = false;
nserror err;
+ bool entry;
assert(root != NULL);
+ if (mode == TREEVIEW_WALK_MODE_LOGICAL_COMPLETE || walking_search) {
+ /* We need to visit children of collapsed folders. */
+ full = true;
+ }
+
node = root;
parent = node->parent;
next_sibling = node->next_sib;
- child = (!skip_children &&
- (full || (node->flags & TV_NFLAGS_EXPANDED))) ?
- node->children : NULL;
+ child = (full || (node->flags & TV_NFLAGS_EXPANDED)) ?
+ node->children : NULL;
while (node != NULL) {
- if (child != NULL) {
+ if (child != NULL && !skip_children) {
/* Down to children */
node = child;
} else {
@@ -444,9 +662,10 @@ static nserror treeview_walk_internal(treeview_node *root, bool full,
* go to next sibling if present, or nearest ancestor
* with a next sibling. */
- while (node != root &&
- next_sibling == NULL) {
- if (callback_bwd != NULL) {
+ while (node != root && next_sibling == NULL) {
+ entry = (node->type == TREE_NODE_ENTRY);
+ if (callback_bwd != NULL &&
+ (entry || !walking_search)) {
/* Backwards callback */
err = callback_bwd(node, ctx, &abort);
@@ -486,10 +705,17 @@ static nserror treeview_walk_internal(treeview_node *root, bool full,
assert(node != NULL);
assert(node != root);
+ entry = (node->type == TREE_NODE_ENTRY);
+
parent = node->parent;
next_sibling = node->next_sib;
child = (full || (node->flags & TV_NFLAGS_EXPANDED)) ?
- node->children : NULL;
+ node->children : NULL;
+
+ if (walking_search && (!entry ||
+ !(node->flags & TV_NFLAGS_MATCHED))) {
+ continue;
+ }
if (callback_fwd != NULL) {
/* Forwards callback */
@@ -503,16 +729,251 @@ static nserror treeview_walk_internal(treeview_node *root, bool full,
return NSERROR_OK;
}
}
- child = skip_children ? NULL : child;
}
return NSERROR_OK;
}
/**
+ * Data used when doing a treeview walk for search.
+ */
+struct treeview_search_walk_data {
+ treeview *tree; /**< The treeview to search. */
+ const char *text; /**< The string being searched for. */
+ const unsigned int len; /**< Length of string being searched for. */
+ int window_height; /**< Accumulate height for matching entries. */
+};
+
+
+/**
+ * Treewalk node callback for handling search.
+ *
+ * \param[in] n Current node.
+ * \param[in] ctx Treeview search context.
+ * \param[in,out] skip_children Flag to allow children to be skipped.
+ * \param[in,out] end Flag to allow iteration to be finished early.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror treeview__search_walk_cb(
+ treeview_node *n,
+ void *ctx,
+ bool *skip_children,
+ bool *end)
+{
+ struct treeview_search_walk_data *sw = ctx;
+
+ if (n->type != TREE_NODE_ENTRY) {
+ return NSERROR_OK;
+ }
+
+ if (sw->len == 0) {
+ n->flags &= ~TV_NFLAGS_MATCHED;
+ } else {
+ struct treeview_node_entry *entry =
+ (struct treeview_node_entry *)n;
+ bool matched = false;
+
+ for (int i = 0; i < sw->tree->n_fields; i++) {
+ struct treeview_field *ef = &(sw->tree->fields[i + 1]);
+ if (ef->flags & TREE_FLAG_SEARCHABLE) {
+ if (strcasestr(entry->fields[i].value.data,
+ sw->text) != NULL) {
+ matched = true;
+ break;
+ }
+ }
+ }
+
+ if (!matched && strcasestr(n->text.data, sw->text) != NULL) {
+ matched = true;
+ }
+
+ if (matched) {
+ n->flags |= TV_NFLAGS_MATCHED;
+ sw->window_height += n->height;
+ } else {
+ n->flags &= ~TV_NFLAGS_MATCHED;
+ }
+ }
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * Search treeview for text.
+ *
+ * \param[in] tree Treeview to search.
+ * \param[in] text UTF-8 string to search for. (NULL-terminated.)
+ * \param[in] len Byte length of UTF-8 string.
+ * \return NSERROR_OK on success, appropriate error otherwise.
+ */
+static nserror treeview__search(
+ treeview *tree,
+ const char *text,
+ unsigned int len)
+{
+ nserror err;
+ uint32_t height;
+ uint32_t prev_height = treeview__get_display_height(tree);
+ int search_height = (tree->flags & TREEVIEW_SEARCHABLE) ?
+ tree_g.line_height : 0;
+ struct treeview_search_walk_data sw = {
+ .len = len,
+ .text = text,
+ .tree = tree,
+ .window_height = 0,
+ };
+ struct rect r = {
+ .x0 = 0,
+ .y0 = search_height,
+ .x1 = REDRAW_MAX,
+ };
+
+ assert(text[len] == '\0');
+
+ if (tree->root == NULL) {
+ return NSERROR_OK;
+ }
+
+ err = treeview_walk_internal(tree, tree->root,
+ TREEVIEW_WALK_MODE_LOGICAL_COMPLETE, NULL,
+ treeview__search_walk_cb, &sw);
+ if (err != NSERROR_OK) {
+ return err;
+ }
+
+ if (len > 0) {
+ tree->search.height = sw.window_height;
+ tree->search.search = true;
+ height = sw.window_height;
+ } else {
+ tree->search.search = false;
+ height = tree->root->height;
+ }
+
+ r.y1 = ((height > prev_height) ? height : prev_height) + search_height;
+ treeview__cw_invalidate_area(tree, &r);
+ treeview__cw_update_size(tree, -1, height);
+ treeview__cw_scroll_top(tree);
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * Cancel a treeview search, optionally droping focus from search widget.
+ *
+ * \param[in] tree Treeview to cancel search in.
+ * \param[in] drop_focus Iff true, drop input focus from search widget.
+ */
+static void treeview__search_cancel(treeview *tree, bool drop_focus)
+{
+ struct rect r = {
+ .x0 = tree_g.window_padding + tree_g.icon_size,
+ .x1 = 600,
+ .y0 = 0,
+ .y1 = tree_g.line_height,
+ };
+
+ tree->search.search = false;
+ if (tree->search.active == false) {
+ return;
+ }
+
+ if (drop_focus) {
+ tree->search.active = false;
+ textarea_set_caret(tree->search.textarea, -1);
+ } else {
+ textarea_set_caret(tree->search.textarea, 0);
+ }
+
+ textarea_set_text(tree->search.textarea, "");
+ treeview__cw_invalidate_area(tree, &r);
+}
+
+
+/**
+ * Callback for textarea_create, in desktop/treeview.h
+ *
+ * \param data treeview context
+ * \param msg textarea message
+ */
+static void treeview_textarea_search_callback(void *data,
+ struct textarea_msg *msg)
+{
+ treeview *tree = data;
+ struct rect *r;
+
+ if (tree->search.active == false || tree->root == NULL) {
+ return;
+ }
+
+ switch (msg->type) {
+ case TEXTAREA_MSG_DRAG_REPORT:
+ if (msg->data.drag == TEXTAREA_DRAG_NONE) {
+ /* Textarea drag finished */
+ tree->drag.type = TV_DRAG_NONE;
+ } else {
+ /* Textarea drag started */
+ tree->drag.type = TV_DRAG_SEARCH;
+ }
+ treeview__cw_drag_status(tree, tree->drag.type);
+ break;
+
+ case TEXTAREA_MSG_REDRAW_REQUEST:
+ r = &msg->data.redraw;
+ r->x0 += tree_g.window_padding + tree_g.icon_size;
+ r->y0 += 0;
+ r->x1 += 600;
+ r->y1 += tree_g.line_height;
+
+ /* Redraw the textarea */
+ treeview__cw_invalidate_area(tree, r);
+ break;
+
+ case TEXTAREA_MSG_TEXT_MODIFIED:
+ /* Textarea length includes trailing NULL, so subtract it. */
+ treeview__search(tree,
+ msg->data.modified.text,
+ msg->data.modified.len - 1);
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+/**
+ * Update the layout for any active search.
+ *
+ * \param[in] tree The tree to update.
+ */
+static void treeview__search_update_display(
+ treeview *tree)
+{
+ const char *string;
+ unsigned int len;
+
+ if (tree->search.search == false) {
+ /* No active search to update view for. */
+ return;
+ }
+
+ string = textarea_data(tree->search.textarea, &len);
+ if (string == NULL || len == 0) {
+ return;
+ }
+
+ treeview__search(tree, string, len - 1);
+}
+
+
+/**
* Create treeview's root node
*
- * \param root Returns root node
+ * \param[out] root Returns root node
* \return NSERROR_OK on success, appropriate error otherwise
*/
static nserror treeview_create_node_root(treeview_node **root)
@@ -548,10 +1009,20 @@ static nserror treeview_create_node_root(treeview_node **root)
/**
- * Set a node's inset from its parent (can be used as treeview walk callback)
+ * Set a node's inset from its parent
+ *
+ * This may be used as treeview walk callback
+ *
+ * \param[in] n node to set inset on
+ * \param[in] ctx context unused
+ * \param[out] skip_children set to false so child nodes are not skipped.
+ * \param[out] end unused flag so treewalk in not terminated early.
*/
-static nserror treeview_set_inset_from_parent(treeview_node *n, void *ctx,
- bool *skip_children, bool *end)
+static nserror
+treeview_set_inset_from_parent(treeview_node *n,
+ void *ctx,
+ bool *skip_children,
+ bool *end)
{
if (n->parent != NULL)
n->inset = n->parent->inset + tree_g.step_width;
@@ -559,14 +1030,20 @@ static nserror treeview_set_inset_from_parent(treeview_node *n, void *ctx,
*skip_children = false;
return NSERROR_OK;
}
+
+
/**
* Insert a treeview node into a treeview
*
- * \param a parentless node to insert
- * \param b tree node to insert a as a relation of
- * \param rel a's relationship to b
+ * \param tree the treeview to insert node into.
+ * \param a parentless node to insert
+ * \param b tree node to insert a as a relation of
+ * \param rel The relationship between \a a and \a b
*/
-static inline void treeview_insert_node(treeview_node *a,
+static inline void
+treeview_insert_node(
+ treeview *tree,
+ treeview_node *a,
treeview_node *b,
enum treeview_relationship rel)
{
@@ -603,7 +1080,8 @@ static inline void treeview_insert_node(treeview_node *a,
a->inset = a->parent->inset + tree_g.step_width;
if (a->children != NULL) {
- treeview_walk_internal(a, true, NULL,
+ treeview_walk_internal(tree, a,
+ TREEVIEW_WALK_MODE_LOGICAL_COMPLETE, NULL,
treeview_set_inset_from_parent, NULL);
}
@@ -627,12 +1105,14 @@ static inline void treeview_insert_node(treeview_node *a,
/* Exported interface, documented in treeview.h */
-nserror treeview_create_node_folder(treeview *tree,
- treeview_node **folder,
- treeview_node *relation,
- enum treeview_relationship rel,
- const struct treeview_field_data *field,
- void *data, treeview_node_options_flags flags)
+nserror
+treeview_create_node_folder(treeview *tree,
+ treeview_node **folder,
+ treeview_node *relation,
+ enum treeview_relationship rel,
+ const struct treeview_field_data *field,
+ void *data,
+ treeview_node_options_flags flags)
{
treeview_node *n;
@@ -651,7 +1131,7 @@ nserror treeview_create_node_folder(treeview *tree,
}
n->flags = (flags & TREE_OPTION_SPECIAL_DIR) ?
- TV_NFLAGS_SPECIAL : TV_NFLAGS_NONE;
+ TV_NFLAGS_SPECIAL : TV_NFLAGS_NONE;
n->type = TREE_NODE_FOLDER;
n->height = tree_g.line_height;
@@ -667,13 +1147,13 @@ nserror treeview_create_node_folder(treeview *tree,
n->client_data = data;
- treeview_insert_node(n, relation, rel);
+ treeview_insert_node(tree, n, relation, rel);
if (n->parent->flags & TV_NFLAGS_EXPANDED) {
/* Inform front end of change in dimensions */
if (!(flags & TREE_OPTION_SUPPRESS_RESIZE))
treeview__cw_update_size(tree, -1,
- tree->root->height);
+ tree->root->height);
/* Redraw */
if (!(flags & TREE_OPTION_SUPPRESS_REDRAW)) {
@@ -682,7 +1162,7 @@ nserror treeview_create_node_folder(treeview *tree,
r.y0 = treeview_node_y(tree, n);
r.x1 = REDRAW_MAX;
r.y1 = tree->root->height;
- treeview__cw_redraw_request(tree, &r);
+ treeview__cw_invalidate_area(tree, &r);
}
}
@@ -693,10 +1173,11 @@ nserror treeview_create_node_folder(treeview *tree,
/* Exported interface, documented in treeview.h */
-nserror treeview_update_node_folder(treeview *tree,
- treeview_node *folder,
- const struct treeview_field_data *field,
- void *data)
+nserror
+treeview_update_node_folder(treeview *tree,
+ treeview_node *folder,
+ const struct treeview_field_data *field,
+ void *data)
{
bool match;
@@ -708,8 +1189,8 @@ nserror treeview_update_node_folder(treeview *tree,
assert(field != NULL);
assert(lwc_string_isequal(tree->fields[tree->n_fields].field,
- field->field, &match) == lwc_error_ok &&
- match == true);
+ field->field, &match) == lwc_error_ok &&
+ match == true);
folder->text.data = field->value;
folder->text.len = field->value_len;
folder->text.width = 0;
@@ -717,9 +1198,9 @@ nserror treeview_update_node_folder(treeview *tree,
if (folder->parent->flags & TV_NFLAGS_EXPANDED) {
/* Text will be seen, get its width */
guit->layout->width(&plot_style_odd.text,
- folder->text.data,
- folder->text.len,
- &(folder->text.width));
+ folder->text.data,
+ folder->text.len,
+ &(folder->text.width));
} else {
/* Just invalidate the width, since it's not needed now */
folder->text.width = 0;
@@ -732,7 +1213,7 @@ nserror treeview_update_node_folder(treeview *tree,
r.y0 = treeview_node_y(tree, folder);
r.x1 = REDRAW_MAX;
r.y1 = r.y0 + tree_g.line_height;
- treeview__cw_redraw_request(tree, &r);
+ treeview__cw_invalidate_area(tree, &r);
}
return NSERROR_OK;
@@ -740,10 +1221,11 @@ nserror treeview_update_node_folder(treeview *tree,
/* Exported interface, documented in treeview.h */
-nserror treeview_update_node_entry(treeview *tree,
- treeview_node *entry,
- const struct treeview_field_data fields[],
- void *data)
+nserror
+treeview_update_node_entry(treeview *tree,
+ treeview_node *entry,
+ const struct treeview_field_data fields[],
+ void *data)
{
bool match;
struct treeview_node_entry *e = (struct treeview_node_entry *)entry;
@@ -758,8 +1240,8 @@ nserror treeview_update_node_entry(treeview *tree,
assert(fields != NULL);
assert(fields[0].field != NULL);
assert(lwc_string_isequal(tree->fields[0].field,
- fields[0].field, &match) == lwc_error_ok &&
- match == true);
+ fields[0].field, &match) == lwc_error_ok &&
+ match == true);
entry->text.data = fields[0].value;
entry->text.len = fields[0].value_len;
entry->text.width = 0;
@@ -767,9 +1249,9 @@ nserror treeview_update_node_entry(treeview *tree,
if (entry->parent->flags & TV_NFLAGS_EXPANDED) {
/* Text will be seen, get its width */
guit->layout->width(&plot_style_odd.text,
- entry->text.data,
- entry->text.len,
- &(entry->text.width));
+ entry->text.data,
+ entry->text.len,
+ &(entry->text.width));
} else {
/* Just invalidate the width, since it's not needed now */
entry->text.width = 0;
@@ -778,8 +1260,8 @@ nserror treeview_update_node_entry(treeview *tree,
for (i = 1; i < tree->n_fields; i++) {
assert(fields[i].field != NULL);
assert(lwc_string_isequal(tree->fields[i].field,
- fields[i].field, &match) == lwc_error_ok &&
- match == true);
+ fields[i].field, &match) == lwc_error_ok &&
+ match == true);
e->fields[i - 1].value.data = fields[i].value;
e->fields[i - 1].value.len = fields[i].value_len;
@@ -787,15 +1269,17 @@ nserror treeview_update_node_entry(treeview *tree,
if (entry->flags & TV_NFLAGS_EXPANDED) {
/* Text will be seen, get its width */
guit->layout->width(&plot_style_odd.text,
- e->fields[i - 1].value.data,
- e->fields[i - 1].value.len,
- &(e->fields[i - 1].value.width));
+ e->fields[i - 1].value.data,
+ e->fields[i - 1].value.len,
+ &(e->fields[i - 1].value.width));
} else {
/* Invalidate the width, since it's not needed yet */
e->fields[i - 1].value.width = 0;
}
}
+ treeview__search_update_display(tree);
+
/* Redraw */
if (entry->parent->flags & TV_NFLAGS_EXPANDED) {
struct rect r;
@@ -803,7 +1287,7 @@ nserror treeview_update_node_entry(treeview *tree,
r.y0 = treeview_node_y(tree, entry);
r.x1 = REDRAW_MAX;
r.y1 = r.y0 + entry->height;
- treeview__cw_redraw_request(tree, &r);
+ treeview__cw_invalidate_area(tree, &r);
}
return NSERROR_OK;
@@ -811,12 +1295,14 @@ nserror treeview_update_node_entry(treeview *tree,
/* Exported interface, documented in treeview.h */
-nserror treeview_create_node_entry(treeview *tree,
- treeview_node **entry,
- treeview_node *relation,
- enum treeview_relationship rel,
- const struct treeview_field_data fields[],
- void *data, treeview_node_options_flags flags)
+nserror
+treeview_create_node_entry(treeview *tree,
+ treeview_node **entry,
+ treeview_node *relation,
+ enum treeview_relationship rel,
+ const struct treeview_field_data fields[],
+ void *data,
+ treeview_node_options_flags flags)
{
bool match;
struct treeview_node_entry *e;
@@ -873,13 +1359,13 @@ nserror treeview_create_node_entry(treeview *tree,
e->fields[i - 1].value.width = 0;
}
- treeview_insert_node(n, relation, rel);
+ treeview_insert_node(tree, n, relation, rel);
if (n->parent->flags & TV_NFLAGS_EXPANDED) {
/* Inform front end of change in dimensions */
if (!(flags & TREE_OPTION_SUPPRESS_RESIZE))
treeview__cw_update_size(tree, -1,
- tree->root->height);
+ tree->root->height);
/* Redraw */
if (!(flags & TREE_OPTION_SUPPRESS_REDRAW)) {
@@ -888,25 +1374,42 @@ nserror treeview_create_node_entry(treeview *tree,
r.y0 = treeview_node_y(tree, n);
r.x1 = REDRAW_MAX;
r.y1 = tree->root->height;
- treeview__cw_redraw_request(tree, &r);
+ treeview__cw_invalidate_area(tree, &r);
}
}
+ treeview__search_update_display(tree);
+
*entry = n;
return NSERROR_OK;
}
+/**
+ * Treewalk iterator context
+ */
struct treeview_walk_ctx {
treeview_walk_cb enter_cb;
treeview_walk_cb leave_cb;
void *ctx;
enum treeview_node_type type;
};
-/** Treewalk node enter callback. */
-static nserror treeview_walk_fwd_cb(treeview_node *n, void *ctx,
- bool *skip_children, bool *end)
+
+
+/**
+ * Treewalk node enter callback.
+ *
+ * \param n current node
+ * \param ctx treewalk context
+ * \param skip_children set if child nodes should be skipped
+ * \param end set if iteration should end early
+ */
+static nserror
+treeview_walk_fwd_cb(treeview_node *n,
+ void *ctx,
+ bool *skip_children,
+ bool *end)
{
struct treeview_walk_ctx *tw = ctx;
@@ -916,7 +1419,15 @@ static nserror treeview_walk_fwd_cb(treeview_node *n, void *ctx,
return NSERROR_OK;
}
-/** Treewalk node leave callback. */
+
+
+/**
+ * Treewalk node leave callback.
+ *
+ * \param n current node
+ * \param ctx treewalk context
+ * \param end set if iteration should end early
+ */
static nserror treeview_walk_bwd_cb(treeview_node *n, void *ctx, bool *end)
{
struct treeview_walk_ctx *tw = ctx;
@@ -927,10 +1438,16 @@ static nserror treeview_walk_bwd_cb(treeview_node *n, void *ctx, bool *end)
return NSERROR_OK;
}
+
+
/* Exported interface, documented in treeview.h */
-nserror treeview_walk(treeview *tree, treeview_node *root,
- treeview_walk_cb enter_cb, treeview_walk_cb leave_cb,
- void *ctx, enum treeview_node_type type)
+nserror
+treeview_walk(treeview *tree,
+ treeview_node *root,
+ treeview_walk_cb enter_cb,
+ treeview_walk_cb leave_cb,
+ void *ctx,
+ enum treeview_node_type type)
{
struct treeview_walk_ctx tw = {
.enter_cb = enter_cb,
@@ -945,16 +1462,18 @@ nserror treeview_walk(treeview *tree, treeview_node *root,
if (root == NULL)
root = tree->root;
- return treeview_walk_internal(root, true,
+ return treeview_walk_internal(tree, root,
+ TREEVIEW_WALK_MODE_LOGICAL_COMPLETE,
(leave_cb != NULL) ? treeview_walk_bwd_cb : NULL,
- (enter_cb != NULL) ? treeview_walk_fwd_cb : NULL, &tw);
+ (enter_cb != NULL) ? treeview_walk_fwd_cb : NULL,
+ &tw);
}
/**
* Unlink a treeview node
*
- * \param n Node to unlink
+ * \param n Node to unlink
* \return true iff ancestor heights need to be reduced
*/
static inline bool treeview_unlink_node(treeview_node *n)
@@ -975,7 +1494,8 @@ static inline bool treeview_unlink_node(treeview_node *n)
}
/* Reduce ancestor heights */
- if (n->parent != NULL && n->parent->flags & TV_NFLAGS_EXPANDED) {
+ if ((n->parent != NULL) &&
+ (n->parent->flags & TV_NFLAGS_EXPANDED)) {
return true;
}
@@ -986,8 +1506,8 @@ static inline bool treeview_unlink_node(treeview_node *n)
/**
* Cancel the editing of a treeview node
*
- * \param tree Treeview object to cancel node editing in
- * \param redraw Set true iff redraw of removed textarea area required
+ * \param tree Treeview object to cancel node editing in
+ * \param redraw Set true iff redraw of removed textarea area required
*/
static void treeview_edit_cancel(treeview *tree, bool redraw)
{
@@ -1009,15 +1529,17 @@ static void treeview_edit_cancel(treeview *tree, bool redraw)
r.y0 = tree->edit.y;
r.x1 = tree->edit.x + tree->edit.w;
r.y1 = tree->edit.y + tree->edit.h;
- treeview__cw_redraw_request(tree, &r);
+ treeview__cw_invalidate_area(tree, &r);
}
}
/**
- * Complete a treeview edit, by informing the client with a change request msg
+ * Complete a treeview edit
+ *
+ * Complete edit by informing the client with a change request msg
*
- * \param tree Treeview object to complete edit in
+ * \param tree Treeview object to complete edit in
*/
static void treeview_edit_done(treeview *tree)
{
@@ -1027,8 +1549,9 @@ static void treeview_edit_done(treeview *tree)
struct treeview_node_msg msg;
msg.msg = TREE_MSG_NODE_EDIT;
- if (tree->edit.textarea == NULL)
+ if (tree->edit.textarea == NULL) {
return;
+ }
assert(n != NULL);
@@ -1066,7 +1589,6 @@ static void treeview_edit_done(treeview *tree)
break;
}
-
/* Finished with the new text */
free(new_text);
@@ -1075,17 +1597,25 @@ static void treeview_edit_done(treeview *tree)
}
+/**
+ * context for treeview node deletion iterator
+ */
struct treeview_node_delete {
treeview *tree;
int h_reduction;
bool user_interaction;
};
-/** Treewalk node callback deleting nodes. */
-static nserror treeview_delete_node_walk_cb(treeview_node *n,
- void *ctx, bool *end)
+
+
+/**
+ * Treewalk node callback deleting nodes.
+ */
+static nserror
+treeview_delete_node_walk_cb(treeview_node *n, void *ctx, bool *end)
{
struct treeview_node_delete *nd = (struct treeview_node_delete *)ctx;
struct treeview_node_msg msg;
+
msg.msg = TREE_MSG_NODE_DELETE;
msg.data.delete.user = nd->user_interaction;
@@ -1093,51 +1623,60 @@ static nserror treeview_delete_node_walk_cb(treeview_node *n,
if (treeview_unlink_node(n))
nd->h_reduction += (n->type == TREE_NODE_ENTRY) ?
- n->height : tree_g.line_height;
+ n->height : tree_g.line_height;
/* Handle any special treatment */
switch (n->type) {
case TREE_NODE_ENTRY:
nd->tree->callbacks->entry(msg, n->client_data);
break;
+
case TREE_NODE_FOLDER:
nd->tree->callbacks->folder(msg, n->client_data);
break;
+
case TREE_NODE_ROOT:
break;
+
default:
return NSERROR_BAD_PARAMETER;
}
/* Cancel any edit of this node */
if (nd->tree->edit.textarea != NULL &&
- nd->tree->edit.node == n)
+ nd->tree->edit.node == n) {
treeview_edit_cancel(nd->tree, false);
+ }
/* Free the node */
free(n);
return NSERROR_OK;
}
+
+
/**
* Delete a treeview node
*
- * \param tree Treeview object to delete node from
- * \param n Node to delete
- * \param interaction Delete is result of user interaction with treeview
- * \param flags Treeview node options flags
- * \return NSERROR_OK on success, appropriate error otherwise
- *
* Will emit folder or entry deletion msg callback.
*
- * Note this can be called from inside a treeview_walk fwd callback.
+ * \note this can be called from inside a treeview_walk fwd callback.
* For example walking the tree and calling this for any node that's selected.
*
* This function does not delete empty nodes, so if TREEVIEW_DEL_EMPTY_DIRS is
* set, caller must also call treeview_delete_empty.
+ *
+ * \param tree Treeview object to delete node from
+ * \param n Node to delete
+ * \param interaction Delete is result of user interaction with treeview
+ * \param flags Treeview node options flags
+ * \return NSERROR_OK on success, appropriate error otherwise
*/
-static nserror treeview_delete_node_internal(treeview *tree, treeview_node *n,
- bool interaction, treeview_node_options_flags flags)
+static nserror
+treeview_delete_node_internal(treeview *tree,
+ treeview_node *n,
+ bool interaction,
+ treeview_node_options_flags flags)
{
nserror err;
treeview_node *p = n->parent;
@@ -1152,8 +1691,9 @@ static nserror treeview_delete_node_internal(treeview *tree, treeview_node *n,
}
/* Delete any children first */
- err = treeview_walk_internal(n, true, treeview_delete_node_walk_cb,
- NULL, &nd);
+ err = treeview_walk_internal(tree, n,
+ TREEVIEW_WALK_MODE_LOGICAL_COMPLETE,
+ treeview_delete_node_walk_cb, NULL, &nd);
if (err != NSERROR_OK) {
return err;
}
@@ -1175,12 +1715,14 @@ static nserror treeview_delete_node_internal(treeview *tree, treeview_node *n,
/* Inform front end of change in dimensions */
if (tree->root != NULL && p != NULL && p->flags & TV_NFLAGS_EXPANDED &&
- nd.h_reduction > 0 &&
- !(flags & TREE_OPTION_SUPPRESS_RESIZE)) {
+ nd.h_reduction > 0 &&
+ !(flags & TREE_OPTION_SUPPRESS_RESIZE)) {
treeview__cw_update_size(tree, -1,
- tree->root->height);
+ tree->root->height);
}
+ treeview__search_update_display(tree);
+
return NSERROR_OK;
}
@@ -1188,8 +1730,8 @@ static nserror treeview_delete_node_internal(treeview *tree, treeview_node *n,
/**
* Delete any empty treeview folder nodes
*
- * \param tree Treeview object to delete empty nodes from
- * \param interaction Delete is result of user interaction with treeview
+ * \param tree Treeview object to delete empty nodes from
+ * \param interaction Delete is result of user interaction with treeview
* \return NSERROR_OK on success, appropriate error otherwise
*
* Note this must not be called within a treeview_walk. It may delete the
@@ -1226,21 +1768,21 @@ static nserror treeview_delete_empty_nodes(treeview *tree, bool interaction)
* with a next sibling. */
while (node->parent != NULL &&
- next_sibling == NULL) {
+ next_sibling == NULL) {
if (node->type == TREE_NODE_FOLDER &&
- node->children == NULL) {
+ node->children == NULL) {
/* Delete node */
p = node->parent;
err = treeview_delete_node_walk_cb(
- node, &nd, &abort);
+ node, &nd, &abort);
if (err != NSERROR_OK) {
return err;
}
/* Reduce ancestor heights */
while (p != NULL &&
- p->flags &
- TV_NFLAGS_EXPANDED) {
+ p->flags &
+ TV_NFLAGS_EXPANDED) {
p->height -= nd.h_reduction;
p = p->parent;
}
@@ -1255,18 +1797,18 @@ static nserror treeview_delete_empty_nodes(treeview *tree, bool interaction)
break;
if (node->type == TREE_NODE_FOLDER &&
- node->children == NULL) {
+ node->children == NULL) {
/* Delete node */
p = node->parent;
err = treeview_delete_node_walk_cb(
- node, &nd, &abort);
+ node, &nd, &abort);
if (err != NSERROR_OK) {
return err;
}
/* Reduce ancestor heights */
while (p != NULL &&
- p->flags & TV_NFLAGS_EXPANDED) {
+ p->flags & TV_NFLAGS_EXPANDED) {
p->height -= nd.h_reduction;
p = p->parent;
}
@@ -1281,7 +1823,7 @@ static nserror treeview_delete_empty_nodes(treeview *tree, bool interaction)
parent = node->parent;
next_sibling = node->next_sib;
child = (node->flags & TV_NFLAGS_EXPANDED) ?
- node->children : NULL;
+ node->children : NULL;
}
return NSERROR_OK;
@@ -1289,8 +1831,10 @@ static nserror treeview_delete_empty_nodes(treeview *tree, bool interaction)
/* Exported interface, documented in treeview.h */
-nserror treeview_delete_node(treeview *tree, treeview_node *n,
- treeview_node_options_flags flags)
+nserror
+treeview_delete_node(treeview *tree,
+ treeview_node *n,
+ treeview_node_options_flags flags)
{
nserror err;
struct rect r;
@@ -1321,7 +1865,7 @@ nserror treeview_delete_node(treeview *tree, treeview_node *n,
r.y0 = 0;
if (!(flags & TREE_OPTION_SUPPRESS_RESIZE)) {
treeview__cw_update_size(tree, -1,
- tree->root->height);
+ tree->root->height);
}
}
}
@@ -1330,19 +1874,69 @@ nserror treeview_delete_node(treeview *tree, treeview_node *n,
if (visible && !(flags & TREE_OPTION_SUPPRESS_REDRAW)) {
r.x0 = 0;
r.x1 = REDRAW_MAX;
- treeview__cw_redraw_request(tree, &r);
+ treeview__cw_invalidate_area(tree, &r);
}
return NSERROR_OK;
}
+/**
+ * Helper to create a textarea.
+ *
+ * \param[in] tree The treeview we're creating the textarea for.
+ * \param[in] width The width of the textarea.
+ * \param[in] height The height of the textarea.
+ * \param[in] border The border colour to use.
+ * \param[in] background The background colour to use.
+ * \param[in] foreground The foreground colour to use.
+ * \param[in] text The text style to use for the text area.
+ * \param[in] ta_callback The textarea callback function to give the textarea.
+ * \return the textarea pointer on success, or NULL on failure.
+ */
+static struct textarea *treeview__create_textarea(
+ treeview *tree,
+ int width,
+ int height,
+ colour border,
+ colour background,
+ colour foreground,
+ plot_font_style_t text,
+ textarea_client_callback ta_callback)
+{
+ /* Configure the textarea */
+ textarea_flags ta_flags = TEXTAREA_INTERNAL_CARET;
+ textarea_setup ta_setup = {
+ .text = text,
+ .width = width,
+ .height = height,
+ .pad_top = 0,
+ .pad_left = 2,
+ .pad_right = 2,
+ .pad_bottom = 0,
+ .border_width = 1,
+ .border_col = border,
+ .selected_bg = foreground,
+ .selected_text = background,
+ };
+
+ ta_setup.text.foreground = foreground;
+ ta_setup.text.background = background;
+
+ /* Create text area */
+ return textarea_create(ta_flags, &ta_setup, ta_callback, tree);
+}
+
+
/* Exported interface, documented in treeview.h */
-nserror treeview_create(treeview **tree,
+nserror
+treeview_create(treeview **tree,
const struct treeview_callback_table *callbacks,
- int n_fields, struct treeview_field_desc fields[],
+ int n_fields,
+ struct treeview_field_desc fields[],
const struct core_window_callback_table *cw_t,
- struct core_window *cw, treeview_flags flags)
+ struct core_window *cw,
+ treeview_flags flags)
{
nserror error;
int i;
@@ -1383,7 +1977,7 @@ nserror treeview_create(treeview **tree,
f->value.len = lwc_string_length(fields[i].field);
guit->layout->width(&plot_style_odd.text, f->value.data,
- f->value.len, &(f->value.width));
+ f->value.len, &(f->value.width));
if (f->flags & TREE_FLAG_SHOW_NAME)
if ((*tree)->field_width < f->value.width)
@@ -1413,6 +2007,24 @@ nserror treeview_create(treeview **tree,
(*tree)->edit.textarea = NULL;
(*tree)->edit.node = NULL;
+ if (flags & TREEVIEW_SEARCHABLE) {
+ (*tree)->search.textarea = treeview__create_textarea(
+ *tree, 600, tree_g.line_height,
+ plot_style_even.text.background,
+ plot_style_even.text.background,
+ plot_style_even.text.foreground,
+ plot_style_odd.text,
+ treeview_textarea_search_callback);
+ if ((*tree)->search.textarea == NULL) {
+ treeview_destroy(*tree);
+ return NSERROR_NOMEM;
+ }
+ } else {
+ (*tree)->search.textarea = NULL;
+ }
+ (*tree)->search.active = false;
+ (*tree)->search.search = false;
+
(*tree)->flags = flags;
(*tree)->cw_t = cw_t;
@@ -1423,15 +2035,16 @@ nserror treeview_create(treeview **tree,
/* Exported interface, documented in treeview.h */
-nserror treeview_cw_attach(treeview *tree,
- const struct core_window_callback_table *cw_t,
- struct core_window *cw)
+nserror
+treeview_cw_attach(treeview *tree,
+ const struct core_window_callback_table *cw_t,
+ struct core_window *cw)
{
assert(cw_t != NULL);
assert(cw != NULL);
if (tree->cw_t != NULL || tree->cw_h != NULL) {
- LOG("Treeview already attached.");
+ NSLOG(netsurf, INFO, "Treeview already attached.");
return NSERROR_UNKNOWN;
}
tree->cw_t = cw_t;
@@ -1447,6 +2060,8 @@ nserror treeview_cw_detach(treeview *tree)
tree->cw_t = NULL;
tree->cw_h = NULL;
+ treeview__search_cancel(tree, true);
+
return NSERROR_OK;
}
@@ -1458,10 +2073,16 @@ nserror treeview_destroy(treeview *tree)
assert(tree != NULL);
+ if (tree->search.textarea != NULL) {
+ tree->search.active = false;
+ tree->search.search = false;
+ textarea_destroy(tree->search.textarea);
+ }
+
/* Destroy nodes */
treeview_delete_node_internal(tree, tree->root, false,
- TREE_OPTION_SUPPRESS_RESIZE |
- TREE_OPTION_SUPPRESS_REDRAW);
+ TREE_OPTION_SUPPRESS_RESIZE |
+ TREE_OPTION_SUPPRESS_REDRAW);
/* Destroy feilds */
for (f = 0; f <= tree->n_fields; f++) {
@@ -1483,8 +2104,8 @@ nserror treeview_destroy(treeview *tree)
* \param node The node to expand.
* \return NSERROR_OK on success, appropriate error otherwise.
*/
-static nserror treeview_node_expand_internal(treeview *tree,
- treeview_node *node)
+static nserror
+treeview_node_expand_internal(treeview *tree, treeview_node *node)
{
treeview_node *child;
struct treeview_node_entry *e;
@@ -1496,7 +2117,7 @@ static nserror treeview_node_expand_internal(treeview *tree,
if (node->flags & TV_NFLAGS_EXPANDED) {
/* What madness is this? */
- LOG("Tried to expand an expanded node.");
+ NSLOG(netsurf, INFO, "Tried to expand an expanded node.");
return NSERROR_OK;
}
@@ -1509,12 +2130,11 @@ static nserror treeview_node_expand_internal(treeview *tree,
}
do {
- assert((child->flags & TV_NFLAGS_EXPANDED) == false);
if (child->text.width == 0) {
guit->layout->width(&plot_style_odd.text,
- child->text.data,
- child->text.len,
- &(child->text.width));
+ child->text.data,
+ child->text.len,
+ &(child->text.width));
}
additional_height += child->height;
@@ -1533,9 +2153,9 @@ static nserror treeview_node_expand_internal(treeview *tree,
if (e->fields[i].value.width == 0) {
guit->layout->width(&plot_style_odd.text,
- e->fields[i].value.data,
- e->fields[i].value.len,
- &(e->fields[i].value.width));
+ e->fields[i].value.data,
+ e->fields[i].value.len,
+ &(e->fields[i].value.width));
}
/* Add height for field */
@@ -1554,17 +2174,24 @@ static nserror treeview_node_expand_internal(treeview *tree,
/* Update the node */
node->flags |= TV_NFLAGS_EXPANDED;
- /* And parent's heights */
- do {
- node->height += additional_height;
- node = node->parent;
- } while (node->parent != NULL);
+ /* And node heights */
+ for (struct treeview_node *n = node;
+ (n != NULL) && (n->flags & TV_NFLAGS_EXPANDED);
+ n = n->parent) {
+ n->height += additional_height;
+ }
- node->height += additional_height;
+ if (tree->search.search &&
+ node->type == TREE_NODE_ENTRY &&
+ node->flags & TV_NFLAGS_MATCHED) {
+ tree->search.height += additional_height;
+ }
/* Inform front end of change in dimensions */
- if (additional_height != 0)
- treeview__cw_update_size(tree, -1, tree->root->height);
+ if (additional_height != 0) {
+ treeview__cw_update_size(tree, -1,
+ treeview__get_display_height(tree));
+ }
return NSERROR_OK;
}
@@ -1573,29 +2200,37 @@ static nserror treeview_node_expand_internal(treeview *tree,
/* Exported interface, documented in treeview.h */
nserror treeview_node_expand(treeview *tree, treeview_node *node)
{
- nserror err;
- struct rect r;
-
- err = treeview_node_expand_internal(tree, node);
- if (err != NSERROR_OK)
- return err;
-
- r.x0 = 0;
- r.y0 = treeview_node_y(tree, node);
- r.x1 = REDRAW_MAX;
- r.y1 = tree->root->height;
-
- /* Redraw */
- treeview__cw_redraw_request(tree, &r);
+ nserror res;
+
+ res = treeview_node_expand_internal(tree, node);
+ NSLOG(netsurf, INFO, "Expanding!");
+ if (res == NSERROR_OK) {
+ /* expansion was successful, attempt redraw */
+ treeview__redraw_from_node(tree, node);
+ NSLOG(netsurf, INFO, "Expanded!");
+ }
- return NSERROR_OK;
+ return res;
}
+/**
+ * context for treeview contraction callback
+ */
struct treeview_contract_data {
+ treeview *tree;
bool only_entries;
};
-/** Treewalk node callback for handling node contraction. */
+
+
+/**
+ * Treewalk node callback for handling node contraction.
+ *
+ * \param n node
+ * \param ctx contract iterator context
+ * \param end flag to end iteration now
+ * \return NSERROR_OK on success else appropriate error code
+ */
static nserror treeview_node_contract_cb(treeview_node *n, void *ctx, bool *end)
{
struct treeview_contract_data *data = ctx;
@@ -1607,32 +2242,39 @@ static nserror treeview_node_contract_cb(treeview_node *n, void *ctx, bool *end)
n->flags &= ~TV_NFLAGS_SELECTED;
if ((n->flags & TV_NFLAGS_EXPANDED) == false ||
- (n->type == TREE_NODE_FOLDER && data->only_entries)) {
+ (n->type == TREE_NODE_FOLDER && data->only_entries)) {
/* Nothing to do. */
return NSERROR_OK;
}
- n->flags ^= TV_NFLAGS_EXPANDED;
h_reduction = n->height - tree_g.line_height;
assert(h_reduction >= 0);
+ for (struct treeview_node *node = n;
+ (node != NULL) && (node->flags & TV_NFLAGS_EXPANDED);
+ node = node->parent) {
+ node->height -= h_reduction;
+ }
- do {
- n->height -= h_reduction;
- n = n->parent;
- } while (n != NULL);
+ if (data->tree->search.search) {
+ data->tree->search.height -= h_reduction;
+ }
+
+ n->flags ^= TV_NFLAGS_EXPANDED;
return NSERROR_OK;
}
+
+
/**
* Contract a treeview node
*
- * \param tree Treeview object to contract node in
- * \param node Node to contract
+ * \param tree Treeview object to contract node in
+ * \param node Node to contract
* \return NSERROR_OK on success, appropriate error otherwise
*/
-static nserror treeview_node_contract_internal(treeview *tree,
- treeview_node *node)
+static nserror
+treeview_node_contract_internal(treeview *tree, treeview_node *node)
{
struct treeview_contract_data data;
bool selected;
@@ -1640,16 +2282,17 @@ static nserror treeview_node_contract_internal(treeview *tree,
if ((node->flags & TV_NFLAGS_EXPANDED) == false) {
/* What madness is this? */
- LOG("Tried to contract a contracted node.");
+ NSLOG(netsurf, INFO, "Tried to contract a contracted node.");
return NSERROR_OK;
}
+ data.tree = tree;
data.only_entries = false;
selected = node->flags & TV_NFLAGS_SELECTED;
/* Contract children. */
- treeview_walk_internal(node, false, treeview_node_contract_cb,
- NULL, &data);
+ treeview_walk_internal(tree, node, TREEVIEW_WALK_MODE_LOGICAL_EXPANDED,
+ treeview_node_contract_cb, NULL, &data);
/* Contract node */
treeview_node_contract_cb(node, &data, false);
@@ -1658,7 +2301,7 @@ static nserror treeview_node_contract_internal(treeview *tree,
node->flags |= TV_NFLAGS_SELECTED;
/* Inform front end of change in dimensions */
- treeview__cw_update_size(tree, -1, tree->root->height);
+ treeview__cw_update_size(tree, -1, treeview__get_display_height(tree));
return NSERROR_OK;
}
@@ -1667,30 +2310,27 @@ static nserror treeview_node_contract_internal(treeview *tree,
/* Exported interface, documented in treeview.h */
nserror treeview_node_contract(treeview *tree, treeview_node *node)
{
- nserror err;
- struct rect r;
+ nserror res;
assert(tree != NULL);
- r.x0 = 0;
- r.y0 = treeview_node_y(tree, node);
- r.x1 = REDRAW_MAX;
- r.y1 = tree->root->height;
-
- err = treeview_node_contract_internal(tree, node);
- if (err != NSERROR_OK)
- return err;
-
- /* Redraw */
- treeview__cw_redraw_request(tree, &r);
+ res = treeview_node_contract_internal(tree, node);
+ NSLOG(netsurf, INFO, "Contracting!");
+ if (res == NSERROR_OK) {
+ /* successful contraction, request redraw */
+ treeview__redraw_from_node(tree, node);
+ NSLOG(netsurf, INFO, "Contracted!");
+ }
- return NSERROR_OK;
+ return res;
}
/* Exported interface, documented in treeview.h */
nserror treeview_contract(treeview *tree, bool all)
{
+ int search_height = (tree->flags & TREEVIEW_SEARCHABLE) ?
+ tree_g.line_height : 0;
struct treeview_contract_data data;
bool selected;
treeview_node *n;
@@ -1702,8 +2342,9 @@ nserror treeview_contract(treeview *tree, bool all)
r.x0 = 0;
r.y0 = 0;
r.x1 = REDRAW_MAX;
- r.y1 = tree->root->height;
+ r.y1 = tree->root->height + search_height;
+ data.tree = tree;
data.only_entries = !all;
for (n = tree->root->children; n != NULL; n = n->next_sib) {
@@ -1714,7 +2355,8 @@ nserror treeview_contract(treeview *tree, bool all)
selected = n->flags & TV_NFLAGS_SELECTED;
/* Contract children. */
- treeview_walk_internal(n, false,
+ treeview_walk_internal(tree, n,
+ TREEVIEW_WALK_MODE_LOGICAL_EXPANDED,
treeview_node_contract_cb, NULL, &data);
/* Contract node */
@@ -1728,19 +2370,35 @@ nserror treeview_contract(treeview *tree, bool all)
treeview__cw_update_size(tree, -1, tree->root->height);
/* Redraw */
- treeview__cw_redraw_request(tree, &r);
+ treeview__cw_invalidate_area(tree, &r);
return NSERROR_OK;
}
+/**
+ * context data for treeview expansion
+ */
struct treeview_expand_data {
treeview *tree;
bool only_folders;
};
-/** Treewalk node callback for handling recursive node expansion. */
-static nserror treeview_expand_cb(treeview_node *n, void *ctx,
- bool *skip_children, bool *end)
+
+
+/**
+ * Treewalk node callback for handling recursive node expansion.
+ *
+ * \param n current node
+ * \param ctx node expansion context
+ * \param skip_children flag to allow children to be skipped
+ * \param end flag to allow iteration to be finished early.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+treeview_expand_cb(treeview_node *n,
+ void *ctx,
+ bool *skip_children,
+ bool *end)
{
struct treeview_expand_data *data = ctx;
nserror err;
@@ -1749,7 +2407,7 @@ static nserror treeview_expand_cb(treeview_node *n, void *ctx,
assert(n->type != TREE_NODE_ROOT);
if (n->flags & TV_NFLAGS_EXPANDED ||
- (data->only_folders && n->type != TREE_NODE_FOLDER)) {
+ (data->only_folders && n->type != TREE_NODE_FOLDER)) {
/* Nothing to do. */
return NSERROR_OK;
}
@@ -1758,11 +2416,13 @@ static nserror treeview_expand_cb(treeview_node *n, void *ctx,
return err;
}
+
+
/* Exported interface, documented in treeview.h */
nserror treeview_expand(treeview *tree, bool only_folders)
{
struct treeview_expand_data data;
- nserror err;
+ nserror res;
struct rect r;
assert(tree != NULL);
@@ -1771,50 +2431,57 @@ nserror treeview_expand(treeview *tree, bool only_folders)
data.tree = tree;
data.only_folders = only_folders;
- err = treeview_walk_internal(tree->root, true, NULL,
- treeview_expand_cb, &data);
- if (err != NSERROR_OK)
- return err;
-
- r.x0 = 0;
- r.y0 = 0;
- r.x1 = REDRAW_MAX;
- r.y1 = tree->root->height;
+ res = treeview_walk_internal(tree, tree->root,
+ TREEVIEW_WALK_MODE_LOGICAL_COMPLETE,
+ NULL, treeview_expand_cb, &data);
+ if (res == NSERROR_OK) {
+ /* expansion succeeded, schedule redraw */
- /* Redraw */
- treeview__cw_redraw_request(tree, &r);
+ r.x0 = 0;
+ r.y0 = 0;
+ r.x1 = REDRAW_MAX;
+ r.y1 = tree->root->height;
- return NSERROR_OK;
+ treeview__cw_invalidate_area(tree, &r);
+ }
+ return res;
}
-/* Exported interface, documented in treeview.h */
-void treeview_redraw(treeview *tree, const int x, const int y,
- struct rect *clip, const struct redraw_context *ctx)
+/**
+ * Draw a treeview normally, in tree mode.
+ *
+ * \param[in] tree The treeview we're rendering.
+ * \param[in] x X coordinate we're rendering the treeview at.
+ * \param[in] y Y coordinate we're rendering the treeview at.
+ * \param[in,out] render_y Current vertical position in tree, updated on exit.
+ * \param[in] r Clip rectangle.
+ * \param[in] data Redraw data for rendering contents.
+ * \param[in] ctx Current render context.
+ */
+static void treeview_redraw_tree(
+ treeview *tree,
+ const int x,
+ const int y,
+ int *render_y_in_out,
+ struct rect *r,
+ struct content_redraw_data *data,
+ const struct redraw_context *ctx)
{
- struct redraw_context new_ctx = *ctx;
- treeview_node *node, *root, *next;
- struct treeview_node_entry *entry;
struct treeview_node_style *style = &plot_style_odd;
- struct content_redraw_data data;
- struct rect r;
- uint32_t count = 0;
- int render_y = y;
- int inset;
- int x0, y0, y1;
- int baseline = (tree_g.line_height * 3 + 2) / 4;
enum treeview_resource_id res = TREE_RES_CONTENT;
- plot_style_t *bg_style;
- plot_font_style_t *text_style;
+ int baseline = (tree_g.line_height * 3 + 2) / 4;
plot_font_style_t *infotext_style;
- struct bitmap *furniture;
- int height;
+ treeview_node *root = tree->root;
+ treeview_node *node = tree->root;
+ int render_y = *render_y_in_out;
+ plot_font_style_t *text_style;
+ plot_style_t *bg_style;
int sel_min, sel_max;
- bool invert_selection;
-
- assert(tree != NULL);
- assert(tree->root != NULL);
- assert(tree->root->flags & TV_NFLAGS_EXPANDED);
+ uint32_t count = 0;
+ struct rect rect;
+ int inset;
+ int x0;
if (tree->drag.start.y > tree->drag.prev.y) {
sel_min = tree->drag.prev.y;
@@ -1824,31 +2491,16 @@ void treeview_redraw(treeview *tree, const int x, const int y,
sel_max = tree->drag.prev.y;
}
- /* Start knockout rendering if it's available for this plotter */
- if (ctx->plot->option_knockout)
- knockout_plot_start(ctx, &new_ctx);
-
- /* Set up clip rectangle */
- r.x0 = clip->x0 + x;
- r.y0 = clip->y0 + y;
- r.x1 = clip->x1 + x;
- r.y1 = clip->y1 + y;
- new_ctx.plot->clip(&r);
-
- /* Draw the tree */
- node = root = tree->root;
-
- /* Setup common content redraw data */
- data.width = tree_g.icon_size;
- data.height = tree_g.icon_size;
- data.scale = 1;
- data.repeat_x = false;
- data.repeat_y = false;
-
while (node != NULL) {
+ struct treeview_node_entry *entry;
+ struct bitmap *furniture;
+ bool invert_selection;
+ treeview_node *next;
+ int height;
int i;
+
next = (node->flags & TV_NFLAGS_EXPANDED) ?
- node->children : NULL;
+ node->children : NULL;
if (next != NULL) {
/* down to children */
@@ -1859,7 +2511,7 @@ void treeview_redraw(treeview *tree, const int x, const int y,
* with a next sibling. */
while (node != root &&
- node->next_sib == NULL) {
+ node->next_sib == NULL) {
node = node->parent;
}
@@ -1872,14 +2524,14 @@ void treeview_redraw(treeview *tree, const int x, const int y,
assert(node != NULL);
assert(node != root);
assert(node->type == TREE_NODE_FOLDER ||
- node->type == TREE_NODE_ENTRY);
+ node->type == TREE_NODE_ENTRY);
count++;
inset = x + node->inset;
height = (node->type == TREE_NODE_ENTRY) ? node->height :
- tree_g.line_height;
+ tree_g.line_height;
- if ((render_y + height) < r.y0) {
+ if ((render_y + height) < r->y0) {
/* This node's line is above clip region */
render_y += height;
continue;
@@ -1887,70 +2539,77 @@ void treeview_redraw(treeview *tree, const int x, const int y,
style = (count & 0x1) ? &plot_style_odd : &plot_style_even;
if (tree->drag.type == TV_DRAG_SELECTION &&
- (render_y + height >= sel_min &&
- render_y < sel_max)) {
+ (render_y + height >= sel_min &&
+ render_y < sel_max)) {
invert_selection = true;
} else {
invert_selection = false;
}
if ((node->flags & TV_NFLAGS_SELECTED && !invert_selection) ||
- (!(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 & TV_NFLAGS_EXPANDED) ?
- style->furn[TREE_FURN_CONTRACT].sel :
- style->furn[TREE_FURN_EXPAND].sel;
+ 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 & TV_NFLAGS_EXPANDED) ?
- style->furn[TREE_FURN_CONTRACT].bmp :
- style->furn[TREE_FURN_EXPAND].bmp;
+ style->furn[TREE_FURN_CONTRACT].bmp :
+ style->furn[TREE_FURN_EXPAND].bmp;
}
/* Render background */
- y0 = render_y;
- y1 = render_y + height;
- new_ctx.plot->rectangle(r.x0, y0, r.x1, y1, bg_style);
+ rect.x0 = r->x0;
+ rect.y0 = render_y;
+ rect.x1 = r->x1;
+ rect.y1 = render_y + height;
+ ctx->plot->rectangle(ctx, bg_style, &rect);
/* Render toggle */
- new_ctx.plot->bitmap(inset, render_y + tree_g.line_height / 4,
+ ctx->plot->bitmap(ctx,
+ furniture,
+ inset,
+ render_y + tree_g.line_height / 4,
style->furn[TREE_FURN_EXPAND].size,
style->furn[TREE_FURN_EXPAND].size,
- furniture,
- bg_style->fill_colour, BITMAPF_NONE);
+ bg_style->fill_colour,
+ BITMAPF_NONE);
/* Render icon */
- if (node->type == TREE_NODE_ENTRY)
+ if (node->type == TREE_NODE_ENTRY) {
res = TREE_RES_CONTENT;
- else if (node->flags & TV_NFLAGS_SPECIAL)
+ } else if (node->flags & TV_NFLAGS_SPECIAL) {
res = TREE_RES_FOLDER_SPECIAL;
- else
+ } else {
res = TREE_RES_FOLDER;
+ }
if (treeview_res[res].ready) {
/* Icon resource is available */
- data.x = inset + tree_g.step_width;
- data.y = render_y + ((tree_g.line_height -
- treeview_res[res].height + 1) / 2);
- data.background_colour = bg_style->fill_colour;
+ data->x = inset + tree_g.step_width;
+ data->y = render_y + ((tree_g.line_height -
+ treeview_res[res].height + 1) / 2);
+ data->background_colour = bg_style->fill_colour;
- content_redraw(treeview_res[res].c,
- &data, &r, &new_ctx);
+ content_redraw(treeview_res[res].c, data, r, ctx);
}
/* Render text */
x0 = inset + tree_g.step_width + tree_g.icon_step;
- new_ctx.plot->text(x0, render_y + baseline,
- node->text.data, node->text.len,
- text_style);
+ ctx->plot->text(ctx,
+ text_style,
+ x0, render_y + baseline,
+ node->text.data,
+ node->text.len);
/* Rendered the node */
render_y += tree_g.line_height;
- if (render_y > r.y1) {
+ if (render_y > r->y1) {
/* Passed the bottom of what's in the clip region.
* Done. */
break;
@@ -1958,7 +2617,7 @@ void treeview_redraw(treeview *tree, const int x, const int y,
if (node->type != TREE_NODE_ENTRY ||
- !(node->flags & TV_NFLAGS_EXPANDED))
+ !(node->flags & TV_NFLAGS_EXPANDED))
/* Done everything for this node */
continue;
@@ -1970,57 +2629,364 @@ void treeview_redraw(treeview *tree, const int x, const int y,
if (ef->flags & TREE_FLAG_SHOW_NAME) {
int max_width = tree->field_width;
- new_ctx.plot->text(x0 + max_width -
- ef->value.width -
- tree_g.step_width,
+ ctx->plot->text(ctx,
+ infotext_style,
+ x0 + max_width - ef->value.width - tree_g.step_width,
render_y + baseline,
ef->value.data,
- ef->value.len,
- infotext_style);
+ ef->value.len);
- new_ctx.plot->text(x0 + max_width,
+ ctx->plot->text(ctx,
+ infotext_style,
+ x0 + max_width,
render_y + baseline,
entry->fields[i].value.data,
- entry->fields[i].value.len,
- infotext_style);
+ entry->fields[i].value.len);
} else {
- new_ctx.plot->text(x0, render_y + baseline,
+ ctx->plot->text(ctx,
+ infotext_style,
+ x0, render_y + baseline,
entry->fields[i].value.data,
- entry->fields[i].value.len,
- infotext_style);
+ entry->fields[i].value.len);
+ }
+
+ /* Rendered the expanded entry field */
+ render_y += tree_g.line_height;
+ }
+
+ /* Finished rendering expanded entry */
+
+ if (render_y > r->y1) {
+ /* Passed the bottom of what's in the clip region.
+ * Done. */
+ break;
+ }
+ }
+
+ *render_y_in_out = render_y;
+}
+
+
+/**
+ * Draw a treeview normally, in tree mode.
+ *
+ * \param[in] tree The treeview we're rendering.
+ * \param[in] x X coordinate we're rendering the treeview at.
+ * \param[in] y Y coordinate we're rendering the treeview at.
+ * \param[in,out] render_y Current vertical position in tree, updated on exit.
+ * \param[in] r Clip rectangle.
+ * \param[in] data Redraw data for rendering contents.
+ * \param[in] ctx Current render context.
+ */
+static void treeview_redraw_search(
+ treeview *tree,
+ const int x,
+ const int y,
+ int *render_y_in_out,
+ struct rect *r,
+ struct content_redraw_data *data,
+ const struct redraw_context *ctx)
+{
+ struct treeview_node_style *style = &plot_style_odd;
+ enum treeview_resource_id res = TREE_RES_CONTENT;
+ int baseline = (tree_g.line_height * 3 + 2) / 4;
+ plot_font_style_t *infotext_style;
+ treeview_node *root = tree->root;
+ treeview_node *node = tree->root;
+ int render_y = *render_y_in_out;
+ plot_font_style_t *text_style;
+ plot_style_t *bg_style;
+ int sel_min, sel_max;
+ uint32_t count = 0;
+ struct rect rect;
+ int inset;
+ int x0;
+
+ if (tree->drag.start.y > tree->drag.prev.y) {
+ sel_min = tree->drag.prev.y;
+ sel_max = tree->drag.start.y;
+ } else {
+ sel_min = tree->drag.start.y;
+ sel_max = tree->drag.prev.y;
+ }
+
+ while (node != NULL) {
+ struct treeview_node_entry *entry;
+ struct bitmap *furniture;
+ bool invert_selection;
+ treeview_node *next;
+ int height;
+ int i;
+
+ next = node->children;
+
+ if (next != NULL) {
+ /* down to children */
+ node = next;
+ } else {
+ /* No children. As long as we're not at the root,
+ * go to next sibling if present, or nearest ancestor
+ * with a next sibling. */
+
+ while (node != root &&
+ node->next_sib == NULL) {
+ node = node->parent;
+ }
+
+ if (node == root)
+ break;
+
+ node = node->next_sib;
+ }
+
+ assert(node != NULL);
+ assert(node != root);
+ assert(node->type == TREE_NODE_FOLDER ||
+ node->type == TREE_NODE_ENTRY);
+
+ if (node->type == TREE_NODE_FOLDER ||
+ !(node->flags & TV_NFLAGS_MATCHED)) {
+ continue;
+ }
+
+ count++;
+ inset = x + tree_g.window_padding;
+ height = node->height;
+
+ if ((render_y + height) < r->y0) {
+ /* This node's line is above clip region */
+ render_y += height;
+ continue;
+ }
+
+ style = (count & 0x1) ? &plot_style_odd : &plot_style_even;
+ if (tree->drag.type == TV_DRAG_SELECTION &&
+ (render_y + height >= sel_min &&
+ render_y < sel_max)) {
+ invert_selection = true;
+ } else {
+ invert_selection = false;
+ }
+ 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 & 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 & TV_NFLAGS_EXPANDED) ?
+ style->furn[TREE_FURN_CONTRACT].bmp :
+ style->furn[TREE_FURN_EXPAND].bmp;
+ }
+
+ /* Render background */
+ rect.x0 = r->x0;
+ rect.y0 = render_y;
+ rect.x1 = r->x1;
+ rect.y1 = render_y + height;
+ ctx->plot->rectangle(ctx, bg_style, &rect);
+
+ /* Render toggle */
+ ctx->plot->bitmap(ctx,
+ furniture,
+ inset,
+ render_y + tree_g.line_height / 4,
+ style->furn[TREE_FURN_EXPAND].size,
+ style->furn[TREE_FURN_EXPAND].size,
+ bg_style->fill_colour,
+ BITMAPF_NONE);
+
+ /* Render icon */
+ if (node->type == TREE_NODE_ENTRY) {
+ res = TREE_RES_CONTENT;
+ } else if (node->flags & TV_NFLAGS_SPECIAL) {
+ res = TREE_RES_FOLDER_SPECIAL;
+ } else {
+ res = TREE_RES_FOLDER;
+ }
+
+ if (treeview_res[res].ready) {
+ /* Icon resource is available */
+ data->x = inset + tree_g.step_width;
+ data->y = render_y + ((tree_g.line_height -
+ treeview_res[res].height + 1) / 2);
+ data->background_colour = bg_style->fill_colour;
+
+ content_redraw(treeview_res[res].c, data, r, ctx);
+ }
+
+ /* Render text */
+ x0 = inset + tree_g.step_width + tree_g.icon_step;
+ ctx->plot->text(ctx,
+ text_style,
+ x0, render_y + baseline,
+ node->text.data,
+ node->text.len);
+
+ /* Rendered the node */
+ render_y += tree_g.line_height;
+ if (render_y > r->y1) {
+ /* Passed the bottom of what's in the clip region.
+ * Done. */
+ break;
+ }
+
+
+ if (node->type != TREE_NODE_ENTRY ||
+ !(node->flags & TV_NFLAGS_EXPANDED))
+ /* Done everything for this node */
+ continue;
+
+ /* Render expanded entry fields */
+ entry = (struct treeview_node_entry *)node;
+ for (i = 0; i < tree->n_fields - 1; i++) {
+ struct treeview_field *ef = &(tree->fields[i + 1]);
+
+ if (ef->flags & TREE_FLAG_SHOW_NAME) {
+ int max_width = tree->field_width;
+ ctx->plot->text(ctx,
+ infotext_style,
+ x0 + max_width - ef->value.width - tree_g.step_width,
+ render_y + baseline,
+ ef->value.data,
+ ef->value.len);
+
+ ctx->plot->text(ctx,
+ infotext_style,
+ x0 + max_width,
+ render_y + baseline,
+ entry->fields[i].value.data,
+ entry->fields[i].value.len);
+ } else {
+ ctx->plot->text(ctx,
+ infotext_style,
+ x0, render_y + baseline,
+ entry->fields[i].value.data,
+ entry->fields[i].value.len);
}
/* Rendered the expanded entry field */
render_y += tree_g.line_height;
}
- /* Finshed rendering expanded entry */
+ /* Finished rendering expanded entry */
- if (render_y > r.y1) {
+ if (render_y > r->y1) {
/* Passed the bottom of what's in the clip region.
* Done. */
break;
}
}
+ *render_y_in_out = render_y;
+}
+
+
+/* Exported interface, documented in treeview.h */
+void
+treeview_redraw(treeview *tree,
+ const int x,
+ const int y,
+ struct rect *clip,
+ const struct redraw_context *ctx)
+{
+ struct redraw_context new_ctx = *ctx;
+ struct content_redraw_data data;
+ struct rect r;
+ struct rect rect;
+ int render_y = y;
+
+ assert(tree != NULL);
+ assert(tree->root != NULL);
+ assert(tree->root->flags & TV_NFLAGS_EXPANDED);
+
+ /* Start knockout rendering if it's available for this plotter */
+ if (ctx->plot->option_knockout) {
+ knockout_plot_start(ctx, &new_ctx);
+ }
+
+ /* Set up clip rectangle */
+ r.x0 = clip->x0 + x;
+ r.y0 = clip->y0 + y;
+ r.x1 = clip->x1 + x;
+ r.y1 = clip->y1 + y;
+ new_ctx.plot->clip(&new_ctx, &r);
+
+ /* Setup common content redraw data */
+ data.width = tree_g.icon_size;
+ data.height = tree_g.icon_size;
+ data.scale = 1;
+ data.repeat_x = false;
+ data.repeat_y = false;
+
+ if (tree->flags & TREEVIEW_SEARCHABLE) {
+ if (render_y < r.y1) {
+ enum treeview_resource_id icon = TREE_RES_SEARCH;
+
+ /* Fill the blank area at the bottom */
+ rect.x0 = r.x0;
+ rect.y0 = render_y;
+ rect.x1 = r.x1;
+ rect.y1 = render_y + tree_g.line_height;
+ new_ctx.plot->rectangle(&new_ctx, &plot_style_even.bg,
+ &rect);
+
+ if (treeview_res[icon].ready) {
+ /* Icon resource is available */
+ data.x = tree_g.window_padding;
+ data.y = render_y + ((tree_g.line_height -
+ treeview_res[icon].height + 1) /
+ 2);
+ data.background_colour = plot_style_even.bg.
+ fill_colour;
+
+ content_redraw(treeview_res[icon].c,
+ &data, &r, &new_ctx);
+ }
+
+ textarea_redraw(tree->search.textarea,
+ x + tree_g.window_padding +
+ tree_g.icon_step, y,
+ plot_style_even.bg.fill_colour, 1.0,
+ &r, &new_ctx);
+ }
+ render_y += tree_g.line_height;
+ }
+
+ /* Render the treeview data */
+ if (tree->search.search == true) {
+ treeview_redraw_search(tree, x, y,
+ &render_y, &r, &data, &new_ctx);
+ } else {
+ treeview_redraw_tree(tree, x, y,
+ &render_y, &r, &data, &new_ctx);
+ }
+
if (render_y < r.y1) {
/* Fill the blank area at the bottom */
- y0 = render_y;
- new_ctx.plot->rectangle(r.x0, y0, r.x1, r.y1,
- &plot_style_even.bg);
+ rect.x0 = r.x0;
+ rect.y0 = render_y;
+ rect.x1 = r.x1;
+ rect.y1 = r.y1;
+ new_ctx.plot->rectangle(&new_ctx, &plot_style_even.bg, &rect);
}
/* All normal treeview rendering is done; render any overlays */
- if (tree->move.target_pos != TV_TARGET_NONE &&
- treeview_res[TREE_RES_ARROW].ready) {
+ if ((tree->move.target_pos != TV_TARGET_NONE) &&
+ (treeview_res[TREE_RES_ARROW].ready)) {
/* Got a MOVE drag; render move indicator arrow */
data.x = tree->move.target_area.x0 + x;
data.y = tree->move.target_area.y0 + y;
data.background_colour = plot_style_even.bg.fill_colour;
- content_redraw(treeview_res[TREE_RES_ARROW].c,
- &data, &r, &new_ctx);
+ content_redraw(treeview_res[TREE_RES_ARROW].c, &data, &r, &new_ctx);
} else if (tree->edit.textarea != NULL) {
/* Edit in progress; render textarea */
@@ -2031,10 +2997,15 @@ void treeview_redraw(treeview *tree, const int x, const int y,
}
/* Rendering complete */
- if (ctx->plot->option_knockout)
- knockout_plot_end();
+ if (ctx->plot->option_knockout) {
+ knockout_plot_end(ctx);
+ }
}
+
+/**
+ * context for treeview selection
+ */
struct treeview_selection_walk_data {
enum {
TREEVIEW_WALK_HAS_SELECTION,
@@ -2059,6 +3030,7 @@ struct treeview_selection_walk_data {
} drag;
struct {
treeview_node *prev;
+ treeview_node *fixed;
} yank;
struct {
treeview_node *n;
@@ -2071,9 +3043,22 @@ struct treeview_selection_walk_data {
int current_y;
treeview *tree;
};
-/** Treewalk node callback for handling selection related actions. */
-static nserror treeview_node_selection_walk_cb(treeview_node *n,
- void *ctx, bool *skip_children, bool *end)
+
+
+/**
+ * Treewalk node callback for handling selection related actions.
+ *
+ * \param n current node
+ * \param ctx node selection context
+ * \param skip_children flag to allow children to be skipped
+ * \param end flag to allow iteration to be finished early.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+treeview_node_selection_walk_cb(treeview_node *n,
+ void *ctx,
+ bool *skip_children,
+ bool *end)
{
struct treeview_selection_walk_data *sw = ctx;
int height;
@@ -2103,7 +3088,7 @@ static nserror treeview_node_selection_walk_cb(treeview_node *n,
case TREEVIEW_WALK_DELETE_SELECTION:
if (n->flags & TV_NFLAGS_SELECTED) {
err = treeview_delete_node_internal(sw->tree, n, true,
- TREE_OPTION_NONE);
+ TREE_OPTION_NONE);
if (err != NSERROR_OK) {
return err;
}
@@ -2114,8 +3099,8 @@ static nserror treeview_node_selection_walk_cb(treeview_node *n,
case TREEVIEW_WALK_PROPAGATE_SELECTION:
if (n->parent != NULL &&
- n->parent->flags & TV_NFLAGS_SELECTED &&
- !(n->flags & TV_NFLAGS_SELECTED)) {
+ n->parent->flags & TV_NFLAGS_SELECTED &&
+ !(n->flags & TV_NFLAGS_SELECTED)) {
n->flags ^= TV_NFLAGS_SELECTED;
changed = true;
}
@@ -2137,8 +3122,8 @@ static nserror treeview_node_selection_walk_cb(treeview_node *n,
case TREEVIEW_WALK_COMMIT_SELECT_DRAG:
if (sw->current_y >= sw->data.drag.sel_min &&
- sw->current_y - height <
- sw->data.drag.sel_max) {
+ sw->current_y - height <
+ sw->data.drag.sel_max) {
n->flags ^= TV_NFLAGS_SELECTED;
}
return NSERROR_OK;
@@ -2148,6 +3133,10 @@ static nserror treeview_node_selection_walk_cb(treeview_node *n,
treeview_node *p = n->parent;
int h = 0;
+ if (n == sw->data.yank.fixed) {
+ break;
+ }
+
if (treeview_unlink_node(n))
h = n->height;
@@ -2175,7 +3164,7 @@ static nserror treeview_node_selection_walk_cb(treeview_node *n,
case TREEVIEW_WALK_COPY_SELECTION:
if (n->flags & TV_NFLAGS_SELECTED &&
- n->type == TREE_NODE_ENTRY) {
+ n->type == TREE_NODE_ENTRY) {
int i;
char *temp;
uint32_t len;
@@ -2190,12 +3179,12 @@ static nserror treeview_node_selection_walk_cb(treeview_node *n,
continue;
}
val = treeview_get_text_for_field(sw->tree,
- n, i);
+ n, i);
text = val->data;
len = val->len;
temp = realloc(sw->data.copy.text,
- sw->data.copy.len + len + 1);
+ sw->data.copy.len + len + 1);
if (temp == NULL) {
free(sw->data.copy.text);
sw->data.copy.text = NULL;
@@ -2238,7 +3227,8 @@ bool treeview_has_selection(treeview *tree)
sw.purpose = TREEVIEW_WALK_HAS_SELECTION;
sw.data.has_selection = false;
- treeview_walk_internal(tree->root, false, NULL,
+ treeview_walk_internal(tree, tree->root,
+ TREEVIEW_WALK_MODE_DISPLAY, NULL,
treeview_node_selection_walk_cb, &sw);
return sw.data.has_selection;
@@ -2248,7 +3238,7 @@ bool treeview_has_selection(treeview *tree)
/**
* Get first selected node (in any)
*
- * \param tree Treeview object in which to create folder
+ * \param tree Treeview object in which to create folder
* \return the first selected treeview node, or NULL
*/
static treeview_node * treeview_get_first_selected(treeview *tree)
@@ -2258,7 +3248,8 @@ static treeview_node * treeview_get_first_selected(treeview *tree)
sw.purpose = TREEVIEW_WALK_GET_FIRST_SELECTED;
sw.data.first.n = NULL;
- treeview_walk_internal(tree->root, false, NULL,
+ treeview_walk_internal(tree, tree->root,
+ TREEVIEW_WALK_MODE_DISPLAY, NULL,
treeview_node_selection_walk_cb, &sw);
return sw.data.first.n;
@@ -2267,7 +3258,7 @@ static treeview_node * treeview_get_first_selected(treeview *tree)
/* Exported interface, documented in treeview.h */
enum treeview_node_type treeview_get_selection(treeview *tree,
- void **node_data)
+ void **node_data)
{
treeview_node *n;
@@ -2288,8 +3279,8 @@ enum treeview_node_type treeview_get_selection(treeview *tree,
/**
* Clear any selection in a treeview
*
- * \param tree Treeview object to clear selection in
- * \param rect Redraw rectangle (if redraw required)
+ * \param tree Treeview object to clear selection in
+ * \param rect Redraw rectangle (if redraw required)
* \return true iff redraw required
*/
static bool treeview_clear_selection(treeview *tree, struct rect *rect)
@@ -2304,9 +3295,11 @@ static bool treeview_clear_selection(treeview *tree, struct rect *rect)
sw.purpose = TREEVIEW_WALK_CLEAR_SELECTION;
sw.data.redraw.required = false;
sw.data.redraw.rect = rect;
- sw.current_y = 0;
+ sw.current_y = (tree->flags & TREEVIEW_SEARCHABLE) ?
+ tree_g.line_height : 0;
- treeview_walk_internal(tree->root, false, NULL,
+ treeview_walk_internal(tree, tree->root,
+ TREEVIEW_WALK_MODE_DISPLAY, NULL,
treeview_node_selection_walk_cb, &sw);
return sw.data.redraw.required;
@@ -2316,8 +3309,8 @@ static bool treeview_clear_selection(treeview *tree, struct rect *rect)
/**
* Select all in a treeview
*
- * \param tree Treeview object to select all in
- * \param rect Redraw rectangle (if redraw required)
+ * \param tree Treeview object to select all in
+ * \param rect Redraw rectangle (if redraw required)
* \return true iff redraw required
*/
static bool treeview_select_all(treeview *tree, struct rect *rect)
@@ -2332,9 +3325,11 @@ static bool treeview_select_all(treeview *tree, struct rect *rect)
sw.purpose = TREEVIEW_WALK_SELECT_ALL;
sw.data.redraw.required = false;
sw.data.redraw.rect = rect;
- sw.current_y = 0;
+ sw.current_y = (tree->flags & TREEVIEW_SEARCHABLE) ?
+ tree_g.line_height : 0;
- treeview_walk_internal(tree->root, false, NULL,
+ treeview_walk_internal(tree, tree->root,
+ TREEVIEW_WALK_MODE_DISPLAY, NULL,
treeview_node_selection_walk_cb, &sw);
return sw.data.redraw.required;
@@ -2344,14 +3339,15 @@ static bool treeview_select_all(treeview *tree, struct rect *rect)
/**
* Commit a current selection drag, modifying the node's selection state.
*
- * \param tree Treeview object to commit drag selection in
+ * \param tree Treeview object to commit drag selection in
*/
static void treeview_commit_selection_drag(treeview *tree)
{
struct treeview_selection_walk_data sw;
sw.purpose = TREEVIEW_WALK_COMMIT_SELECT_DRAG;
- sw.current_y = 0;
+ sw.current_y = (tree->flags & TREEVIEW_SEARCHABLE) ?
+ tree_g.line_height : 0;
if (tree->drag.start.y > tree->drag.prev.y) {
sw.data.drag.sel_min = tree->drag.prev.y;
@@ -2361,7 +3357,8 @@ static void treeview_commit_selection_drag(treeview *tree)
sw.data.drag.sel_max = tree->drag.prev.y;
}
- treeview_walk_internal(tree->root, false, NULL,
+ treeview_walk_internal(tree, tree->root,
+ TREEVIEW_WALK_MODE_DISPLAY, NULL,
treeview_node_selection_walk_cb, &sw);
}
@@ -2369,17 +3366,20 @@ static void treeview_commit_selection_drag(treeview *tree)
/**
* Yank a selection to the node move list.
*
- * \param tree Treeview object to yank selection from
+ * \param tree Treeview object to yank selection from
+ * \param fixed Treeview node that should not be yanked
*/
-static void treeview_move_yank_selection(treeview *tree)
+static void treeview_move_yank_selection(treeview *tree, treeview_node *fixed)
{
struct treeview_selection_walk_data sw;
sw.purpose = TREEVIEW_WALK_YANK_SELECTION;
+ sw.data.yank.fixed = fixed;
sw.data.yank.prev = NULL;
sw.tree = tree;
- treeview_walk_internal(tree->root, false, NULL,
+ treeview_walk_internal(tree, tree->root,
+ TREEVIEW_WALK_MODE_DISPLAY, NULL,
treeview_node_selection_walk_cb, &sw);
}
@@ -2387,7 +3387,7 @@ static void treeview_move_yank_selection(treeview *tree)
/**
* Copy a selection to the clipboard.
*
- * \param tree Treeview object to yank selection from
+ * \param tree Treeview object to yank selection from
*/
static void treeview_copy_selection(treeview *tree)
{
@@ -2399,7 +3399,8 @@ static void treeview_copy_selection(treeview *tree)
sw.data.copy.len = 0;
sw.tree = tree;
- err = treeview_walk_internal(tree->root, false, NULL,
+ err = treeview_walk_internal(tree, tree->root,
+ TREEVIEW_WALK_MODE_DISPLAY, NULL,
treeview_node_selection_walk_cb, &sw);
if (err != NSERROR_OK) {
return;
@@ -2407,7 +3408,7 @@ static void treeview_copy_selection(treeview *tree)
if (sw.data.copy.text != NULL) {
guit->clipboard->set(sw.data.copy.text,
- sw.data.copy.len - 1, NULL, 0);
+ sw.data.copy.len - 1, NULL, 0);
free(sw.data.copy.text);
}
}
@@ -2416,8 +3417,8 @@ static void treeview_copy_selection(treeview *tree)
/**
* Delete a selection.
*
- * \param tree Treeview object to delete selected nodes from
- * \param rect Updated to redraw rectangle
+ * \param tree Treeview object to delete selected nodes from
+ * \param rect Updated to redraw rectangle
* \return true iff redraw required.
*/
static bool treeview_delete_selection(treeview *tree, struct rect *rect)
@@ -2438,7 +3439,8 @@ static bool treeview_delete_selection(treeview *tree, struct rect *rect)
sw.current_y = 0;
sw.tree = tree;
- treeview_walk_internal(tree->root, false, NULL,
+ treeview_walk_internal(tree, tree->root,
+ TREEVIEW_WALK_MODE_DISPLAY, NULL,
treeview_node_selection_walk_cb, &sw);
return sw.data.redraw.required;
@@ -2448,8 +3450,8 @@ static bool treeview_delete_selection(treeview *tree, struct rect *rect)
/**
* Propagate selection to visible descendants of selected nodes.
*
- * \param tree Treeview object to propagate selection in
- * \param rect Redraw rectangle (if redraw required)
+ * \param tree Treeview object to propagate selection in
+ * \param rect Redraw rectangle (if redraw required)
* \return true iff redraw required
*/
static bool treeview_propagate_selection(treeview *tree, struct rect *rect)
@@ -2470,7 +3472,8 @@ static bool treeview_propagate_selection(treeview *tree, struct rect *rect)
sw.current_y = 0;
sw.tree = tree;
- treeview_walk_internal(tree->root, false, NULL,
+ treeview_walk_internal(tree, tree->root,
+ TREEVIEW_WALK_MODE_DISPLAY, NULL,
treeview_node_selection_walk_cb, &sw);
return sw.data.redraw.required;
@@ -2480,8 +3483,9 @@ static bool treeview_propagate_selection(treeview *tree, struct rect *rect)
/**
* Move a selection according to the current move drag.
*
- * \param tree Treeview object to move selected nodes in
- * \param rect Redraw rectangle
+ * \param tree Treeview object to move selected nodes in
+ * \param rect Redraw rectangle
+ * \return NSERROR_OK on success else appropriate error code
*/
static nserror treeview_move_selection(treeview *tree, struct rect *rect)
{
@@ -2534,7 +3538,7 @@ static nserror treeview_move_selection(treeview *tree, struct rect *rect)
break;
default:
- LOG("Bad drop target for move.");
+ NSLOG(netsurf, INFO, "Bad drop target for move.");
return NSERROR_BAD_PARAMETER;
}
@@ -2544,23 +3548,24 @@ static nserror treeview_move_selection(treeview *tree, struct rect *rect)
parent = relation->parent;
}
- /* The node that we're moving selection to can't itself be selected */
- assert(!(relation->flags & TV_NFLAGS_SELECTED));
-
/* Move all selected nodes from treeview to tree->move.root */
- treeview_move_yank_selection(tree);
+ treeview_move_yank_selection(tree, relation);
/* Move all nodes on tree->move.root to target location */
for (node = tree->move.root; node != NULL; node = next) {
next = node->next_sib;
+ if (node == relation) {
+ continue;
+ }
+
if (!(parent->flags & TV_NFLAGS_EXPANDED)) {
if (node->flags & TV_NFLAGS_EXPANDED)
treeview_node_contract_internal(tree, node);
node->flags &= ~TV_NFLAGS_SELECTED;
}
- treeview_insert_node(node, relation, relationship);
+ treeview_insert_node(tree, node, relation, relationship);
relation = node;
relationship = TREE_REL_NEXT_SIBLING;
@@ -2581,13 +3586,20 @@ static nserror treeview_move_selection(treeview *tree, struct rect *rect)
}
+/**
+ * context for treeview launch action
+ */
struct treeview_launch_walk_data {
int selected_depth;
treeview *tree;
};
-/** Treewalk node walk backward callback for tracking folder selection. */
-static nserror treeview_node_launch_walk_bwd_cb(treeview_node *n, void *ctx,
- bool *end)
+
+
+/**
+ * Treewalk node walk backward callback for tracking folder selection.
+ */
+static nserror
+treeview_node_launch_walk_bwd_cb(treeview_node *n, void *ctx, bool *end)
{
struct treeview_launch_walk_data *lw = ctx;
@@ -2597,9 +3609,22 @@ static nserror treeview_node_launch_walk_bwd_cb(treeview_node *n, void *ctx,
return NSERROR_OK;
}
-/** Treewalk node walk forward callback for launching nodes. */
-static nserror treeview_node_launch_walk_fwd_cb(treeview_node *n, void *ctx,
- bool *skip_children, bool *end)
+
+
+/**
+ * Treewalk node walk forward callback for launching nodes.
+ *
+ * \param n current node
+ * \param ctx node launch context
+ * \param skip_children flag to allow children to be skipped
+ * \param end flag to allow iteration to be finished early.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+treeview_node_launch_walk_fwd_cb(treeview_node *n,
+ void *ctx,
+ bool *skip_children,
+ bool *end)
{
struct treeview_launch_walk_data *lw = ctx;
nserror ret = NSERROR_OK;
@@ -2608,8 +3633,8 @@ static nserror treeview_node_launch_walk_fwd_cb(treeview_node *n, void *ctx,
lw->selected_depth++;
} else if (n->type == TREE_NODE_ENTRY &&
- (n->flags & TV_NFLAGS_SELECTED ||
- lw->selected_depth > 0)) {
+ (n->flags & TV_NFLAGS_SELECTED ||
+ lw->selected_depth > 0)) {
struct treeview_node_msg msg;
msg.msg = TREE_MSG_NODE_LAUNCH;
msg.data.node_launch.mouse = BROWSER_MOUSE_HOVER;
@@ -2618,14 +3643,16 @@ static nserror treeview_node_launch_walk_fwd_cb(treeview_node *n, void *ctx,
return ret;
}
+
+
/**
* Launch a selection.
*
- * \param tree Treeview object to launch selected nodes in
- * \return NSERROR_OK on success, appropriate error otherwise
+ * \note Selected entries are launched. Entries that are descendants
+ * of selected folders are also launched.
*
- * Note: Selected entries are launched.
- * Entries that are descendants of selected folders are also launched.
+ * \param tree Treeview object to launch selected nodes in
+ * \return NSERROR_OK on success, appropriate error otherwise
*/
static nserror treeview_launch_selection(treeview *tree)
{
@@ -2637,15 +3664,20 @@ static nserror treeview_launch_selection(treeview *tree)
lw.selected_depth = 0;
lw.tree = tree;
- return treeview_walk_internal(tree->root, true,
+ return treeview_walk_internal(tree, tree->root,
+ TREEVIEW_WALK_MODE_LOGICAL_COMPLETE,
treeview_node_launch_walk_bwd_cb,
treeview_node_launch_walk_fwd_cb, &lw);
}
/* Exported interface, documented in treeview.h */
-nserror treeview_get_relation(treeview *tree, treeview_node **relation,
- enum treeview_relationship *rel, bool at_y, int y)
+nserror
+treeview_get_relation(treeview *tree,
+ treeview_node **relation,
+ enum treeview_relationship *rel,
+ bool at_y,
+ int y)
{
treeview_node *n;
@@ -2687,6 +3719,9 @@ nserror treeview_get_relation(treeview *tree, treeview_node **relation,
}
+/**
+ * context for treeview keyboard action
+ */
struct treeview_nav_state {
treeview *tree;
treeview_node *prev;
@@ -2696,9 +3731,22 @@ struct treeview_nav_state {
int n_selected;
int prev_n_selected;
};
-/** Treewalk node callback for handling mouse action. */
-static nserror treeview_node_nav_cb(treeview_node *node, void *ctx,
- bool *skip_children, bool *end)
+
+
+/**
+ * Treewalk node callback for handling mouse action.
+ *
+ * \param node current node
+ * \param ctx node context
+ * \param skip_children flag to allow children to be skipped
+ * \param end flag to allow iteration to be finished early.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+treeview_node_nav_cb(treeview_node *node,
+ void *ctx,
+ bool *skip_children,
+ bool *end)
{
struct treeview_nav_state *ns = ctx;
@@ -2724,19 +3772,21 @@ static nserror treeview_node_nav_cb(treeview_node *node, void *ctx,
return NSERROR_OK;
}
+
+
/**
* Handle keyboard navigation.
*
- * \param tree Treeview object to launch selected nodes in
- * \param key The ucs4 character codepoint
- * \param rect Updated to redraw rectangle
- * \return true if treeview needs redraw, false otherwise
- *
- * Note: Selected entries are launched.
+ * \note Selected entries are launched.
* Entries that are descendants of selected folders are also launched.
+ *
+ * \param tree Treeview object to launch selected nodes in
+ * \param key The ucs4 character codepoint
+ * \param rect Updated to redraw rectangle
+ * \return true if treeview needs redraw, false otherwise
*/
-static bool treeview_keyboard_navigation(treeview *tree, uint32_t key,
- struct rect *rect)
+static bool
+treeview_keyboard_navigation(treeview *tree, uint32_t key, struct rect *rect)
{
struct treeview_nav_state ns = {
.tree = tree,
@@ -2747,26 +3797,35 @@ static bool treeview_keyboard_navigation(treeview *tree, uint32_t key,
.n_selected = 0,
.prev_n_selected = 0
};
- int h = tree->root->height;
+ int search_height = (tree->flags & TREEVIEW_SEARCHABLE) ?
+ tree_g.line_height : 0;
+ int h = treeview__get_display_height(tree) + search_height;
bool redraw = false;
/* Fill out the nav. state struct, by examining the current selection
* state */
- treeview_walk_internal(tree->root, false, NULL,
+ treeview_walk_internal(tree, tree->root,
+ TREEVIEW_WALK_MODE_DISPLAY, NULL,
treeview_node_nav_cb, &ns);
- if (ns.next == NULL)
- ns.next = tree->root->children;
- if (ns.prev == NULL)
- ns.prev = ns.last;
+
+ if (tree->search.search == false) {
+ if (ns.next == NULL)
+ ns.next = tree->root->children;
+ if (ns.prev == NULL)
+ ns.prev = ns.last;
+ }
/* Clear any existing selection */
redraw = treeview_clear_selection(tree, rect);
switch (key) {
case NS_KEY_LEFT:
+ if (tree->search.search == true) {
+ break;
+ }
if (ns.curr != NULL &&
- ns.curr->parent != NULL &&
- ns.curr->parent->type != TREE_NODE_ROOT) {
+ ns.curr->parent != NULL &&
+ ns.curr->parent->type != TREE_NODE_ROOT) {
/* Step to parent */
ns.curr->parent->flags |= TV_NFLAGS_SELECTED;
@@ -2784,7 +3843,7 @@ static bool treeview_keyboard_navigation(treeview *tree, uint32_t key,
if (ns.curr->children != NULL) {
/* Step to first child */
ns.curr->children->flags |=
- TV_NFLAGS_SELECTED;
+ TV_NFLAGS_SELECTED;
} else {
/* Retain current node selection */
ns.curr->flags |= TV_NFLAGS_SELECTED;
@@ -2824,8 +3883,8 @@ static bool treeview_keyboard_navigation(treeview *tree, uint32_t key,
rect->x0 = 0;
rect->y0 = 0;
rect->x1 = REDRAW_MAX;
- if (tree->root->height > h)
- rect->y1 = tree->root->height;
+ if (treeview__get_display_height(tree) + search_height > h)
+ rect->y1 = treeview__get_display_height(tree) + search_height;
else
rect->y1 = h;
redraw = true;
@@ -2842,7 +3901,7 @@ bool treeview_keypress(treeview *tree, uint32_t key)
assert(tree != NULL);
- /* Pass to textarea, if editing in progress */
+ /* Pass to any textarea, if editing in progress */
if (tree->edit.textarea != NULL) {
switch (key) {
case NS_KEY_ESCAPE:
@@ -2855,6 +3914,17 @@ bool treeview_keypress(treeview *tree, uint32_t key)
default:
return textarea_keypress(tree->edit.textarea, key);
}
+ } else if (tree->search.active == true) {
+ switch (key) {
+ case NS_KEY_ESCAPE:
+ treeview__search_cancel(tree, false);
+ return true;
+ case NS_KEY_NL:
+ case NS_KEY_CR:
+ return true;
+ default:
+ return textarea_keypress(tree->search.textarea, key);
+ }
}
/* Keypress to be handled by treeview */
@@ -2878,7 +3948,7 @@ bool treeview_keypress(treeview *tree, uint32_t key)
if (tree->root->height != h) {
r.y0 = 0;
treeview__cw_update_size(tree, -1,
- tree->root->height);
+ tree->root->height);
}
}
break;
@@ -2901,7 +3971,7 @@ bool treeview_keypress(treeview *tree, uint32_t key)
}
if (redraw) {
- treeview__cw_redraw_request(tree, &r);
+ treeview__cw_invalidate_area(tree, &r);
}
return true;
@@ -2920,9 +3990,14 @@ bool treeview_keypress(treeview *tree, uint32_t key)
* \param rect Redraw rectangle (if redraw required)
* \return true iff redraw required
*/
-static bool treeview_set_move_indicator(treeview *tree, bool need_redraw,
- treeview_node *target, int node_height,
- int node_y, int mouse_y, struct rect *rect)
+static bool
+treeview_set_move_indicator(treeview *tree,
+ bool need_redraw,
+ treeview_node *target,
+ int node_height,
+ int node_y,
+ int mouse_y,
+ struct rect *rect)
{
treeview_node *orig = target;
enum treeview_target_pos target_pos;
@@ -2937,44 +4012,44 @@ static bool treeview_set_move_indicator(treeview *tree, bool need_redraw,
if (target->flags & TV_NFLAGS_SELECTED) {
/* Find top selected ancestor */
while (target->parent &&
- target->parent->flags & TV_NFLAGS_SELECTED) {
+ target->parent->flags & TV_NFLAGS_SELECTED) {
target = target->parent;
}
- /* Find top ajdacent selected sibling */
+ /* Find top adjacent selected sibling */
while (target->prev_sib &&
- target->prev_sib->flags & TV_NFLAGS_SELECTED) {
+ target->prev_sib->flags & TV_NFLAGS_SELECTED) {
target = target->prev_sib;
}
target_pos = TV_TARGET_ABOVE;
} else switch (target->type) {
- case TREE_NODE_FOLDER:
- if (mouse_pos <= node_height / 4) {
- target_pos = TV_TARGET_ABOVE;
- } else if (mouse_pos <= (3 * node_height) / 4 ||
- target->flags & TV_NFLAGS_EXPANDED) {
- target_pos = TV_TARGET_INSIDE;
- } else {
- target_pos = TV_TARGET_BELOW;
- }
- break;
+ case TREE_NODE_FOLDER:
+ if (mouse_pos <= node_height / 4) {
+ target_pos = TV_TARGET_ABOVE;
+ } else if (mouse_pos <= (3 * node_height) / 4 ||
+ target->flags & TV_NFLAGS_EXPANDED) {
+ target_pos = TV_TARGET_INSIDE;
+ } else {
+ target_pos = TV_TARGET_BELOW;
+ }
+ break;
- case TREE_NODE_ENTRY:
- if (mouse_pos <= node_height / 2) {
- target_pos = TV_TARGET_ABOVE;
- } else {
- target_pos = TV_TARGET_BELOW;
- }
- break;
+ case TREE_NODE_ENTRY:
+ if (mouse_pos <= node_height / 2) {
+ target_pos = TV_TARGET_ABOVE;
+ } else {
+ target_pos = TV_TARGET_BELOW;
+ }
+ break;
- default:
- assert(target->type != TREE_NODE_ROOT);
- return false;
- }
+ default:
+ assert(target->type != TREE_NODE_ROOT);
+ return false;
+ }
if (target_pos == tree->move.target_pos &&
- target == tree->move.target) {
+ target == tree->move.target) {
/* No change */
return need_redraw;
}
@@ -3008,7 +4083,7 @@ static bool treeview_set_move_indicator(treeview *tree, bool need_redraw,
/* Oftsets are all relative to centred (INSIDE) */
node_y += (tree_g.line_height -
- treeview_res[TREE_RES_ARROW].height + 1) / 2;
+ treeview_res[TREE_RES_ARROW].height + 1) / 2;
x = target->inset + tree_g.move_offset;
@@ -3043,6 +4118,9 @@ static bool treeview_set_move_indicator(treeview *tree, bool need_redraw,
/**
* Callback for textarea_create, in desktop/treeview.h
+ *
+ * \param data treeview context
+ * \param msg textarea message
*/
static void treeview_textarea_callback(void *data, struct textarea_msg *msg)
{
@@ -3069,7 +4147,7 @@ static void treeview_textarea_callback(void *data, struct textarea_msg *msg)
r->y1 += tree->edit.y;
/* Redraw the textarea */
- treeview__cw_redraw_request(tree, r);
+ treeview__cw_invalidate_area(tree, r);
break;
default:
@@ -3081,16 +4159,21 @@ static void treeview_textarea_callback(void *data, struct textarea_msg *msg)
/**
* Start edit of node field, at given y-coord, if editable
*
- * \param tree Treeview object to consider editing in
- * \param n The treeview node to try editing
- * \param node_y The Y coord of the top of n
- * \param mouse_x X coord of mouse position
- * \param mouse_y Y coord of mouse position
- * \param rect Redraw rectangle (if redraw required)
+ * \param tree Treeview object to consider editing in
+ * \param n The treeview node to try editing
+ * \param node_y The Y coord of the top of n
+ * \param mouse_x X coord of mouse position
+ * \param mouse_y Y coord of mouse position
+ * \param rect Redraw rectangle (if redraw required)
* \return true iff redraw required
*/
-static bool treeview_edit_node_at_point(treeview *tree, treeview_node *n,
- int node_y, int mouse_x, int mouse_y, struct rect *rect)
+static bool
+treeview_edit_node_at_point(treeview *tree,
+ treeview_node *n,
+ int node_y,
+ int mouse_x,
+ int mouse_y,
+ struct rect *rect)
{
struct treeview_text *field_data = NULL;
struct treeview_field *ef, *field_desc = NULL;
@@ -3098,8 +4181,6 @@ static bool treeview_edit_node_at_point(treeview *tree, treeview_node *n,
int field_y = node_y;
int field_x;
int width, height;
- textarea_setup ta_setup;
- textarea_flags ta_flags;
bool success;
/* If the main field is editable, make field_data point to it */
@@ -3125,7 +4206,7 @@ static bool treeview_edit_node_at_point(treeview *tree, treeview_node *n,
ef = &(tree->fields[i + 1]);
pos += tree_g.line_height;
if (mouse_y <= pos && (ef->flags &
- TREE_FLAG_ALLOW_EDIT)) {
+ TREE_FLAG_ALLOW_EDIT)) {
field_data = &e->fields[i].value;
field_desc = ef;
field_y = pos - tree_g.line_height;
@@ -3141,31 +4222,15 @@ static bool treeview_edit_node_at_point(treeview *tree, treeview_node *n,
/* Get window width/height */
treeview__cw_get_window_dimensions(tree, &width, &height);
- /* Anow textarea width/height */
+ /* Calculate textarea width/height */
field_x = n->inset + tree_g.step_width + tree_g.icon_step - 3;
width -= field_x;
height = tree_g.line_height;
- /* Configure the textarea */
- ta_flags = TEXTAREA_INTERNAL_CARET;
-
- ta_setup.width = width;
- ta_setup.height = height;
- ta_setup.pad_top = 0;
- ta_setup.pad_right = 2;
- ta_setup.pad_bottom = 0;
- ta_setup.pad_left = 2;
- ta_setup.border_width = 1;
- ta_setup.border_col = 0x000000;
- ta_setup.selected_text = 0xffffff;
- ta_setup.selected_bg = 0x000000;
- ta_setup.text = plot_style_odd.text;
- ta_setup.text.foreground = 0x000000;
- ta_setup.text.background = 0xffffff;
-
/* Create text area */
- tree->edit.textarea = textarea_create(ta_flags, &ta_setup,
- treeview_textarea_callback, tree);
+ tree->edit.textarea = treeview__create_textarea(tree, width, height,
+ 0x000000, 0xffffff, 0x000000, plot_style_odd.text,
+ treeview_textarea_callback);
if (tree->edit.textarea == NULL) {
return false;
}
@@ -3187,8 +4252,8 @@ static bool treeview_edit_node_at_point(treeview *tree, treeview_node *n,
mouse_x = width - 1;
textarea_mouse_action(tree->edit.textarea,
- BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_CLICK_1,
- mouse_x, tree_g.line_height / 2);
+ BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_CLICK_1,
+ mouse_x, tree_g.line_height / 2);
/* Position the textarea */
tree->edit.x = field_x;
@@ -3232,7 +4297,7 @@ void treeview_edit_selection(treeview *tree)
/* Edit node at y */
redraw = treeview_edit_node_at_point(tree, n, y,
- 0, y + tree_g.line_height / 2, &rect);
+ 0, y + tree_g.line_height / 2, &rect);
if (redraw == false)
return;
@@ -3242,20 +4307,37 @@ void treeview_edit_selection(treeview *tree)
rect.y0 = y;
rect.x1 = REDRAW_MAX;
rect.y1 = y + tree_g.line_height;
- treeview__cw_redraw_request(tree, &rect);
+ treeview__cw_invalidate_area(tree, &rect);
}
+/**
+ * context for treeview mouse handling
+ */
struct treeview_mouse_action {
treeview *tree;
browser_mouse_state mouse;
int x;
int y;
int current_y; /* Y coordinate value of top of current node */
+ int search_height;
};
-/** Treewalk node callback for handling mouse action. */
-static nserror treeview_node_mouse_action_cb(treeview_node *node, void *ctx,
- bool *skip_children, bool *end)
+
+
+/**
+ * Treewalk node callback for handling mouse action.
+ *
+ * \param node current node
+ * \param ctx node context
+ * \param skip_children flag to allow children to be skipped
+ * \param end flag to allow iteration to be finished early.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+treeview_node_mouse_action_cb(treeview_node *node,
+ void *ctx,
+ bool *skip_children,
+ bool *end)
{
struct treeview_mouse_action *ma = ctx;
struct rect r;
@@ -3273,7 +4355,7 @@ static nserror treeview_node_mouse_action_cb(treeview_node *node, void *ctx,
r.x1 = REDRAW_MAX;
height = (node->type == TREE_NODE_ENTRY) ? node->height :
- tree_g.line_height;
+ tree_g.line_height;
/* Skip line if we've not reached mouse y */
if (ma->y > ma->current_y + height) {
@@ -3283,25 +4365,29 @@ static nserror treeview_node_mouse_action_cb(treeview_node *node, void *ctx,
/* Find where the mouse is */
if (ma->y <= ma->current_y + tree_g.line_height) {
- if (ma->x >= node->inset - 1 &&
- ma->x < node->inset + tree_g.step_width) {
+ int inset = node->inset;
+ if (ma->tree->search.search == true) {
+ inset = tree_g.window_padding;
+ }
+ if (ma->x >= inset - 1 &&
+ ma->x < inset + tree_g.step_width) {
/* Over expansion toggle */
part = TV_NODE_PART_TOGGLE;
- } else if (ma->x >= node->inset + tree_g.step_width &&
- ma->x < node->inset + tree_g.step_width +
+ } else if (ma->x >= inset + tree_g.step_width &&
+ ma->x < inset + tree_g.step_width +
tree_g.icon_step + node->text.width) {
/* On node */
part = TV_NODE_PART_ON_NODE;
}
} else if (node->type == TREE_NODE_ENTRY &&
- height > tree_g.line_height) {
+ height > tree_g.line_height) {
/* Expanded entries */
int x = node->inset + tree_g.step_width + tree_g.icon_step;
int y = ma->current_y + tree_g.line_height;
int i;
struct treeview_node_entry *entry =
- (struct treeview_node_entry *)node;
+ (struct treeview_node_entry *)node;
for (i = 0; i < ma->tree->n_fields - 1; i++) {
struct treeview_field *ef = &(ma->tree->fields[i + 1]);
@@ -3314,21 +4400,21 @@ static nserror treeview_node_mouse_action_cb(treeview_node *node, void *ctx,
int max_width = ma->tree->field_width;
if (ma->x >= x + max_width - ef->value.width -
- tree_g.step_width &&
- ma->x < x + max_width -
- tree_g.step_width) {
+ tree_g.step_width &&
+ ma->x < x + max_width -
+ tree_g.step_width) {
/* On a field name */
part = TV_NODE_PART_ON_NODE;
} else if (ma->x >= x + max_width &&
- ma->x < x + max_width +
- entry->fields[i].value.width) {
+ ma->x < x + max_width +
+ entry->fields[i].value.width) {
/* On a field value */
part = TV_NODE_PART_ON_NODE;
}
} else {
if (ma->x >= x && ma->x < x +
- entry->fields[i].value.width) {
+ entry->fields[i].value.width) {
/* On a field value */
part = TV_NODE_PART_ON_NODE;
}
@@ -3340,7 +4426,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.type == TV_DRAG_NONE) {
ma->tree->drag.selected = node->flags & TV_NFLAGS_SELECTED;
ma->tree->drag.start_node = node;
ma->tree->drag.part = part;
@@ -3358,29 +4444,30 @@ static nserror treeview_node_mouse_action_cb(treeview_node *node, void *ctx,
/* Handle drag start */
if (ma->tree->drag.type == TV_DRAG_NONE) {
if (ma->mouse & BROWSER_MOUSE_DRAG_1 &&
- ma->tree->drag.selected == false &&
- ma->tree->drag.part == TV_NODE_PART_NONE) {
+ ma->tree->drag.selected == false &&
+ ma->tree->drag.part == TV_NODE_PART_NONE) {
ma->tree->drag.type = TV_DRAG_SELECTION;
treeview__cw_drag_status(ma->tree,
- CORE_WINDOW_DRAG_SELECTION);
+ CORE_WINDOW_DRAG_SELECTION);
- } else if (!(ma->tree->flags & TREEVIEW_NO_MOVES) &&
- ma->mouse & BROWSER_MOUSE_DRAG_1 &&
- (ma->tree->drag.selected == true ||
- ma->tree->drag.part == TV_NODE_PART_ON_NODE)) {
+ } else if (ma->tree->search.search == false &&
+ !(ma->tree->flags & TREEVIEW_NO_MOVES) &&
+ ma->mouse & BROWSER_MOUSE_DRAG_1 &&
+ (ma->tree->drag.selected == true ||
+ ma->tree->drag.part == TV_NODE_PART_ON_NODE)) {
ma->tree->drag.type = TV_DRAG_MOVE;
treeview__cw_drag_status(ma->tree,
- CORE_WINDOW_DRAG_MOVE);
+ CORE_WINDOW_DRAG_MOVE);
redraw |= treeview_propagate_selection(ma->tree, &r);
} else if (ma->mouse & BROWSER_MOUSE_DRAG_2) {
ma->tree->drag.type = TV_DRAG_SELECTION;
treeview__cw_drag_status(ma->tree,
- CORE_WINDOW_DRAG_SELECTION);
+ CORE_WINDOW_DRAG_SELECTION);
}
if (ma->tree->drag.start_node != NULL &&
- ma->tree->drag.type == TV_DRAG_SELECTION) {
+ ma->tree->drag.type == TV_DRAG_SELECTION) {
ma->tree->drag.start_node->flags ^= TV_NFLAGS_SELECTED;
}
}
@@ -3391,10 +4478,10 @@ static nserror treeview_node_mouse_action_cb(treeview_node *node, void *ctx,
{
int curr_y1 = ma->current_y + height;
int prev_y1 = ma->tree->drag.prev.node_y +
- ma->tree->drag.prev.node_h;
+ ma->tree->drag.prev.node_h;
r.y0 = (ma->current_y < ma->tree->drag.prev.node_y) ?
- ma->current_y : ma->tree->drag.prev.node_y;
+ ma->current_y : ma->tree->drag.prev.node_y;
r.y1 = (curr_y1 > prev_y1) ? curr_y1 : prev_y1;
redraw = true;
@@ -3408,7 +4495,8 @@ static nserror treeview_node_mouse_action_cb(treeview_node *node, void *ctx,
case TV_DRAG_MOVE:
redraw |= treeview_set_move_indicator(ma->tree, redraw,
- node, height, ma->current_y, ma->y, &r);
+ node, height,
+ ma->current_y, ma->y, &r);
break;
default:
@@ -3418,9 +4506,10 @@ static nserror treeview_node_mouse_action_cb(treeview_node *node, void *ctx,
click = ma->mouse & (BROWSER_MOUSE_CLICK_1 | BROWSER_MOUSE_CLICK_2);
if (((node->type == TREE_NODE_FOLDER) &&
- (ma->mouse & BROWSER_MOUSE_DOUBLE_CLICK) && click) ||
- (part == TV_NODE_PART_TOGGLE && click)) {
- int h = ma->tree->root->height;
+ (ma->mouse & BROWSER_MOUSE_DOUBLE_CLICK) && click) ||
+ (part == TV_NODE_PART_TOGGLE && click)) {
+ int h = treeview__get_display_height(ma->tree) +
+ ma->search_height;
/* Clear any existing selection */
redraw |= treeview_clear_selection(ma->tree, &r);
@@ -3438,11 +4527,17 @@ static nserror treeview_node_mouse_action_cb(treeview_node *node, void *ctx,
/* Set up redraw */
if (!redraw || r.y0 > ma->current_y)
r.y0 = ma->current_y;
- r.y1 = h > ma->tree->root->height ? h : ma->tree->root->height;
+ if (h > treeview__get_display_height(ma->tree) +
+ ma->search_height) {
+ r.y1 = h;
+ } else {
+ r.y1 = treeview__get_display_height(ma->tree) +
+ ma->search_height;
+ }
redraw = true;
} else if ((node->type == TREE_NODE_ENTRY) &&
- (ma->mouse & BROWSER_MOUSE_DOUBLE_CLICK) && click) {
+ (ma->mouse & BROWSER_MOUSE_DOUBLE_CLICK) && click) {
struct treeview_node_msg msg;
msg.msg = TREE_MSG_NODE_LAUNCH;
msg.data.node_launch.mouse = ma->mouse;
@@ -3454,28 +4549,29 @@ static nserror treeview_node_mouse_action_cb(treeview_node *node, void *ctx,
ma->tree->callbacks->entry(msg, node->client_data);
} else if (ma->mouse & BROWSER_MOUSE_PRESS_2 ||
- (ma->mouse & BROWSER_MOUSE_PRESS_1 &&
- ma->mouse & BROWSER_MOUSE_MOD_2)) {
+ (ma->mouse & BROWSER_MOUSE_PRESS_1 &&
+ ma->mouse & BROWSER_MOUSE_MOD_2)) {
/* Toggle selection of node */
action |= TV_NODE_ACTION_SELECTION;
} else if (ma->mouse & BROWSER_MOUSE_CLICK_1 &&
- ma->mouse &
- (BROWSER_MOUSE_MOD_1 | BROWSER_MOUSE_MOD_3) &&
- part != TV_NODE_PART_TOGGLE) {
+ ma->mouse &
+ (BROWSER_MOUSE_MOD_1 | BROWSER_MOUSE_MOD_3) &&
+ part != TV_NODE_PART_TOGGLE) {
/* Clear any existing selection */
redraw |= treeview_clear_selection(ma->tree, &r);
/* Edit node */
redraw |= treeview_edit_node_at_point(ma->tree, node,
- ma->current_y, ma->x, ma->y, &r);
+ ma->current_y, ma->x,
+ ma->y, &r);
} else if (ma->mouse & BROWSER_MOUSE_PRESS_1 &&
- !(ma->mouse &
- (BROWSER_MOUSE_MOD_1 | BROWSER_MOUSE_MOD_3)) &&
- !(node->flags & TV_NFLAGS_SELECTED) &&
- part != TV_NODE_PART_TOGGLE) {
+ !(ma->mouse &
+ (BROWSER_MOUSE_MOD_1 | BROWSER_MOUSE_MOD_3)) &&
+ !(node->flags & TV_NFLAGS_SELECTED) &&
+ part != TV_NODE_PART_TOGGLE) {
/* Clear any existing selection */
redraw |= treeview_clear_selection(ma->tree, &r);
@@ -3494,35 +4590,69 @@ static nserror treeview_node_mouse_action_cb(treeview_node *node, void *ctx,
r.y1 = ma->current_y + height;
redraw = true;
} else {
- if (r.y0 > ma->current_y)
+ if (r.y0 > ma->current_y) {
r.y0 = ma->current_y;
- if (r.y1 < ma->current_y + height)
+ }
+ if (r.y1 < ma->current_y + height) {
r.y1 = ma->current_y + height;
+ }
}
}
if (redraw) {
- treeview__cw_redraw_request(ma->tree, &r);
+ treeview__cw_invalidate_area(ma->tree, &r);
}
*end = true; /* Reached line with click; stop walking tree */
return NSERROR_OK;
}
+
+
/* Exported interface, documented in treeview.h */
-void treeview_mouse_action(treeview *tree,
- browser_mouse_state mouse, int x, int y)
+void
+treeview_mouse_action(treeview *tree, browser_mouse_state mouse, int x, int y)
{
struct rect r;
bool redraw = false;
+ int search_height = (tree->flags & TREEVIEW_SEARCHABLE) ?
+ tree_g.line_height : 0;
assert(tree != NULL);
assert(tree->root != NULL);
+ /* Not interested in whether mouse leaves window. */
+ if (mouse == BROWSER_MOUSE_LEAVE) {
+ return;
+ }
+
/* Handle mouse drag captured by textarea */
if (tree->drag.type == TV_DRAG_TEXTAREA) {
textarea_mouse_action(tree->edit.textarea, mouse,
- x - tree->edit.x, y - tree->edit.y);
+ x - tree->edit.x, y - tree->edit.y);
+ return;
+ } else if (tree->drag.type == TV_DRAG_SEARCH ||
+ (y < search_height &&
+ tree->drag.type == TV_DRAG_NONE)) {
+ if (tree->search.active == false) {
+ tree->search.active = true;
+ if (treeview_clear_selection(tree, &r)) {
+ treeview__cw_invalidate_area(tree, &r);
+ }
+ }
+ textarea_mouse_action(tree->search.textarea, mouse,
+ x - tree_g.window_padding - tree_g.icon_size,
+ y);
return;
+ } else if (mouse & (BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_PRESS_2) &&
+ tree->search.active == true) {
+
+ tree->search.active = false;
+ textarea_set_caret(tree->search.textarea, -1);
+ r.x0 = 0;
+ r.y0 = 0;
+ r.x1 = REDRAW_MAX;
+ r.y1 = tree_g.line_height;
+ treeview__cw_invalidate_area(tree, &r);
}
/* Handle textarea related mouse action */
@@ -3531,10 +4661,10 @@ void treeview_mouse_action(treeview *tree,
int ta_y = y - tree->edit.y;
if (ta_x > 0 && ta_x < tree->edit.w &&
- ta_y > 0 && ta_y < tree->edit.h) {
+ ta_y > 0 && ta_y < tree->edit.h) {
/* Inside textarea */
textarea_mouse_action(tree->edit.textarea, mouse,
- ta_x, ta_y);
+ ta_x, ta_y);
return;
} else if (mouse != BROWSER_MOUSE_HOVER) {
@@ -3562,7 +4692,7 @@ void treeview_mouse_action(treeview *tree,
tree->move.target_pos = TV_TARGET_NONE;
treeview__cw_drag_status(tree, CORE_WINDOW_DRAG_NONE);
- treeview__cw_redraw_request(tree, &r);
+ treeview__cw_invalidate_area(tree, &r);
return;
default:
/* No drag to end */
@@ -3570,7 +4700,7 @@ void treeview_mouse_action(treeview *tree,
}
}
- if (y > tree->root->height) {
+ if (y > treeview__get_display_height(tree) + search_height) {
/* Below tree */
r.x0 = 0;
@@ -3578,7 +4708,7 @@ void treeview_mouse_action(treeview *tree,
/* Record what position / part a drag started on */
if (mouse & (BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_PRESS_2) &&
- tree->drag.type == TV_DRAG_NONE) {
+ tree->drag.type == TV_DRAG_NONE) {
tree->drag.selected = false;
tree->drag.start_node = NULL;
tree->drag.part = TV_NODE_PART_NONE;
@@ -3596,8 +4726,8 @@ void treeview_mouse_action(treeview *tree,
/* Handle drag start */
if (tree->drag.type == TV_DRAG_NONE) {
if (mouse & BROWSER_MOUSE_DRAG_1 &&
- tree->drag.selected == false &&
- tree->drag.part == TV_NODE_PART_NONE) {
+ tree->drag.selected == false &&
+ tree->drag.part == TV_NODE_PART_NONE) {
tree->drag.type = TV_DRAG_SELECTION;
treeview__cw_drag_status(tree,
CORE_WINDOW_DRAG_SELECTION);
@@ -3608,9 +4738,9 @@ void treeview_mouse_action(treeview *tree,
}
if (tree->drag.start_node != NULL &&
- tree->drag.type == TV_DRAG_SELECTION) {
+ tree->drag.type == TV_DRAG_SELECTION) {
tree->drag.start_node->flags ^=
- TV_NFLAGS_SELECTED;
+ TV_NFLAGS_SELECTED;
}
}
@@ -3618,7 +4748,7 @@ void treeview_mouse_action(treeview *tree,
if (tree->drag.type == TV_DRAG_SELECTION) {
int curr_y1 = tree->root->height;
int prev_y1 = tree->drag.prev.node_y +
- tree->drag.prev.node_h;
+ tree->drag.prev.node_h;
r.y0 = tree->drag.prev.node_y;
r.y1 = (curr_y1 > prev_y1) ? curr_y1 : prev_y1;
@@ -3637,20 +4767,22 @@ void treeview_mouse_action(treeview *tree,
}
if (redraw) {
- treeview__cw_redraw_request(tree, &r);
+ treeview__cw_invalidate_area(tree, &r);
}
} else {
/* On tree */
- struct treeview_mouse_action ma;
-
- ma.tree = tree;
- ma.mouse = mouse;
- ma.x = x;
- ma.y = y;
- ma.current_y = 0;
-
- treeview_walk_internal(tree->root, false, NULL,
+ struct treeview_mouse_action ma = {
+ ma.tree = tree,
+ ma.mouse = mouse,
+ ma.x = x,
+ ma.y = y,
+ ma.current_y = search_height,
+ ma.search_height = search_height,
+ };
+
+ treeview_walk_internal(tree, tree->root,
+ TREEVIEW_WALK_MODE_DISPLAY, NULL,
treeview_node_mouse_action_cb, &ma);
}
}
@@ -3659,78 +4791,111 @@ void treeview_mouse_action(treeview *tree,
/* Exported interface, documented in treeview.h */
int treeview_get_height(treeview *tree)
{
+ int search_height = (tree->flags & TREEVIEW_SEARCHABLE) ?
+ tree_g.line_height : 0;
+ int height = treeview__get_display_height(tree);
+
assert(tree != NULL);
assert(tree->root != NULL);
- treeview__cw_update_size(tree, -1, tree->root->height);
+ treeview__cw_update_size(tree, -1, height);
- return tree->root->height;
+ return height + search_height;
}
/**
* Initialise the plot styles from CSS system colour values.
+ *
+ * \param font_pt_size font size to use
+ * \return NSERROR_OK on success else appropriate error code
*/
-static void treeview_init_plot_styles(int font_pt_size)
+static nserror treeview_init_plot_styles(int font_pt_size)
{
+ nserror res;
+
/* Background colour */
plot_style_even.bg.stroke_type = PLOT_OP_TYPE_NONE;
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 = ns_system_colour_char("Window");
+ res = ns_system_colour_char("Window", &plot_style_even.bg.fill_colour);
+ if (res != NSERROR_OK) {
+ return res;
+ }
/* Text colour */
plot_style_even.text.family = PLOT_FONT_FAMILY_SANS_SERIF;
plot_style_even.text.size = font_pt_size;
plot_style_even.text.weight = 400;
plot_style_even.text.flags = FONTF_NONE;
- plot_style_even.text.foreground = ns_system_colour_char("WindowText");
- plot_style_even.text.background = ns_system_colour_char("Window");
+ res = ns_system_colour_char("WindowText", &plot_style_even.text.foreground);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+ res = ns_system_colour_char("Window", &plot_style_even.text.background);
+ if (res != NSERROR_OK) {
+ return res;
+ }
/* Entry field text colour */
plot_style_even.itext = plot_style_even.text;
plot_style_even.itext.foreground = mix_colour(
- plot_style_even.text.foreground,
- plot_style_even.text.background, 255 * 10 / 16);
+ plot_style_even.text.foreground,
+ plot_style_even.text.background,
+ 255 * 10 / 16);
/* Selected background colour */
plot_style_even.sbg = plot_style_even.bg;
- plot_style_even.sbg.fill_colour = ns_system_colour_char("Highlight");
+ res = ns_system_colour_char("Highlight", &plot_style_even.sbg.fill_colour);
+ if (res != NSERROR_OK) {
+ return res;
+ }
/* Selected text colour */
plot_style_even.stext = plot_style_even.text;
- plot_style_even.stext.foreground =
- ns_system_colour_char("HighlightText");
- plot_style_even.stext.background = ns_system_colour_char("Highlight");
+ res = ns_system_colour_char("HighlightText", &plot_style_even.stext.foreground);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+ res = ns_system_colour_char("Highlight", &plot_style_even.stext.background);
+ if (res != NSERROR_OK) {
+ return res;
+ }
/* Selected entry field text colour */
plot_style_even.sitext = plot_style_even.stext;
plot_style_even.sitext.foreground = mix_colour(
- plot_style_even.stext.foreground,
- plot_style_even.stext.background, 255 * 25 / 32);
-
+ plot_style_even.stext.foreground,
+ plot_style_even.stext.background,
+ 255 * 25 / 32);
/* Odd numbered node styles */
plot_style_odd.bg = plot_style_even.bg;
plot_style_odd.bg.fill_colour = mix_colour(
- plot_style_even.bg.fill_colour,
- plot_style_even.text.foreground, 255 * 15 / 16);
+ plot_style_even.bg.fill_colour,
+ plot_style_even.text.foreground, 255 * 15 / 16);
plot_style_odd.text = plot_style_even.text;
plot_style_odd.text.background = plot_style_odd.bg.fill_colour;
plot_style_odd.itext = plot_style_odd.text;
plot_style_odd.itext.foreground = mix_colour(
- plot_style_odd.text.foreground,
- plot_style_odd.text.background, 255 * 10 / 16);
+ plot_style_odd.text.foreground,
+ plot_style_odd.text.background, 255 * 10 / 16);
plot_style_odd.sbg = plot_style_even.sbg;
plot_style_odd.stext = plot_style_even.stext;
plot_style_odd.sitext = plot_style_even.sitext;
+
+ return NSERROR_OK;
}
/**
- * Callback for hlcache.
+ * Callback for hlcache retrieving resources.
+ *
+ * \param handle content hlcache handle
+ * \param event The event that occurred on the content
+ * \param pw treeview resource context
*/
static nserror
treeview_res_cb(struct hlcache_handle *handle,
@@ -3767,9 +4932,10 @@ static void treeview_init_resources(void)
treeview_res[i].height = 0;
if (nsurl_create(treeview_res[i].url, &url) == NSERROR_OK) {
hlcache_handle_retrieve(url, 0, NULL, NULL,
- treeview_res_cb,
- &(treeview_res[i]), NULL,
- CONTENT_IMAGE, &(treeview_res[i].c));
+ treeview_res_cb,
+ &(treeview_res[i]), NULL,
+ CONTENT_IMAGE,
+ &(treeview_res[i].c));
nsurl_unref(url);
}
}
@@ -3779,12 +4945,12 @@ static void treeview_init_resources(void)
/**
* Create a right-pointing anti-aliased triangle bitmap
*
- * bg background colour
- * fg foreground colour
- * size required bitmap size
+ * \param bg background colour
+ * \param fg foreground colour
+ * \param size required bitmap size
*/
-static struct bitmap * treeview_generate_triangle_bitmap(
- colour bg, colour fg, int size)
+static struct bitmap *
+treeview_generate_triangle_bitmap(colour bg, colour fg, int size)
{
struct bitmap *b = NULL;
int x, y;
@@ -3881,11 +5047,11 @@ static struct bitmap * treeview_generate_triangle_bitmap(
/**
* Create bitmap copy of another bitmap
*
- * orig bitmap to copy
- * size required bitmap size
+ * \param orig bitmap to copy
+ * \param size required bitmap size
*/
-static struct bitmap * treeview_generate_copy_bitmap(
- struct bitmap *orig, int size)
+static struct bitmap *
+treeview_generate_copy_bitmap(struct bitmap *orig, int size)
{
struct bitmap *b = NULL;
unsigned char *data;
@@ -3926,11 +5092,11 @@ static struct bitmap * treeview_generate_copy_bitmap(
/**
* Create bitmap from rotation of another bitmap
*
- * orig bitmap to create rotation of
- * size required bitmap size
+ * \param orig bitmap to create rotation of
+ * \param size required bitmap size
*/
-static struct bitmap * treeview_generate_rotate_bitmap(
- struct bitmap *orig, int size)
+static struct bitmap *
+treeview_generate_rotate_bitmap(struct bitmap *orig, int size)
{
struct bitmap *b = NULL;
int x, y;
@@ -3967,7 +5133,7 @@ static struct bitmap * treeview_generate_rotate_bitmap(
*(pos++) = *(orig_pos++);
*(pos++) = *(orig_pos);
*(pos++) = 0xff;
-
+
}
rpos += stride;
@@ -3987,6 +5153,8 @@ static struct bitmap * treeview_generate_rotate_bitmap(
/**
* Measures width of characters used to represent treeview furniture.
+ *
+ * \return NSERROR_OK on success else error code
*/
static nserror treeview_init_furniture(void)
{
@@ -3994,47 +5162,47 @@ static nserror treeview_init_furniture(void)
plot_style_odd.furn[TREE_FURN_EXPAND].size = size;
plot_style_odd.furn[TREE_FURN_EXPAND].bmp =
- treeview_generate_triangle_bitmap(
+ treeview_generate_triangle_bitmap(
plot_style_odd.bg.fill_colour,
plot_style_odd.itext.foreground, size);
plot_style_odd.furn[TREE_FURN_EXPAND].sel =
- treeview_generate_triangle_bitmap(
+ treeview_generate_triangle_bitmap(
plot_style_odd.sbg.fill_colour,
plot_style_odd.sitext.foreground, size);
plot_style_even.furn[TREE_FURN_EXPAND].size = size;
plot_style_even.furn[TREE_FURN_EXPAND].bmp =
- treeview_generate_triangle_bitmap(
+ treeview_generate_triangle_bitmap(
plot_style_even.bg.fill_colour,
plot_style_even.itext.foreground, size);
plot_style_even.furn[TREE_FURN_EXPAND].sel =
- treeview_generate_copy_bitmap(
+ treeview_generate_copy_bitmap(
plot_style_odd.furn[TREE_FURN_EXPAND].sel, size);
plot_style_odd.furn[TREE_FURN_CONTRACT].size = size;
plot_style_odd.furn[TREE_FURN_CONTRACT].bmp =
- treeview_generate_rotate_bitmap(
+ treeview_generate_rotate_bitmap(
plot_style_odd.furn[TREE_FURN_EXPAND].bmp, size);
plot_style_odd.furn[TREE_FURN_CONTRACT].sel =
- treeview_generate_rotate_bitmap(
+ treeview_generate_rotate_bitmap(
plot_style_odd.furn[TREE_FURN_EXPAND].sel, size);
plot_style_even.furn[TREE_FURN_CONTRACT].size = size;
plot_style_even.furn[TREE_FURN_CONTRACT].bmp =
- treeview_generate_rotate_bitmap(
+ treeview_generate_rotate_bitmap(
plot_style_even.furn[TREE_FURN_EXPAND].bmp, size);
plot_style_even.furn[TREE_FURN_CONTRACT].sel =
- treeview_generate_rotate_bitmap(
+ treeview_generate_rotate_bitmap(
plot_style_even.furn[TREE_FURN_EXPAND].sel, size);
if (plot_style_odd.furn[TREE_FURN_EXPAND].bmp == NULL ||
- plot_style_odd.furn[TREE_FURN_EXPAND].sel == NULL ||
- plot_style_even.furn[TREE_FURN_EXPAND].bmp == NULL ||
- plot_style_even.furn[TREE_FURN_EXPAND].sel == NULL ||
- plot_style_odd.furn[TREE_FURN_CONTRACT].bmp == NULL ||
- plot_style_odd.furn[TREE_FURN_CONTRACT].sel == NULL ||
- plot_style_even.furn[TREE_FURN_CONTRACT].bmp == NULL ||
- plot_style_even.furn[TREE_FURN_CONTRACT].sel == NULL)
+ plot_style_odd.furn[TREE_FURN_EXPAND].sel == NULL ||
+ plot_style_even.furn[TREE_FURN_EXPAND].bmp == NULL ||
+ plot_style_even.furn[TREE_FURN_EXPAND].sel == NULL ||
+ plot_style_odd.furn[TREE_FURN_CONTRACT].bmp == NULL ||
+ plot_style_odd.furn[TREE_FURN_CONTRACT].sel == NULL ||
+ plot_style_even.furn[TREE_FURN_CONTRACT].bmp == NULL ||
+ plot_style_even.furn[TREE_FURN_CONTRACT].sel == NULL)
return NSERROR_NOMEM;
tree_g.furniture_width = size + tree_g.line_height / 4;
@@ -4048,14 +5216,14 @@ nserror treeview_init(void)
{
long long font_px_size;
long long font_pt_size;
- nserror err;
+ nserror res;
if (tree_g.initialised > 0) {
tree_g.initialised++;
return NSERROR_OK;
}
- LOG("Initialising treeview module");
+ NSLOG(netsurf, INFO, "Initialising treeview module");
font_pt_size = nsoption_int(treeview_font_size);
if (font_pt_size <= 0) {
@@ -4066,11 +5234,17 @@ nserror treeview_init(void)
10 + 36) / 72;
tree_g.line_height = (font_px_size * 8 + 3) / 6;
- treeview_init_plot_styles(font_pt_size * FONT_SIZE_SCALE / 10);
+ res = treeview_init_plot_styles(font_pt_size * PLOT_STYLE_SCALE / 10);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
treeview_init_resources();
- err = treeview_init_furniture();
- if (err != NSERROR_OK)
- return err;
+
+ res = treeview_init_furniture();
+ if (res != NSERROR_OK) {
+ return res;
+ }
tree_g.step_width = tree_g.furniture_width;
tree_g.window_padding = 6;
@@ -4080,7 +5254,7 @@ nserror treeview_init(void)
tree_g.initialised++;
- LOG("Initialised treeview module");
+ NSLOG(netsurf, INFO, "Initialised treeview module");
return NSERROR_OK;
}
@@ -4096,11 +5270,12 @@ nserror treeview_fini(void)
return NSERROR_OK;
} else if (tree_g.initialised == 0) {
- LOG("Warning: tried to finalise uninitialised treeview module");
+ NSLOG(netsurf, INFO,
+ "Warning: tried to finalise uninitialised treeview module");
return NSERROR_OK;
}
- LOG("Finalising treeview module");
+ NSLOG(netsurf, INFO, "Finalising treeview module");
for (i = 0; i < TREE_RES_LAST; i++) {
hlcache_handle_release(treeview_res[i].c);
@@ -4117,7 +5292,7 @@ nserror treeview_fini(void)
tree_g.initialised--;
- LOG("Finalised treeview module");
+ NSLOG(netsurf, INFO, "Finalised treeview module");
return NSERROR_OK;
}
diff --git a/desktop/treeview.h b/desktop/treeview.h
index 518f045aa..a8cf29ac5 100644
--- a/desktop/treeview.h
+++ b/desktop/treeview.h
@@ -37,6 +37,10 @@ struct core_window_callback_table;
typedef struct treeview treeview;
typedef struct treeview_node treeview_node;
+
+/**
+ * treeview node type
+ */
enum treeview_node_type {
TREE_NODE_NONE = 0, /**< No node */
TREE_NODE_ROOT = (1 << 0), /**< Node is treeview's root */
@@ -44,40 +48,60 @@ enum treeview_node_type {
TREE_NODE_ENTRY = (1 << 2) /**< Node is an entry */
};
+
+/**
+ * Relationship between nodes
+ */
enum treeview_relationship {
TREE_REL_FIRST_CHILD,
TREE_REL_NEXT_SIBLING
-}; /**< Relationship between nodes */
+};
+
+/**
+ * Node change handling options
+ */
typedef enum {
TREE_OPTION_NONE = (0), /* No flags set */
TREE_OPTION_SPECIAL_DIR = (1 << 0), /* Special folder */
TREE_OPTION_SUPPRESS_RESIZE = (1 << 1), /* Suppress callback */
TREE_OPTION_SUPPRESS_REDRAW = (1 << 2) /* Suppress callback */
-} treeview_node_options_flags; /**< Node change handling options */
+} treeview_node_options_flags;
+/**
+ * treeview control flags
+ */
typedef enum {
TREEVIEW_NO_FLAGS = (0), /**< No flags set */
TREEVIEW_NO_MOVES = (1 << 0), /**< No node drags */
TREEVIEW_NO_DELETES = (1 << 1), /**< No node deletes */
TREEVIEW_READ_ONLY = TREEVIEW_NO_MOVES | TREEVIEW_NO_DELETES,
- TREEVIEW_DEL_EMPTY_DIRS = (1 << 2) /**< Delete dirs on empty */
+ TREEVIEW_DEL_EMPTY_DIRS = (1 << 2), /**< Delete dirs on empty */
+ TREEVIEW_SEARCHABLE = (1 << 3), /**< Treeview has search bar */
} treeview_flags;
+/**
+ * treeview message types
+ */
enum treeview_msg {
TREE_MSG_NODE_DELETE, /**< Node to be deleted */
TREE_MSG_NODE_EDIT, /**< Node to be edited */
TREE_MSG_NODE_LAUNCH /**< Node to be launched */
};
+
+
+/**
+ * treeview message
+ */
struct treeview_node_msg {
enum treeview_msg msg; /**< The message type */
union {
struct {
- bool user; /* True iff delete by user interaction */
+ bool user; /**< True iff delete by user interaction */
} delete;
struct {
- lwc_string *field; /* The field being edited */
- const char *text; /* The proposed new value */
+ lwc_string *field; /**< The field being edited */
+ const char *text; /**< The proposed new value */
} node_edit; /* Client may call treeview_update_node_* */
struct {
browser_mouse_state mouse; /* Button / modifier used */
@@ -85,18 +109,32 @@ struct treeview_node_msg {
} data; /**< The message data. */
};
+
+/**
+ * treeview field flags
+ */
enum treeview_field_flags {
- TREE_FLAG_NONE = 0, /**< No flags set */
- TREE_FLAG_ALLOW_EDIT = (1 << 0), /**< Whether allow edit field */
- TREE_FLAG_DEFAULT = (1 << 1), /**< Whether field is default */
- TREE_FLAG_SHOW_NAME = (1 << 2), /**< Whether field name shown */
- TREE_FLAG_COPY_TEXT = (1 << 3) /**< Whether to copy to clipb */
+ TREE_FLAG_NONE = 0, /**< No flags set */
+ TREE_FLAG_ALLOW_EDIT = (1 << 0), /**< Whether allow edit field */
+ TREE_FLAG_DEFAULT = (1 << 1), /**< Whether field is default */
+ TREE_FLAG_SHOW_NAME = (1 << 2), /**< Whether field name shown */
+ TREE_FLAG_COPY_TEXT = (1 << 3), /**< Whether to copy to clipb */
+ TREE_FLAG_SEARCHABLE = (1 << 4), /**< Whether field is searchable */
};
+
+
+/**
+ * Treeview field description
+ */
struct treeview_field_desc {
lwc_string *field; /**< A treeview field name */
enum treeview_field_flags flags; /**< Flags for field */
-}; /**< Treeview field description */
+};
+
+/**
+ * Treeview field data
+ */
struct treeview_field_data {
lwc_string *field; /**< Field name */
const char *value; /**< Field value */
@@ -104,10 +142,14 @@ struct treeview_field_data {
};
+/**
+ * Client callbacks for events concerning nodes
+ */
struct treeview_callback_table {
nserror (*folder)(struct treeview_node_msg msg, void *data);
nserror (*entry)(struct treeview_node_msg msg, void *data);
-}; /**< Client callbacks for events concerning nodes */
+};
+
/**
* Prepare treeview module for treeview usage
@@ -116,6 +158,7 @@ struct treeview_callback_table {
*/
nserror treeview_init(void);
+
/**
* Finalise the treeview module (all treeviews must have been destroyed first)
*
@@ -123,9 +166,18 @@ nserror treeview_init(void);
*/
nserror treeview_fini(void);
+
/**
* Create a treeview
*
+ * The fields array order is as follows (N = n_fields):
+ *
+ * fields[0] Main field for entries (shown when not expanded)
+ * fields[1]...fields[N-2] Additional fields for entries
+ * fields[N-1] Field for folder nodes
+ *
+ * So fields[0] and fields[N-1] have TREE_FLAG_DEFAULT set.
+ *
* \param tree Returns created treeview object
* \param callbacks Treeview client node event callbacks
* \param n_fields Number of treeview fields (see description)
@@ -134,20 +186,13 @@ nserror treeview_fini(void);
* \param cw The core_window in which the treeview is shown
* \param flags Treeview behaviour flags
* \return NSERROR_OK on success, appropriate error otherwise
- *
- * The fields array order is as follows (N = n_fields):
- *
- * fields[0] Main field for entries (shown when not expanded)
- * fields[1]...fields[N-2] Additional fields for entries
- * fields[N-1] Field for folder nodes
- *
- * So fields[0] and fields[N-1] have TREE_FLAG_DEFAULT set.
*/
nserror treeview_create(treeview **tree,
- const struct treeview_callback_table *callbacks,
- int n_fields, struct treeview_field_desc fields[],
- const struct core_window_callback_table *cw_t,
- struct core_window *cw, treeview_flags flags);
+ const struct treeview_callback_table *callbacks,
+ int n_fields, struct treeview_field_desc fields[],
+ const struct core_window_callback_table *cw_t,
+ struct core_window *cw, treeview_flags flags);
+
/**
* Attach a treeview to a corewindow.
@@ -160,45 +205,50 @@ nserror treeview_create(treeview **tree,
* \return NSERROR_OK on success, appropriate error otherwise
*/
nserror treeview_cw_attach(treeview *tree,
- const struct core_window_callback_table *cw_t,
- struct core_window *cw);
+ const struct core_window_callback_table *cw_t,
+ struct core_window *cw);
+
/**
* Detach a treeview from a corewindow
*
- * \param tree Treeview object
+ * \param tree Treeview object
* \return NSERROR_OK on success, appropriate error otherwise
*/
nserror treeview_cw_detach(treeview *tree);
+
/**
* Destroy a treeview object
*
- * \param tree Treeview object to destroy
- * \return NSERROR_OK on success, appropriate error otherwise
- *
* Will emit folder and entry deletion msg callbacks for all nodes in treeview.
+ *
+ * \param tree Treeview object to destroy
+ * \return NSERROR_OK on success, appropriate error otherwise
*/
nserror treeview_destroy(treeview *tree);
+
/**
- * Find a releation for node creation.
- *
- * \param tree Treeview object in which to create folder
- * \param relation Existing node to insert as relation of, or NULL
- * \param rel Folder's relationship to relation
- * \param at_y Iff true, insert at y-offest
- * \param y Y-offset in px from top of hotlist. Ignored if (!at_y).
- * \return NSERROR_OK on success, appropriate error otherwise
+ * Find a relation for node creation.
*
* If at_y is set, we find a relation that will put the created node at that
* position.
*
* If at_y is unset, we find a relation that would put the node below the first
* selected node, or at the end of the treeview if no nodes selected.
+ *
+ * \param tree Treeview object in which to create folder
+ * \param relation Existing node to insert as relation of, or NULL
+ * \param rel Folder's relationship to relation
+ * \param at_y Iff true, insert at y-offset
+ * \param y Y-offset in px from top of hotlist. Ignored if (!at_y).
+ * \return NSERROR_OK on success, appropriate error otherwise
*/
nserror treeview_get_relation(treeview *tree, treeview_node **relation,
- enum treeview_relationship *rel, bool at_y, int y);
+ enum treeview_relationship *rel,
+ bool at_y, int y);
+
/**
* Create a folder node in given treeview
@@ -217,11 +267,13 @@ nserror treeview_get_relation(treeview *tree, treeview_node **relation,
* If relation is NULL, will insert as child of root node.
*/
nserror treeview_create_node_folder(treeview *tree,
- treeview_node **folder,
- treeview_node *relation,
- enum treeview_relationship rel,
- const struct treeview_field_data *field,
- void *data, treeview_node_options_flags flags);
+ treeview_node **folder,
+ treeview_node *relation,
+ enum treeview_relationship rel,
+ const struct treeview_field_data *field,
+ void *data,
+ treeview_node_options_flags flags);
+
/**
* Create an entry node in given treeview
@@ -240,11 +292,13 @@ nserror treeview_create_node_folder(treeview *tree,
* If relation is NULL, will insert as child of root node.
*/
nserror treeview_create_node_entry(treeview *tree,
- treeview_node **entry,
- treeview_node *relation,
- enum treeview_relationship rel,
- const struct treeview_field_data fields[],
- void *data, treeview_node_options_flags flags);
+ treeview_node **entry,
+ treeview_node *relation,
+ enum treeview_relationship rel,
+ const struct treeview_field_data fields[],
+ void *data,
+ treeview_node_options_flags flags);
+
/**
* Update an folder node in given treeview
@@ -258,9 +312,10 @@ nserror treeview_create_node_entry(treeview *tree,
* Field name must match name past in treeview_create fields[N-1].
*/
nserror treeview_update_node_folder(treeview *tree,
- treeview_node *folder,
- const struct treeview_field_data *field,
- void *data);
+ treeview_node *folder,
+ const struct treeview_field_data *field,
+ void *data);
+
/**
* Update an entry node in given treeview
@@ -274,9 +329,9 @@ nserror treeview_update_node_folder(treeview *tree,
* Fields array names must match names past in treeview_create fields[0...N-2].
*/
nserror treeview_update_node_entry(treeview *tree,
- treeview_node *entry,
- const struct treeview_field_data fields[],
- void *data);
+ treeview_node *entry,
+ const struct treeview_field_data fields[],
+ void *data);
/**
@@ -289,12 +344,19 @@ nserror treeview_update_node_entry(treeview *tree,
* \return NSERROR_OK on success, or appropriate error otherwise
*/
typedef nserror (*treeview_walk_cb)(void *ctx, void *node_data,
- enum treeview_node_type type, bool *abort);
+ enum treeview_node_type type, bool *abort);
+
/**
* Walk (depth first) a treeview subtree, calling a callback at each node of
* required type.
*
+ * Example usage: To export a treeview as XML, XML elements can be opened in
+ * enter_cb, and closed in leave_cb.
+ *
+ * Note, if deleting returned node in enter_cb, the walk must be terminated by
+ * setting abort to true.
+ *
* \param tree Treeview object to walk
* \param root Root node to walk tree from (or NULL for tree root)
* \param enter_cb Function to call on entering nodes, or NULL
@@ -302,16 +364,11 @@ typedef nserror (*treeview_walk_cb)(void *ctx, void *node_data,
* \param ctx Client context, passed back to callback function
* \param type The node type(s) of interest
* \return NSERROR_OK on success, or appropriate error otherwise
- *
- * Example usage: To export a treeview as XML, XML elements can be opened in
- * enter_cb, and closed in leave_cb.
- *
- * Note, if deleting returned node in enter_cb, the walk must be terminated by
- * setting abort to true.
*/
nserror treeview_walk(treeview *tree, treeview_node *root,
- treeview_walk_cb enter_cb, treeview_walk_cb leave_cb,
- void *ctx, enum treeview_node_type type);
+ treeview_walk_cb enter_cb, treeview_walk_cb leave_cb,
+ void *ctx, enum treeview_node_type type);
+
/**
* Delete a treeview node
@@ -324,7 +381,8 @@ nserror treeview_walk(treeview *tree, treeview_node *root,
* Will emit folder or entry deletion msg callback.
*/
nserror treeview_delete_node(treeview *tree, treeview_node *n,
- treeview_node_options_flags flags);
+ treeview_node_options_flags flags);
+
/**
* Expand a treeview node
@@ -335,6 +393,7 @@ nserror treeview_delete_node(treeview *tree, treeview_node *n,
*/
nserror treeview_node_expand(treeview *tree, treeview_node *node);
+
/**
* Contract a treeview node
*
@@ -344,6 +403,7 @@ nserror treeview_node_expand(treeview *tree, treeview_node *node);
*/
nserror treeview_node_contract(treeview *tree, treeview_node *node);
+
/**
* Expand a treeview's nodes
*
@@ -353,6 +413,7 @@ nserror treeview_node_contract(treeview *tree, treeview_node *node);
*/
nserror treeview_expand(treeview *tree, bool only_folders);
+
/**
* Contract a treeview's nodes
*
@@ -362,6 +423,7 @@ nserror treeview_expand(treeview *tree, bool only_folders);
*/
nserror treeview_contract(treeview *tree, bool all);
+
/**
* Redraw a treeview object
*
@@ -372,7 +434,8 @@ nserror treeview_contract(treeview *tree, bool all);
* \param ctx Current redraw context
*/
void treeview_redraw(treeview *tree, int x, int y, struct rect *clip,
- const struct redraw_context *ctx);
+ const struct redraw_context *ctx);
+
/**
* Key press handling for treeviews.
@@ -383,6 +446,7 @@ void treeview_redraw(treeview *tree, int x, int y, struct rect *clip,
*/
bool treeview_keypress(treeview *tree, uint32_t key);
+
/**
* Handles all kinds of mouse action
*
@@ -392,16 +456,18 @@ bool treeview_keypress(treeview *tree, uint32_t key);
* \param y Y coordinate
*/
void treeview_mouse_action(treeview *tree,
- browser_mouse_state mouse, int x, int y);
+ browser_mouse_state mouse, int x, int y);
+
/**
* Determine whether treeview has a selection
*
- * \param tree Treeview object to delete node from
+ * \param tree Treeview object to delete node from
* \return true iff treeview has a selection
*/
bool treeview_has_selection(treeview *tree);
+
/**
* Get the first selected node
*
@@ -410,19 +476,21 @@ bool treeview_has_selection(treeview *tree);
* \return node type of first selected node.
*/
enum treeview_node_type treeview_get_selection(treeview *tree,
- void **node_data);
+ void **node_data);
+
/**
* Edit the first selected node
*
- * \param tree Treeview object to edit selected node in
+ * \param tree Treeview object to edit selected node in
*/
void treeview_edit_selection(treeview *tree);
+
/**
* Find current height of a treeview
*
- * \param tree Treeview object to find height of
+ * \param tree Treeview object to find height of
* \return height of treeview in px
*/
int treeview_get_height(treeview *tree);
diff --git a/desktop/version.c b/desktop/version.c
index 6126c5b99..bbe759f2e 100644
--- a/desktop/version.c
+++ b/desktop/version.c
@@ -20,11 +20,11 @@
#include "desktop/version.h"
-const char * const netsurf_version = "3.7 (Dev"
+const char * const netsurf_version = "3.8 (Dev"
#if defined(CI_BUILD)
" CI #" CI_BUILD
#endif
")"
;
const int netsurf_version_major = 3;
-const int netsurf_version_minor = 7;
+const int netsurf_version_minor = 8;