summaryrefslogtreecommitdiff
path: root/desktop/local_history.c
diff options
context:
space:
mode:
authorMichael Drake <tlsa@netsurf-browser.org>2014-02-15 18:43:59 +0000
committerMichael Drake <tlsa@netsurf-browser.org>2014-02-15 18:44:50 +0000
commita38a63a37ef8bdc62661d398fb485296c0bed470 (patch)
tree11a1279537f28f51de2fca4c410ecc9b96629a3d /desktop/local_history.c
parenta55957b1c975e96a60d96d9a70c3b64bf02f96fd (diff)
downloadnetsurf-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.c855
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;
-}