From 2b87a0b14874d9530d9aca3fb18f5bb74259beae Mon Sep 17 00:00:00 2001 From: Richard Wilson Date: Sat, 22 Apr 2006 16:38:13 +0000 Subject: Clone history for child browser windows. svn path=/trunk/netsurf/; revision=2546 --- desktop/browser.c | 5 ++- desktop/history_core.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++ desktop/history_core.h | 1 + 3 files changed, 95 insertions(+), 1 deletion(-) (limited to 'desktop') diff --git a/desktop/browser.c b/desktop/browser.c index 525d18b5d..dacea8e1d 100644 --- a/desktop/browser.c +++ b/desktop/browser.c @@ -108,7 +108,10 @@ void browser_window_create(const char *url, struct browser_window *clone, bw->current_content = NULL; bw->loading_content = NULL; - bw->history = history_create(); + if (!clone) + bw->history = history_create(); + else + bw->history = history_clone(clone->history); bw->sel = selection_create(bw); bw->throbbing = false; bw->caret_callback = NULL; diff --git a/desktop/history_core.c b/desktop/history_core.c index d851423f1..197596853 100644 --- a/desktop/history_core.c +++ b/desktop/history_core.c @@ -63,6 +63,8 @@ struct history { int height; }; +static bool history_clone_entry(struct history *history, + struct history_entry **start); static void history_free_entry(struct history_entry *entry); static void history_go(struct browser_window *bw, struct history *history, struct history_entry *entry, bool new_window); @@ -98,6 +100,94 @@ struct history *history_create(void) } +/** + * 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 history *new_history; + + if (!history->start) + return history_create(); + + new_history = malloc(sizeof *history); + if (!new_history) + return 0; + memcpy(new_history, history, sizeof *history); + + if (!history_clone_entry(new_history, &new_history->start)) { + warn_user("NoMemory", 0); + return 0; + } + + return new_history; +} + + +/** + * Clone a history entry + * + * \param history opaque history structure, as returned by history_create() + * \param start entry to clone + * + * \return true on success, false otherwise. + */ + +bool history_clone_entry(struct history *history, struct history_entry **start) +{ + struct history_entry *child; + struct history_entry *sibling; + struct history_entry *entry = *start; + struct history_entry *new_entry; + + /* clone the entry */ + new_entry = malloc(sizeof *entry); + if (!new_entry) + return false; + memcpy(new_entry, entry, sizeof *entry); + new_entry->url = strdup(entry->url); + new_entry->frag_id = strdup(entry->frag_id); + new_entry->title = strdup(entry->title); + if (((entry->url) && (!new_entry->url)) || + ((entry->title) && (!new_entry->title)) || + ((entry->frag_id) && (!new_entry->frag_id))) + return false; + if (history->current == entry) + history->current = new_entry; + *start = new_entry; + + if (entry->back) { + /* update all entry->next refrences */ + for (sibling = entry->back->forward; sibling->next; + sibling = sibling->next) { + if (sibling->next == entry) + sibling->next = new_entry; + } + /* update all entry->forward, entry->forward_pref, and + * entry->forward_last references */ + if (entry->back->forward == entry) + entry->back->forward = new_entry; + if (entry->back->forward_pref == entry) + entry->back->forward_pref = new_entry; + if (entry->back->forward_last == entry) + entry->back->forward_last = new_entry; + } + + for (child = entry->forward; child; child = child->next) { + child->back = new_entry; + if (!history_clone_entry(history, &child)) + return false; + } + + return true; +} + + /** * Insert a url into the history tree. * diff --git a/desktop/history_core.h b/desktop/history_core.h index 4889ad524..d1f55ad83 100644 --- a/desktop/history_core.h +++ b/desktop/history_core.h @@ -19,6 +19,7 @@ struct history; struct browser_window; struct history *history_create(void); +struct history *history_clone(struct history *history); void history_add(struct history *history, struct content *content, char *frag_id); void history_update(struct history *history, struct content *content); -- cgit v1.2.3