summaryrefslogtreecommitdiff
path: root/desktop/browser_history.c
diff options
context:
space:
mode:
Diffstat (limited to 'desktop/browser_history.c')
-rw-r--r--desktop/browser_history.c588
1 files changed, 182 insertions, 406 deletions
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);
}