From a38a63a37ef8bdc62661d398fb485296c0bed470 Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Sat, 15 Feb 2014 18:43:59 +0000 Subject: Make history internal to browser_window module. --- desktop/Makefile | 2 +- desktop/browser.c | 28 +- desktop/browser_history.c | 915 ++++++++++++++++++++++++++++++++++++++++++++++ desktop/browser_history.h | 141 +++++++ desktop/browser_private.h | 2 +- desktop/frames.c | 1 - desktop/local_history.c | 855 ------------------------------------------- desktop/local_history.h | 133 ------- 8 files changed, 1076 insertions(+), 1001 deletions(-) create mode 100644 desktop/browser_history.c create mode 100644 desktop/browser_history.h delete mode 100644 desktop/local_history.c delete mode 100644 desktop/local_history.h (limited to 'desktop') diff --git a/desktop/Makefile b/desktop/Makefile index 0e2e460de..a914eb3e4 100644 --- a/desktop/Makefile +++ b/desktop/Makefile @@ -12,7 +12,7 @@ desktop/version.c: testament utils/testament.h # S_BROWSER are sources related to full browsers but are common # between RISC OS, GTK, BeOS and AmigaOS builds -S_BROWSER := browser.c download.c frames.c local_history.c netsurf.c \ +S_BROWSER := browser.c browser_history.c download.c frames.c netsurf.c \ save_complete.c save_text.c selection.c textinput.c gui_factory.c S_BROWSER := $(addprefix desktop/,$(S_BROWSER)) diff --git a/desktop/browser.c b/desktop/browser.c index ca60e9ec1..03c7a8e76 100644 --- a/desktop/browser.c +++ b/desktop/browser.c @@ -41,6 +41,7 @@ #include "content/fetch.h" #include "content/hlcache.h" #include "content/urldb.h" +#include "desktop/browser_history.h" #include "desktop/browser_private.h" #include "desktop/download.h" #include "desktop/frames.h" @@ -48,7 +49,6 @@ #include "desktop/gui_factory.h" #include "desktop/hotlist.h" #include "desktop/knockout.h" -#include "desktop/local_history.h" #include "utils/nsoption.h" #include "desktop/scrollbar.h" #include "desktop/selection.h" @@ -778,18 +778,22 @@ nserror browser_window_create(enum browser_window_create_flags flags, * \param bw The window to initialise * \param existing The existing window if cloning, else NULL */ -void browser_window_initialise_common(enum browser_window_create_flags flags, +nserror browser_window_initialise_common(enum browser_window_create_flags flags, struct browser_window *bw, struct browser_window *existing) { + nserror err; assert(bw); if (flags & BW_CREATE_CLONE) { assert(existing != NULL); - bw->history = history_clone(existing->history, bw); + err = browser_window_history_clone(existing, bw); } else { - bw->history = history_create(bw); + err = browser_window_history_create(bw); } + if (err != NSERROR_OK) + return err; + /* window characteristics */ bw->refresh_interval = -1; @@ -807,6 +811,8 @@ void browser_window_initialise_common(enum browser_window_create_flags flags, bw->status_text_len = 0; bw->status_match = 0; bw->status_miss = 0; + + return NSERROR_OK; } /** @@ -1288,7 +1294,7 @@ static nserror browser_window_callback(hlcache_handle *c, * after, we only leak the thumbnails when urldb does * not add the URL. */ - history_add(bw->history, c, bw->frag_id); + browser_window_history_add(bw, c, bw->frag_id); } /* frames */ @@ -1318,7 +1324,7 @@ static nserror browser_window_callback(hlcache_handle *c, browser_window_stop_throbber(bw); browser_window_update_favicon(c, bw, NULL); - history_update(bw->history, c); + browser_window_history_update(bw, c); hotlist_update_url(hlcache_handle_get_url(c)); if (bw->refresh_interval != -1) @@ -1689,7 +1695,7 @@ void browser_window_destroy_internal(struct browser_window *bw) if (bw->frag_id != NULL) lwc_string_unref(bw->frag_id); - history_destroy(bw->history); + browser_window_history_destroy(bw); free(bw->name); free(bw->status_text); @@ -1882,7 +1888,7 @@ nserror browser_window_navigate(struct browser_window *bw, } if ((flags & BW_NAVIGATE_HISTORY) != 0) { - history_add(bw->history, + browser_window_history_add(bw, bw->current_content, bw->frag_id); } @@ -3047,7 +3053,8 @@ void browser_window_page_drag_start(struct browser_window *bw, int x, int y) bool browser_window_back_available(struct browser_window *bw) { - return (bw && bw->history && history_back_available(bw->history)); + return (bw && bw->history && + browser_window_history_back_available(bw)); } @@ -3060,7 +3067,8 @@ bool browser_window_back_available(struct browser_window *bw) bool browser_window_forward_available(struct browser_window *bw) { - return (bw && bw->history && history_forward_available(bw->history)); + return (bw && bw->history && + browser_window_history_forward_available(bw)); } diff --git a/desktop/browser_history.c b/desktop/browser_history.c new file mode 100644 index 000000000..c52f01c1a --- /dev/null +++ b/desktop/browser_history.c @@ -0,0 +1,915 @@ +/* + * Copyright 2006 James Bursa + * Copyright 2005 Richard Wilson + * + * 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 . + */ + +/** \file + * Browser history tree (implementation). + */ + +#include +#include +#include +#include +#include + +#include "content/content.h" +#include "content/hlcache.h" +#include "content/urldb.h" +#include "css/css.h" +#include "desktop/browser_history.h" +#include "desktop/browser_private.h" +#include "desktop/plotters.h" +#include "desktop/thumbnail.h" +#include "image/bitmap.h" +#include "render/font.h" +#include "utils/log.h" +#include "utils/nsurl.h" +#include "utils/utils.h" + + +#define WIDTH 100 +#define HEIGHT 86 +#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 start entry to clone + * + * \return a cloned history entry, or 0 on error + */ + +static struct history_entry *browser_window_history__clone_entry( + struct history *history, + struct history_entry *entry) +{ + struct history_entry *child; + struct history_entry *new_child; + struct history_entry *prev = NULL; + struct history_entry *new_entry; + + assert(entry->page.url); + assert(entry->page.title); + + /* clone the entry */ + new_entry = malloc(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); + + 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); + free(new_entry->page.title); + free(new_entry); + return NULL; + } + + /* update references */ + if (history->current == entry) + history->current = new_entry; + + /* recurse for all children */ + for (child = new_entry->forward; child; child = child->next) { + new_child = browser_window_history__clone_entry(history, child); + if (new_child) { + new_child->back = new_entry; + } else { + nsurl_unref(new_entry->page.url); + if (new_entry->page.frag_id) + lwc_string_unref(new_entry->page.frag_id); + free(new_entry->page.title); + free(new_entry); + return NULL; + } + if (prev) + prev->next = new_child; + if (new_entry->forward == child) + new_entry->forward = new_child; + if (new_entry->forward_pref == child) + new_entry->forward_pref = new_child; + if (new_entry->forward_last == child) + new_entry->forward_last = new_child; + prev = new_child; + } + return new_entry; +} + + +/** + * Free an entry in the tree recursively. + */ + +static void browser_window_history__free_entry(struct history_entry *entry) +{ + if (!entry) + return; + browser_window_history__free_entry(entry->forward); + browser_window_history__free_entry(entry->next); + nsurl_unref(entry->page.url); + if (entry->page.frag_id) + lwc_string_unref(entry->page.frag_id); + free(entry->page.title); + free(entry); +} + + +/** + * Recursively position a subtree. + * + * \param history history being laid out + * \param entry subtree to position + * \param x x position for entry + * \param y smallest available y + * \param shuffle shuffle layout + * \return greatest y used by subtree + */ + +static int browser_window_history__layout_subtree(struct history *history, + struct history_entry *entry, int x, int y, bool shuffle) +{ + struct history_entry *child; + int y1 = y; + + if (history->width < x + WIDTH) + history->width = x + WIDTH; + + if (!entry->forward) { + entry->x = x; + entry->y = y; + if (shuffle) { + entry->x = rand() % 600; + entry->y = rand() % 400; + } + return y + HEIGHT; + } + + /* layout child subtrees below each other */ + for (child = entry->forward; child; child = child->next) { + y1 = browser_window_history__layout_subtree(history, child, + x + WIDTH + RIGHT_MARGIN, y1, shuffle); + if (child->next) + y1 += BOTTOM_MARGIN; + } + + /* place ourselves in the middle */ + entry->x = x; + entry->y = (y + y1) / 2 - HEIGHT / 2; + if (shuffle) { + entry->x = rand() % 600; + entry->y = rand() % 400; + } + + return y1; +} + + +/** + * Compute node positions. + * + * \param history history to layout + * + * Each node's x and y are filled in. + */ + +static void browser_window_history__layout(struct history *history) +{ + time_t t = time(0); + struct tm *tp = localtime(&t); + bool shuffle = tp->tm_mon == 3 && tp->tm_mday == 1; + + if (!history) + return; + + history->width = 0; + if (history->start) + history->height = browser_window_history__layout_subtree( + history, history->start, + RIGHT_MARGIN / 2, BOTTOM_MARGIN / 2, + shuffle); + else + history->height = 0; + if (shuffle) { + history->width = 600 + WIDTH; + history->height = 400 + HEIGHT; + } + history->width += RIGHT_MARGIN / 2; + history->height += BOTTOM_MARGIN / 2; +} + +/** + * Recursively redraw a history_entry. + * + * \param history history containing the entry + * \param history_entry entry to render + * \param ctx current redraw context + */ + +static bool browser_window_history__redraw_entry(struct history *history, + struct history_entry *entry, + int x0, int y0, int x1, int y1, + int x, int y, bool clip, + const struct redraw_context *ctx) +{ + const struct plotter_table *plot = ctx->plot; + size_t char_offset; + int actual_x; + struct history_entry *child; + colour c = entry == history->current ? + HISTORY_COLOUR_SELECTED : HISTORY_COLOUR_FOREGROUND; + int tailsize = 5; + int xoffset = x - x0; + int yoffset = y - y0; + plot_style_t pstyle_history_rect = { + .stroke_type = PLOT_OP_TYPE_SOLID, + .stroke_colour = c, + .stroke_width = entry == history->current ? 3 : 1, + }; + plot_font_style_t fstyle = *plot_style_font; + + if (clip) { + struct rect rect; + rect.x0 = x0 + xoffset; + rect.y0 = y0 + yoffset; + rect.x1 = x1 + xoffset; + rect.y1 = y1 + yoffset; + if(!plot->clip(&rect)) + return false; + } + + if (!plot->bitmap(entry->x + xoffset, entry->y + yoffset, WIDTH, HEIGHT, + entry->bitmap, 0xffffff, 0)) + return false; + if (!plot->rectangle(entry->x - 1 + xoffset, + entry->y - 1 + yoffset, + entry->x + xoffset + WIDTH, + entry->y + yoffset + HEIGHT, + &pstyle_history_rect)) + return false; + + if (!nsfont.font_position_in_string(plot_style_font, entry->page.title, + strlen(entry->page.title), WIDTH, + &char_offset, &actual_x)) + return false; + + fstyle.background = HISTORY_COLOUR_BACKGROUND; + fstyle.foreground = c; + fstyle.weight = entry == history->current ? 900 : 400; + + if (!plot->text(entry->x + xoffset, entry->y + HEIGHT + 12 + yoffset, + entry->page.title, char_offset, &fstyle)) + return false; + + for (child = entry->forward; child; child = child->next) { + if (!plot->line(entry->x + WIDTH + xoffset, + entry->y + HEIGHT / 2 + yoffset, + entry->x + WIDTH + tailsize + xoffset, + entry->y + HEIGHT / 2 + yoffset, + plot_style_stroke_history)) + return false; + if (!plot->line(entry->x + WIDTH + tailsize + xoffset, + entry->y + HEIGHT / 2 + yoffset, + child->x - tailsize +xoffset, + child->y + HEIGHT / 2 + yoffset, + plot_style_stroke_history)) + return false; + if (!plot->line(child->x - tailsize + xoffset, + child->y + HEIGHT / 2 + yoffset, + child->x + xoffset, child->y + + HEIGHT / 2 + yoffset, + plot_style_stroke_history)) + return false; + if (!browser_window_history__redraw_entry(history, child, + x0, y0, x1, y1, x, y, clip, ctx)) + return false; + } + + return true; +} + + +/** + * Find the history entry at a position. + * + * \param entry entry to search from + * \param x coordinate + * \param y coordinate + * \return an entry if found, 0 if none + */ + +static struct history_entry *browser_window_history__find_position( + struct history_entry *entry, int x, int y) +{ + struct history_entry *child; + struct history_entry *found; + + if (!entry) + return 0; + + if (entry->x <= x && x <= entry->x + WIDTH && + entry->y <= y && y <= entry->y + HEIGHT) + return entry; + + for (child = entry->forward; child; child = child->next) { + found = browser_window_history__find_position(child, x, y); + if (found) + return found; + } + + return 0; +} + +/** + * Enumerate subentries in history + * See also history_enumerate() + * + * \param bw The browser window to enumerate history of + * \param entry entry to start enumeration at + * \param cb callback function + * \param ud context pointer passed to cb + * \return true to continue enumeration, false to cancel + */ +static bool browser_window_history__enumerate_entry( + const struct browser_window *bw, + const struct history_entry *entry, + browser_window_history_enumerate_cb cb, + void *ud) +{ + const struct history_entry *child; + + if (!cb(bw, entry->x, entry->y, + entry->x + WIDTH, entry->y + HEIGHT, + entry, ud)) + return false; + + for (child = entry->forward; child; child = child->next) { + if (!browser_window_history__enumerate_entry(bw, child, + cb, ud)) + return false; + } + + return true; +} + + +/* -------------------------------------------------------------------------- */ + + +/** + * Create a new history tree for a browser window window. + * + * \param bw browser window to create history for. + * + * \return NSERROR_OK or appropriate error otherwise + */ + +nserror browser_window_history_create(struct browser_window *bw) +{ + struct history *history; + + bw->history = NULL; + + history = calloc(1, sizeof *history); + if (!history) { + warn_user("NoMemory", 0); + return NSERROR_NOMEM; + } + history->width = RIGHT_MARGIN / 2; + history->height = BOTTOM_MARGIN / 2; + + bw->history = history; + return NSERROR_OK; +} + + +/** + * Clone a bw's history tree for new bw + * + * \param bw browser window with history to clone. + * \param new browser window to make cloned history for. + * + * \return NSERROR_OK or appropriate error otherwise + */ + +nserror browser_window_history_clone(const struct browser_window *bw, + struct browser_window *new) +{ + struct history *new_history; + + new->history = NULL; + + if (bw == NULL || bw->history == NULL || bw->history->start == NULL) + return browser_window_history_create(new); + + new_history = malloc(sizeof *new_history); + if (!new_history) + return NSERROR_NOMEM; + + new->history = new_history; + memcpy(new_history, bw->history, sizeof *new_history); + + new_history->start = browser_window_history__clone_entry(new_history, + new_history->start); + if (!new_history->start) { + LOG(("Insufficient memory to clone history")); + warn_user("NoMemory", 0); + browser_window_history_destroy(new); + new->history = NULL; + return NSERROR_NOMEM; + } + + return NSERROR_OK; +} + + +/** + * 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. + * + * The page is added after the current entry and becomes current. + */ + + +void browser_window_history_add(struct browser_window *bw, + struct hlcache_handle *content, lwc_string *frag_id) +{ + struct history *history; + struct history_entry *entry; + nsurl *nsurl = hlcache_handle_get_url(content); + char *title; + struct bitmap *bitmap; + + assert(bw); + assert(bw->history); + assert(content); + + history = bw->history; + + /* allocate space */ + entry = malloc(sizeof *entry); + if (entry == NULL) + return; + + title = strdup(content_get_title(content)); + if (title == NULL) { + warn_user("NoMemory", 0); + free(entry); + return; + } + + entry->page.url = nsurl_ref(nsurl); + entry->page.frag_id = frag_id ? lwc_string_ref(frag_id) : 0; + + entry->page.title = title; + entry->back = history->current; + entry->next = 0; + entry->forward = entry->forward_pref = entry->forward_last = 0; + entry->children = 0; + entry->bitmap = 0; + if (history->current) { + if (history->current->forward_last) + history->current->forward_last->next = entry; + else + history->current->forward = entry; + history->current->forward_pref = entry; + history->current->forward_last = entry; + history->current->children++; + } else { + history->start = entry; + } + history->current = entry; + + /* if we have a thumbnail, don't update until the page has finished + * loading */ + bitmap = urldb_get_thumbnail(nsurl); + if (!bitmap) { + LOG(("Creating thumbnail for %s", nsurl_access(nsurl))); + bitmap = bitmap_create(WIDTH, HEIGHT, + BITMAP_NEW | BITMAP_CLEAR_MEMORY | + BITMAP_OPAQUE); + if (!bitmap) { + warn_user("NoMemory", 0); + return; + } + if (thumbnail_create(content, bitmap, nsurl) == false) { + /* Thumbnailing failed. Ignore it silently */ + bitmap_destroy(bitmap); + bitmap = NULL; + } + } + entry->bitmap = bitmap; + + browser_window_history__layout(history); +} + + +/** + * Update the thumbnail for the current entry. + * + * \param history opaque history structure, as returned by history_create() + * \param content content for current entry + */ + +void browser_window_history_update(struct browser_window *bw, + struct hlcache_handle *content) +{ + struct history *history; + char *title; + + assert(bw != NULL); + + history = bw->history; + + if (!history || !history->current || !history->current->bitmap) + return; + + assert(history->current->page.url); + assert(history->current->page.title); + + title = strdup(content_get_title(content)); + if (!title) { + warn_user("NoMemory", 0); + return; + } + + assert(title); + free(history->current->page.title); + history->current->page.title = title; + + thumbnail_create(content, history->current->bitmap, NULL); +} + + +/** + * Free a history structure. + * + * \param history opaque history structure, as returned by history_create() + */ + +void browser_window_history_destroy(struct browser_window *bw) +{ + assert(bw != NULL); + + if (bw->history == NULL) + return; + + browser_window_history__free_entry(bw->history->start); + free(bw->history); + + bw->history = NULL; +} + + +/** + * Go back in the history. + * + * \param bw browser window + * \param history history of the window + * \param new_window whether to open in new window + */ + +void browser_window_history_back(struct browser_window *bw, bool new_window) +{ + if (!bw || !bw->history || !bw->history->current || + !bw->history->current->back) + return; + browser_window_history_go(bw, bw->history->current->back, new_window); +} + + +/** + * Go forward in the history. + * + * \param bw browser window + * \param history history of the window + * \param new_window whether to open in new window + */ + +void browser_window_history_forward(struct browser_window *bw, bool new_window) +{ + if (!bw || !bw->history || !bw->history->current || + !bw->history->current->forward_pref) + return; + browser_window_history_go(bw, bw->history->current->forward_pref, + new_window); +} + + +/** + * Check whether it is pssible to go back in the history. + * + * \param history history of the window + * \return true if the history can go back, false otherwise + */ + +bool browser_window_history_back_available(struct browser_window *bw) +{ + return (bw && bw->history && bw->history->current && + bw->history->current->back); +} + + +/** + * Check whether it is pssible to go forwards in the history. + * + * \param history history of the window + * \return true if the history can go forwards, false otherwise + */ + +bool browser_window_history_forward_available(struct browser_window *bw) +{ + return (bw && bw->history && bw->history->current && + bw->history->current->forward_pref); +} + + +/* Documented in local_history.h */ +void browser_window_history_go(struct browser_window *bw, + struct history_entry *entry, bool new_window) +{ + struct history *history; + nsurl *url; + struct history_entry *current; + nserror error; + + assert(bw != NULL); + history = bw->history; + + if (entry->page.frag_id) { + error = nsurl_refragment(entry->page.url, + entry->page.frag_id, &url); + + if (error != NSERROR_OK) { + warn_user("NoMemory", 0); + return; + } + } else { + url = nsurl_ref(entry->page.url); + } + + if (new_window) { + current = history->current; + history->current = entry; + + browser_window_create(BW_CREATE_CLONE, + url, NULL, bw, NULL); + history->current = current; + } else { + history->current = entry; + browser_window_navigate(bw, url, NULL, + BW_NAVIGATE_NONE, NULL, NULL, NULL); + } + + nsurl_unref(url); +} + + +/** + * Get the dimensions of a history. + * + * \param history history to measure + * \param width updated to width + * \param height updated to height + */ + +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; +} + + +/** + * Redraw a history. + * + * \param history history to render + * \param ctx current redraw context + */ + +bool browser_window_history_redraw(struct browser_window *bw, + const struct redraw_context *ctx) +{ + struct history *history; + + assert(bw != NULL); + history = bw->history; + + if (!history->start) + return true; + return browser_window_history__redraw_entry(history, history->start, + 0, 0, 0, 0, 0, 0, false, ctx); +} + +/** + * Redraw part of a history. + * + * \param history history to render + * \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) +{ + 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); +} + + +/** + * 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) +{ + 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; +} + + +/** + * Determine the URL of the entry at a position. + * + * \param history history to search + * \param x coordinate + * \param y coordinate + * \return URL, or 0 if no entry at (x, y) + */ + +const char *browser_window_history_position_url(struct browser_window *bw, + int x, int y) +{ + struct history_entry *entry; + struct history *history; + + assert(bw != NULL); + history = bw->history; + + entry = browser_window_history__find_position(history->start, x, y); + if (!entry) + return 0; + + return nsurl_access(entry->page.url); +} + +/* Documented in local_history.h */ +void browser_window_history_enumerate_forward(const struct browser_window *bw, + browser_window_history_enumerate_cb cb, void *user_data) +{ + struct history_entry *e; + + if (bw == NULL || bw->history == NULL || bw->history->current == NULL) + return; + + e = bw->history->current->forward_pref; + for (; e != NULL; e = e->forward_pref) { + if (!cb(bw, e->x, e->y, e->x + WIDTH, e->y + HEIGHT, + e, user_data)) + break; + } +} + +/* Documented in local_history.h */ +void browser_window_history_enumerate_back(const struct browser_window *bw, + browser_window_history_enumerate_cb cb, void *user_data) +{ + struct history_entry *e; + + if (bw == NULL || bw->history == NULL || bw->history->current == NULL) + return; + + for (e = bw->history->current->back; e != NULL; e = e->back) { + if (!cb(bw, e->x, e->y, e->x + WIDTH, e->y + HEIGHT, + e, user_data)) + break; + } +} + +/* Documented in local_history.h */ +void browser_window_history_enumerate(const struct browser_window *bw, + browser_window_history_enumerate_cb cb, void *user_data) +{ + if (bw == NULL || bw->history == NULL) + return; + browser_window_history__enumerate_entry(bw, + bw->history->start, cb, user_data); +} + +/* Documented in local_history.h */ +const char *browser_window_history_entry_get_url( + const struct history_entry *entry) +{ + return nsurl_access(entry->page.url); +} + +/* Documented in local_history.h */ +const char *browser_window_history_entry_get_fragment_id( + const struct history_entry *entry) +{ + return (entry->page.frag_id) ? lwc_string_data(entry->page.frag_id) : 0; +} + +/* Documented in local_history.h */ +const char *browser_window_history_entry_get_title( + const struct history_entry *entry) +{ + return entry->page.title; +} diff --git a/desktop/browser_history.h b/desktop/browser_history.h new file mode 100644 index 000000000..11b58e4dd --- /dev/null +++ b/desktop/browser_history.h @@ -0,0 +1,141 @@ +/* + * Copyright 2006 James Bursa + * + * 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 . + */ + +/** \file + * Browser history tree (interface). + */ + +#ifndef _NETSURF_DESKTOP_BROWSER_HISTORY_H_ +#define _NETSURF_DESKTOP_BROWSER_HISTORY_H_ + +#include +#include + +#include "utils/errors.h" + +struct hlcache_handle; +struct browser_window; +struct history_entry; +struct redraw_context; + +nserror browser_window_history_create(struct browser_window *bw); +nserror browser_window_history_clone(const struct browser_window *bw, + struct browser_window *new); +void browser_window_history_add(struct browser_window *bw, + struct hlcache_handle *content, lwc_string *frag_id); +void browser_window_history_update(struct browser_window *bw, + struct hlcache_handle *content); +void browser_window_history_destroy(struct browser_window *bw); +void browser_window_history_back(struct browser_window *bw, bool new_window); +void browser_window_history_forward(struct browser_window *bw, bool new_window); +bool browser_window_history_back_available(struct browser_window *bw); +bool browser_window_history_forward_available(struct browser_window *bw); +void browser_window_history_size(struct browser_window *bw, + int *width, int *height); +bool browser_window_history_redraw(struct browser_window *bw, + const struct redraw_context *ctx); +bool browser_window_history_redraw_rectangle(struct browser_window *bw, + int x0, int y0, int x1, int y1, int x, int y, + const struct redraw_context *ctx); +bool browser_window_history_click(struct browser_window *bw, + int x, int y, bool new_window); +const char *browser_window_history_position_url(struct browser_window *bw, + int x, int y); + +/** + * Callback function type for history enumeration + * + * \param bw The browser window with history being enumerated + * \param x0, y0, x1, y1 Coordinates of entry in history tree view + * \param entry Current history entry + * \return true to continue enumeration, false to cancel enumeration + */ +typedef bool (*browser_window_history_enumerate_cb)( + const struct browser_window *bw, + int x0, int y0, int x1, int y1, + const struct history_entry *entry, void *user_data); + +/** + * Enumerate all entries in the history. + * Do not change the history while it is being enumerated. + * + * \param bw The browser window to enumerate history of + * \param cb callback function + * \param user_data context pointer passed to cb + */ +void browser_window_history_enumerate(const struct browser_window *bw, + browser_window_history_enumerate_cb cb, void *user_data); + +/** + * Enumerate all entries that will be reached by the 'forward' button + * + * \param bw The browser window to enumerate history of + * \param cb The callback function + * \param user_data Data passed to the callback + */ +void browser_window_history_enumerate_forward(const struct browser_window *bw, + browser_window_history_enumerate_cb cb, void *user_data); + +/** + * Enumerate all entries that will be reached by the 'back' button + * + * \param bw The browser window to enumerate history of + * \param cb The callback function + * \param user_data Data passed to the callback + */ +void browser_window_history_enumerate_back(const struct browser_window *bw, + browser_window_history_enumerate_cb cb, void *user_data); + +/** + * Returns the URL to a history entry + * + * \param entry the history entry to retrieve the URL from + * \return the URL + */ +const char *browser_window_history_entry_get_url( + const struct history_entry *entry); + +/** + * Returns the URL to a history entry + * + * \param entry the history entry to retrieve the fragment id from + * \return the fragment id + */ +const char *browser_window_history_entry_get_fragment_id( + const struct history_entry *entry); + +/** + * Returns the title of a history entry + * + * \param entry the history entry to retrieve the title from + * \return the title + */ +const char *browser_window_history_entry_get_title( + const struct history_entry *entry); + +/** + * Navigate to specified history entry, optionally in new window + * + * \param bw browser window + * \param entry entry to open + * \param new_window open entry in new window + */ +void browser_window_history_go(struct browser_window *bw, + struct history_entry *entry, bool new_window); + +#endif diff --git a/desktop/browser_private.h b/desktop/browser_private.h index 9007007a8..339bc46ee 100644 --- a/desktop/browser_private.h +++ b/desktop/browser_private.h @@ -165,7 +165,7 @@ struct browser_window { -void browser_window_initialise_common(enum browser_window_create_flags flags, +nserror browser_window_initialise_common(enum browser_window_create_flags flags, struct browser_window *bw, struct browser_window *existing); /** diff --git a/desktop/frames.c b/desktop/frames.c index ab5f8171c..534cca4f7 100644 --- a/desktop/frames.c +++ b/desktop/frames.c @@ -33,7 +33,6 @@ #include "content/hlcache.h" #include "desktop/browser_private.h" #include "desktop/frames.h" -#include "desktop/local_history.h" #include "desktop/scrollbar.h" #include "desktop/selection.h" #include "utils/log.h" diff --git a/desktop/local_history.c b/desktop/local_history.c deleted file mode 100644 index 687d4c754..000000000 --- a/desktop/local_history.c +++ /dev/null @@ -1,855 +0,0 @@ -/* - * Copyright 2006 James Bursa - * Copyright 2005 Richard Wilson - * - * 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 . - */ - -/** \file - * Browser history tree (implementation). - */ - -#include -#include -#include -#include -#include - -#include "content/content.h" -#include "content/hlcache.h" -#include "content/urldb.h" -#include "css/css.h" -#include "desktop/browser.h" -#include "desktop/local_history.h" -#include "desktop/plotters.h" -#include "desktop/thumbnail.h" -#include "image/bitmap.h" -#include "render/font.h" -#include "utils/log.h" -#include "utils/nsurl.h" -#include "utils/utils.h" - - -#define WIDTH 100 -#define HEIGHT 86 -#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; - /** Browser window that local history belongs to */ - struct browser_window *bw; -}; - -static struct history_entry *history_clone_entry(struct history *history, - struct history_entry *entry); -static void history_free_entry(struct history_entry *entry); -static void history_layout(struct history *history); -static int history_layout_subtree(struct history *history, - struct history_entry *entry, int x, int y, bool shuffle); -static bool history_redraw_entry(struct history *history, - struct history_entry *entry, - int x0, int y0, int x1, int y1, - int x, int y, bool clip, const struct redraw_context *ctx); -static struct history_entry *history_find_position(struct history_entry *entry, - int x, int y); -static bool history_enumerate_entry(const struct history *history, - const struct history_entry *entry, history_enumerate_cb cb, void *ud); - - -/** - * Create a new history tree for a window. - * - * \return pointer to an opaque history structure, 0 on failure. - */ - -struct history *history_create(struct browser_window *bw) -{ - struct history *history; - - history = calloc(1, sizeof *history); - if (!history) { - warn_user("NoMemory", 0); - return 0; - } - history->width = RIGHT_MARGIN / 2; - history->height = BOTTOM_MARGIN / 2; - history->bw = bw; - return history; -} - - -/** - * Clone a history tree - * - * \param history opaque history structure, as returned by history_create() - * - * \return pointer to an opaque history structure, 0 on failure. - */ - -struct history *history_clone(struct history *history, - struct browser_window *bw) -{ - struct history *new_history; - - if (!history->start) - return history_create(bw); - - new_history = malloc(sizeof *history); - if (!new_history) - return 0; - memcpy(new_history, history, sizeof *history); - - new_history->start = history_clone_entry(new_history, - new_history->start); - if (!history->start) { - LOG(("Insufficient memory to clone history")); - warn_user("NoMemory", 0); - history_destroy(new_history); - return 0; - } - - new_history->bw = bw; - - return new_history; -} - - -/** - * Clone a history entry - * - * \param history opaque history structure, as returned by history_create() - * \param start entry to clone - * - * \return a cloned history entry, or 0 on error - */ - -struct history_entry *history_clone_entry(struct history *history, - struct history_entry *entry) -{ - struct history_entry *child; - struct history_entry *new_child; - struct history_entry *prev = NULL; - struct history_entry *new_entry; - - assert(entry->page.url); - assert(entry->page.title); - - /* clone the entry */ - new_entry = malloc(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); - - 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); - free(new_entry->page.title); - free(new_entry); - return NULL; - } - - /* update references */ - if (history->current == entry) - history->current = new_entry; - - /* recurse for all children */ - for (child = new_entry->forward; child; child = child->next) { - new_child = history_clone_entry(history, child); - if (new_child) { - new_child->back = new_entry; - } else { - nsurl_unref(new_entry->page.url); - if (new_entry->page.frag_id) - lwc_string_unref(new_entry->page.frag_id); - free(new_entry->page.title); - free(new_entry); - return NULL; - } - if (prev) - prev->next = new_child; - if (new_entry->forward == child) - new_entry->forward = new_child; - if (new_entry->forward_pref == child) - new_entry->forward_pref = new_child; - if (new_entry->forward_last == child) - new_entry->forward_last = new_child; - prev = new_child; - } - return new_entry; -} - - -/** - * Insert a url into the history tree. - * - * \param history opaque history structure, as returned by history_create() - * \param content content to add to history - * \param frag_id fragment identifier, or NULL. - * - * The page is added after the current entry and becomes current. - */ - -void history_add(struct history *history, hlcache_handle *content, - lwc_string *frag_id) -{ - struct history_entry *entry; - nsurl *nsurl = hlcache_handle_get_url(content); - char *title; - struct bitmap *bitmap; - - assert(history); - assert(content); - - /* allocate space */ - entry = malloc(sizeof *entry); - if (entry == NULL) - return; - - title = strdup(content_get_title(content)); - if (title == NULL) { - warn_user("NoMemory", 0); - free(entry); - return; - } - - entry->page.url = nsurl_ref(nsurl); - entry->page.frag_id = frag_id ? lwc_string_ref(frag_id) : 0; - - entry->page.title = title; - entry->back = history->current; - entry->next = 0; - entry->forward = entry->forward_pref = entry->forward_last = 0; - entry->children = 0; - entry->bitmap = 0; - if (history->current) { - if (history->current->forward_last) - history->current->forward_last->next = entry; - else - history->current->forward = entry; - history->current->forward_pref = entry; - history->current->forward_last = entry; - history->current->children++; - } else { - history->start = entry; - } - history->current = entry; - - /* if we have a thumbnail, don't update until the page has finished - * loading */ - bitmap = urldb_get_thumbnail(nsurl); - if (!bitmap) { - LOG(("Creating thumbnail for %s", nsurl_access(nsurl))); - bitmap = bitmap_create(WIDTH, HEIGHT, - BITMAP_NEW | BITMAP_CLEAR_MEMORY | - BITMAP_OPAQUE); - if (!bitmap) { - warn_user("NoMemory", 0); - return; - } - if (thumbnail_create(content, bitmap, nsurl) == false) { - /* Thumbnailing failed. Ignore it silently */ - bitmap_destroy(bitmap); - bitmap = NULL; - } - } - entry->bitmap = bitmap; - - history_layout(history); -} - - -/** - * Update the thumbnail for the current entry. - * - * \param history opaque history structure, as returned by history_create() - * \param content content for current entry - */ - -void history_update(struct history *history, hlcache_handle *content) -{ - char *title; - - if (!history || !history->current || !history->current->bitmap) - return; - - assert(history->current->page.url); - assert(history->current->page.title); - - title = strdup(content_get_title(content)); - if (!title) { - warn_user("NoMemory", 0); - return; - } - - assert(title); - free(history->current->page.title); - history->current->page.title = title; - - thumbnail_create(content, history->current->bitmap, NULL); -} - - -/** - * Free a history structure. - * - * \param history opaque history structure, as returned by history_create() - */ - -void history_destroy(struct history *history) -{ - if (!history) - return; - history_free_entry(history->start); - free(history); -} - - -/** - * Free an entry in the tree recursively. - */ - -void history_free_entry(struct history_entry *entry) -{ - if (!entry) - return; - history_free_entry(entry->forward); - history_free_entry(entry->next); - nsurl_unref(entry->page.url); - if (entry->page.frag_id) - lwc_string_unref(entry->page.frag_id); - free(entry->page.title); - free(entry); -} - - -/** - * Go back in the history. - * - * \param bw browser window - * \param history history of the window - * \param new_window whether to open in new window - */ - -void history_back(struct history *history, bool new_window) -{ - if (!history || !history->current || !history->current->back) - return; - history_go(history, history->current->back, new_window); -} - - -/** - * Go forward in the history. - * - * \param bw browser window - * \param history history of the window - * \param new_window whether to open in new window - */ - -void history_forward(struct history *history, bool new_window) -{ - if (!history || !history->current || !history->current->forward_pref) - return; - history_go(history, history->current->forward_pref, new_window); -} - - -/** - * Check whether it is pssible to go back in the history. - * - * \param history history of the window - * \return true if the history can go back, false otherwise - */ - -bool history_back_available(struct history *history) -{ - return (history && history->current && history->current->back); -} - - -/** - * Check whether it is pssible to go forwards in the history. - * - * \param history history of the window - * \return true if the history can go forwards, false otherwise - */ - -bool history_forward_available(struct history *history) -{ - return (history && history->current && history->current->forward_pref); -} - - -/* Documented in local_history.h */ -void history_go(struct history *history, struct history_entry *entry, - bool new_window) -{ - nsurl *url; - struct history_entry *current; - nserror error; - -// LOG(("%p %p %p", bw, history, entry)); -// LOG(("%s %s %s", -// entry->page.url, entry->page.title, entry->page.frag_id)); - - if (entry->page.frag_id) { - error = nsurl_refragment(entry->page.url, - entry->page.frag_id, &url); - - if (error != NSERROR_OK) { - warn_user("NoMemory", 0); - return; - } - } else { - url = nsurl_ref(entry->page.url); - } - - if (new_window) { - current = history->current; - history->current = entry; - - browser_window_create(BW_CREATE_CLONE, - url, NULL, history->bw, NULL); - history->current = current; - } else { - history->current = entry; - browser_window_navigate(history->bw, url, NULL, - BW_NAVIGATE_NONE, NULL, NULL, NULL); - } - - nsurl_unref(url); -} - - -/** - * Compute node positions. - * - * \param history history to layout - * - * Each node's x and y are filled in. - */ - -void history_layout(struct history *history) -{ - time_t t = time(0); - struct tm *tp = localtime(&t); - bool shuffle = tp->tm_mon == 3 && tp->tm_mday == 1; - - if (!history) - return; - - history->width = 0; - if (history->start) - history->height = history_layout_subtree(history, - history->start, RIGHT_MARGIN / 2, BOTTOM_MARGIN / 2, - shuffle); - else - history->height = 0; - if (shuffle) { - history->width = 600 + WIDTH; - history->height = 400 + HEIGHT; - } - history->width += RIGHT_MARGIN / 2; - history->height += BOTTOM_MARGIN / 2; -} - - -/** - * Recursively position a subtree. - * - * \param history history being laid out - * \param entry subtree to position - * \param x x position for entry - * \param y smallest available y - * \param shuffle shuffle layout - * \return greatest y used by subtree - */ - -int history_layout_subtree(struct history *history, - struct history_entry *entry, int x, int y, bool shuffle) -{ - struct history_entry *child; - int y1 = y; - - if (history->width < x + WIDTH) - history->width = x + WIDTH; - - if (!entry->forward) { - entry->x = x; - entry->y = y; - if (shuffle) { - entry->x = rand() % 600; - entry->y = rand() % 400; - } - return y + HEIGHT; - } - - /* layout child subtrees below each other */ - for (child = entry->forward; child; child = child->next) { - y1 = history_layout_subtree(history, child, - x + WIDTH + RIGHT_MARGIN, y1, shuffle); - if (child->next) - y1 += BOTTOM_MARGIN; - } - - /* place ourselves in the middle */ - entry->x = x; - entry->y = (y + y1) / 2 - HEIGHT / 2; - if (shuffle) { - entry->x = rand() % 600; - entry->y = rand() % 400; - } - - return y1; -} - - -/** - * Get the dimensions of a history. - * - * \param history history to measure - * \param width updated to width - * \param height updated to height - */ - -void history_size(struct history *history, int *width, int *height) -{ - *width = history->width; - *height = history->height; -} - - -/** - * Redraw a history. - * - * \param history history to render - * \param ctx current redraw context - */ - -bool history_redraw(struct history *history, const struct redraw_context *ctx) -{ - if (!history->start) - return true; - return history_redraw_entry(history, history->start, 0, 0, 0, 0, 0, 0, - false, ctx); -} - -/** - * Redraw part of a history. - * - * \param history history to render - * \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 history_redraw_rectangle(struct history *history, - int x0, int y0, int x1, int y1, - int x, int y, const struct redraw_context *ctx) -{ - if (!history->start) - return true; - return history_redraw_entry(history, history->start, - x0, y0, x1, y1, x, y, true, ctx); -} - -/** - * Recursively redraw a history_entry. - * - * \param history history containing the entry - * \param history_entry entry to render - * \param ctx current redraw context - */ - -bool history_redraw_entry(struct history *history, - struct history_entry *entry, - int x0, int y0, int x1, int y1, - int x, int y, bool clip, const struct redraw_context *ctx) -{ - const struct plotter_table *plot = ctx->plot; - size_t char_offset; - int actual_x; - struct history_entry *child; - colour c = entry == history->current ? HISTORY_COLOUR_SELECTED : HISTORY_COLOUR_FOREGROUND; - int tailsize = 5; - int xoffset = x - x0; - int yoffset = y - y0; - plot_style_t pstyle_history_rect = { - .stroke_type = PLOT_OP_TYPE_SOLID, - .stroke_colour = c, - .stroke_width = entry == history->current ? 3 : 1, - }; - plot_font_style_t fstyle = *plot_style_font; - - if (clip) { - struct rect rect; - rect.x0 = x0 + xoffset; - rect.y0 = y0 + yoffset; - rect.x1 = x1 + xoffset; - rect.y1 = y1 + yoffset; - if(!plot->clip(&rect)) - return false; - } - - if (!plot->bitmap(entry->x + xoffset, entry->y + yoffset, WIDTH, HEIGHT, - entry->bitmap, 0xffffff, 0)) - return false; - if (!plot->rectangle(entry->x - 1 + xoffset, - entry->y - 1 + yoffset, - entry->x + xoffset + WIDTH, - entry->y + yoffset + HEIGHT, - &pstyle_history_rect)) - return false; - - if (!nsfont.font_position_in_string(plot_style_font, entry->page.title, - strlen(entry->page.title), WIDTH, - &char_offset, &actual_x)) - return false; - - fstyle.background = HISTORY_COLOUR_BACKGROUND; - fstyle.foreground = c; - fstyle.weight = entry == history->current ? 900 : 400; - - if (!plot->text(entry->x + xoffset, entry->y + HEIGHT + 12 + yoffset, - entry->page.title, char_offset, &fstyle)) - return false; - - for (child = entry->forward; child; child = child->next) { - if (!plot->line(entry->x + WIDTH + xoffset, - entry->y + HEIGHT / 2 + yoffset, - entry->x + WIDTH + tailsize + xoffset, - entry->y + HEIGHT / 2 + yoffset, - plot_style_stroke_history)) - return false; - if (!plot->line(entry->x + WIDTH + tailsize + xoffset, - entry->y + HEIGHT / 2 + yoffset, - child->x - tailsize +xoffset, - child->y + HEIGHT / 2 + yoffset, - plot_style_stroke_history)) - return false; - if (!plot->line(child->x - tailsize + xoffset, - child->y + HEIGHT / 2 + yoffset, - child->x + xoffset, child->y + HEIGHT / 2 + yoffset, - plot_style_stroke_history)) - return false; - if (!history_redraw_entry(history, child, x0, y0, x1, y1, x, y, - clip, ctx)) - return false; - } - - return true; -} - - -/** - * Handle a mouse click in a history. - * - * \param bw browser window containing history - * \param history history that was clicked in - * \param x click coordinate - * \param y click coordinate - * \param new_window open a new window instead of using bw - * \return true if action was taken, false if click was not on an entry - */ - -bool history_click(struct history *history, int x, int y, bool new_window) -{ - struct history_entry *entry; - - entry = history_find_position(history->start, x, y); - if (!entry) - return false; - if (entry == history->current) - return false; - - history_go(history, entry, new_window); - - return true; -} - - -/** - * Determine the URL of the entry at a position. - * - * \param history history to search - * \param x coordinate - * \param y coordinate - * \return URL, or 0 if no entry at (x, y) - */ - -const char *history_position_url(struct history *history, int x, int y) -{ - struct history_entry *entry; - - entry = history_find_position(history->start, x, y); - if (!entry) - return 0; - - return nsurl_access(entry->page.url); -} - - -/** - * Find the history entry at a position. - * - * \param entry entry to search from - * \param x coordinate - * \param y coordinate - * \return an entry if found, 0 if none - */ - -struct history_entry *history_find_position(struct history_entry *entry, - int x, int y) -{ - 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 = history_find_position(child, x, y); - if (found) - return found; - } - - return 0; -} - -/* Documented in local_history.h */ -void history_enumerate_forward(struct history *history, - history_enumerate_cb cb, void *user_data) -{ - struct history_entry *entry; - - if (history == NULL || history->current == NULL) return; - - for (entry = history->current->forward_pref; entry != NULL; entry = entry->forward_pref) { - if (!cb(history, entry->x, entry->y, entry->x + WIDTH, - entry->y + HEIGHT, entry, user_data)) - break; - } -} - -/* Documented in local_history.h */ -void history_enumerate_back(struct history *history, - history_enumerate_cb cb, void *user_data) -{ - struct history_entry *entry; - - if (history == NULL || history->current == NULL) return; - - for (entry = history->current->back; entry != NULL; entry = entry->back) { - if (!cb(history, entry->x, entry->y, entry->x + WIDTH, - entry->y + HEIGHT, entry, user_data)) - break; - } -} - -/* Documented in local_history.h */ -void history_enumerate(const struct history *history, history_enumerate_cb cb, - void *user_data) -{ - history_enumerate_entry(history, history->start, cb, user_data); -} - -/** - * Enumerate subentries in history - * See also history_enumerate() - * - * \param history history to enumerate - * \param entry entry to start enumeration at - * \param cb callback function - * \param ud context pointer passed to cb - * \return true to continue enumeration, false to cancel - */ -static bool history_enumerate_entry(const struct history *history, - const struct history_entry *entry, history_enumerate_cb cb, void *ud) -{ - const struct history_entry *child; - - if (!cb(history, entry->x, entry->y, entry->x + WIDTH, entry->y + HEIGHT, - entry, ud)) return false; - - for (child = entry->forward; child; child = child->next) { - if (!history_enumerate_entry(history, child, cb, ud)) - return false; - } - - return true; -} - -/* Documented in local_history.h */ -const char *history_entry_get_url(const struct history_entry *entry) -{ - return nsurl_access(entry->page.url); -} - -/* Documented in local_history.h */ -const char *history_entry_get_fragment_id(const struct history_entry *entry) -{ - return (entry->page.frag_id) ? lwc_string_data(entry->page.frag_id) : 0; -} - -/* Documented in local_history.h */ -const char *history_entry_get_title(const struct history_entry *entry) -{ - return entry->page.title; -} diff --git a/desktop/local_history.h b/desktop/local_history.h deleted file mode 100644 index b3e177b28..000000000 --- a/desktop/local_history.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright 2006 James Bursa - * - * 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 . - */ - -/** \file - * Browser history tree (interface). - */ - -#ifndef _NETSURF_DESKTOP_HISTORY_H_ -#define _NETSURF_DESKTOP_HISTORY_H_ - -#include -#include - -struct hlcache_handle; -struct history; -struct browser_window; -struct history_entry; -struct redraw_context; - -struct history *history_create(struct browser_window *bw); -struct history *history_clone(struct history *history, - struct browser_window *bw); -void history_add(struct history *history, struct hlcache_handle *content, - lwc_string *frag_id); -void history_update(struct history *history, struct hlcache_handle *content); -void history_destroy(struct history *history); -void history_back(struct history *history, bool new_window); -void history_forward(struct history *history, bool new_window); -bool history_back_available(struct history *history); -bool history_forward_available(struct history *history); -void history_size(struct history *history, int *width, int *height); -bool history_redraw(struct history *history, const struct redraw_context *ctx); -bool history_redraw_rectangle(struct history *history, - int x0, int y0, int x1, int y1, int x, int y, - const struct redraw_context *ctx); -bool history_click(struct history *history, int x, int y, bool new_window); -const char *history_position_url(struct history *history, int x, int y); - -/** - * Callback function type for history enumeration - * - * \param history history being enumerated - * \param x0, y0, x1, y1 Coordinates of entry in history tree view - * \param entry Current history entry - * \return true to continue enumeration, false to cancel enumeration - */ -typedef bool (*history_enumerate_cb)(const struct history *history, - int x0, int y0, - int x1, int y1, - const struct history_entry *entry, void *user_data); - -/** - * Enumerate all entries in the history. - * Do not change the history while it is being enumerated. - * - * \param history history to enumerate - * \param cb callback function - * \param user_data context pointer passed to cb - */ -void history_enumerate(const struct history *history, - history_enumerate_cb cb, void *user_data); - -/** - * Enumerate all entries that will be reached by the 'forward' button - * - * \param history The history object to enumerate in - * \param cb The callback function - * \param user_data Data passed to the callback - */ -void history_enumerate_forward( struct history *history, - history_enumerate_cb cb, void *user_data); - -/** - * Enumerate all entries that will be reached by the 'back' button - * - * \param history The history object to enumerate in - * \param cb The callback function - * \param user_data Data passed to the callback - */ -void history_enumerate_back( struct history *history, - history_enumerate_cb cb, void *user_data); - -/** - * Returns the URL to a history entry - * - * \param entry the history entry to retrieve the URL from - * \return the URL - */ -const char *history_entry_get_url(const struct history_entry *entry); - -/** - * Returns the URL to a history entry - * - * \param entry the history entry to retrieve the fragment id from - * \return the fragment id - */ -const char *history_entry_get_fragment_id(const struct history_entry *entry); - -/** - * Returns the title of a history entry - * - * \param entry the history entry to retrieve the title from - * \return the title - */ -const char *history_entry_get_title(const struct history_entry *entry); - -/** - * Open a history entry in the specified browser window - * - * \param bw browser window - * \param history history containing entry - * \param entry entry to open - * \param new_window open entry in new window - */ -void history_go(struct history *history, struct history_entry *entry, - bool new_window); - -#endif -- cgit v1.2.3