diff options
author | Michael Drake <tlsa@netsurf-browser.org> | 2014-02-15 18:43:59 +0000 |
---|---|---|
committer | Michael Drake <tlsa@netsurf-browser.org> | 2014-02-15 18:44:50 +0000 |
commit | a38a63a37ef8bdc62661d398fb485296c0bed470 (patch) | |
tree | 11a1279537f28f51de2fca4c410ecc9b96629a3d /desktop/local_history.c | |
parent | a55957b1c975e96a60d96d9a70c3b64bf02f96fd (diff) | |
download | netsurf-a38a63a37ef8bdc62661d398fb485296c0bed470.tar.gz netsurf-a38a63a37ef8bdc62661d398fb485296c0bed470.tar.bz2 |
Make history internal to browser_window module.
Diffstat (limited to 'desktop/local_history.c')
-rw-r--r-- | desktop/local_history.c | 855 |
1 files changed, 0 insertions, 855 deletions
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 <bursa@users.sourceforge.net> - * Copyright 2005 Richard Wilson <info@tinct.net> - * - * This file is part of NetSurf, http://www.netsurf-browser.org/ - * - * NetSurf is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * NetSurf is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -/** \file - * Browser history tree (implementation). - */ - -#include <assert.h> -#include <stdbool.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> - -#include "content/content.h" -#include "content/hlcache.h" -#include "content/urldb.h" -#include "css/css.h" -#include "desktop/browser.h" -#include "desktop/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; -} |