From 5a72700817565b139e9576738d5b1ec23e23e69e Mon Sep 17 00:00:00 2001 From: James Bursa Date: Sat, 25 Mar 2006 20:30:35 +0000 Subject: [project @ 2006-03-25 20:30:35 by bursa] Split local history into portable and RISC OS specific code. Improve layout of history tree. svn path=/import/netsurf/; revision=2164 --- desktop/browser.c | 3 + desktop/browser.h | 16 +- desktop/history_core.c | 545 ++++++++++++++++++++++++++++++++++++++ desktop/history_core.h | 36 +++ makefile | 6 +- riscos/gui.c | 10 +- riscos/gui.h | 6 +- riscos/history.c | 699 ++++++++++++------------------------------------- riscos/thumbnail.h | 2 - 9 files changed, 767 insertions(+), 556 deletions(-) create mode 100644 desktop/history_core.c create mode 100644 desktop/history_core.h diff --git a/desktop/browser.c b/desktop/browser.c index b709ba289..031089b9d 100644 --- a/desktop/browser.c +++ b/desktop/browser.c @@ -29,6 +29,7 @@ #include "netsurf/desktop/401login.h" #endif #include "netsurf/desktop/browser.h" +#include "netsurf/desktop/history_core.h" #include "netsurf/desktop/gui.h" #include "netsurf/desktop/options.h" #include "netsurf/desktop/selection.h" @@ -173,6 +174,8 @@ void browser_window_go_post(struct browser_window *bw, const char *url, char url_buf[256]; LOG(("bw %p, url %s", bw, url)); + assert(bw); + assert(url); res = url_normalize(url, &url2); if (res != URL_FUNC_OK) { diff --git a/desktop/browser.h b/desktop/browser.h index 67da0abea..642512592 100644 --- a/desktop/browser.h +++ b/desktop/browser.h @@ -3,7 +3,7 @@ * Licensed under the GNU General Public License, * http://www.opensource.org/licenses/gpl-license * Copyright 2003 Phil Mellor - * Copyright 2004 James Bursa + * Copyright 2006 James Bursa */ /** \file @@ -150,22 +150,14 @@ void browser_window_redraw_rect(struct browser_window *bw, int x, int y, /* In platform specific hotlist.c. */ void hotlist_visited(struct content *content); -/* In platform specific history.c. */ -struct history *history_create(void); -void history_add(struct history *history, struct content *content, - char *frag_id); -void history_update(struct history *history, struct content *content); -void history_destroy(struct history *history); -void history_back(struct browser_window *bw, struct history *history); -void history_forward(struct browser_window *bw, struct history *history); -bool history_back_available(struct history *history); -bool history_forward_available(struct history *history); - /* In platform specific global_history.c. */ void global_history_add(struct url_content *data); void global_history_add_recent(const char *url); char **global_history_get_recent(int *count); +/* In platform specific thumbnail.c. */ +bool thumbnail_create(struct content *content, struct bitmap *bitmap, + const char *url); /* In platform specific schedule.c. */ void schedule(int t, void (*callback)(void *p), void *p); diff --git a/desktop/history_core.c b/desktop/history_core.c new file mode 100644 index 000000000..04e02d736 --- /dev/null +++ b/desktop/history_core.c @@ -0,0 +1,545 @@ +/* + * This file is part of NetSurf, http://netsurf.sourceforge.net/ + * Licensed under the GNU General Public License, + * http://www.opensource.org/licenses/gpl-license + * Copyright 2006 James Bursa + * Copyright 2005 Richard Wilson + */ + +/** \file + * Browser history tree (implementation). + */ + +#include +#include +#include +#include +#include +#include "netsurf/content/content.h" +#include "netsurf/content/url_store.h" +#include "netsurf/css/css.h" +#include "netsurf/desktop/gui.h" +#include "netsurf/desktop/history_core.h" +#include "netsurf/desktop/plotters.h" +#include "netsurf/image/bitmap.h" +#include "netsurf/render/font.h" +#include "netsurf/utils/log.h" +#include "netsurf/utils/url.h" +#include "netsurf/utils/utils.h" + + +#define WIDTH 100 +#define HEIGHT 86 +#define RIGHT_MARGIN 50 +#define BOTTOM_MARGIN 30 + + +/** A node in the history tree. */ +struct history_entry { + char *url; /**< Page URL. */ + char *frag_id; /** Fragment identifier */ + char *title; /**< Page title. */ + 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; +}; + +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); +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); +static struct history_entry *history_find_position(struct history_entry *entry, + int x, int y); + + +/** + * Create a new history tree for a window. + * + * \return pointer to an opaque history structure, 0 on failure. + */ + +struct history *history_create(void) +{ + struct history *history; + + history = malloc(sizeof *history); + if (!history) { + warn_user("NoMemory", 0); + return 0; + } + + history->start = 0; + history->current = 0; + + return history; +} + + +/** + * 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 + * + * The page is added after the current entry and becomes current. + */ + +void history_add(struct history *history, struct content *content, + char *frag_id) +{ + url_func_result res; + struct history_entry *entry; + char *url; + char *title; + struct bitmap *bitmap; + + assert(history); + assert(content); + + /* allocate space */ + entry = malloc(sizeof *entry); + res = url_normalize(content->url, &url); + if (res != URL_FUNC_OK) { + warn_user("NoMemory", 0); + return; + } + title = strdup(content->title ? content->title : url); + if (!entry || !url || !title) { + warn_user("NoMemory", 0); + free(entry); + free(url); + free(title); + return; + } + + entry->url = url; + entry->frag_id = frag_id ? strdup(frag_id) : 0; + entry->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 = url_store_get_thumbnail(url); + if (!bitmap) { + bitmap = bitmap_create(WIDTH, HEIGHT, + BITMAP_NEW | BITMAP_CLEAR_MEMORY | + BITMAP_OPAQUE | BITMAP_PERSISTENT); + if (!bitmap) { + warn_user("NoMemory", 0); + return; + } + thumbnail_create(content, bitmap, url); + } + 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, struct content *content) +{ + if (!history || !history->current || !history->current->bitmap) + return; + + thumbnail_create(content, history->current->bitmap, 0); +} + + +/** + * 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); + free(entry->url); + if (entry->frag_id) + free(entry->frag_id); + free(entry->title); + free(entry); +} + + +/** + * Go back in the history. + * + * \param bw browser window + * \param history history of the window + */ + +void history_back(struct browser_window *bw, struct history *history) +{ + if (!history || !history->current || !history->current->back) + return; + history_go(bw, history, history->current->back, false); +} + + +/** + * Go forward in the history. + * + * \param bw browser window + * \param history history of the window + */ + +void history_forward(struct browser_window *bw, struct history *history) +{ + if (!history || !history->current || !history->current->forward_pref) + return; + history_go(bw, history, history->current->forward_pref, false); +} + + +/** + * 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); +} + + +/** + * 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 browser_window *bw, struct history *history, + struct history_entry *entry, bool new_window) +{ + char *url; + + if (entry->frag_id) { + url = malloc(strlen(entry->url) + strlen(entry->frag_id) + 5); + if (!url) { + warn_user("NoMemory", 0); + return; + } + sprintf(url, "%s#%s", entry->url, entry->frag_id); + } + else + url = entry->url; + + if (new_window) + browser_window_create(url, bw, 0); + else { + history->current = entry; + browser_window_go_post(bw, url, 0, 0, false, 0, false); + } + + if (entry->frag_id) + free(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; + + history->width = 0; + history->height = history_layout_subtree(history, history->start, + RIGHT_MARGIN / 2, BOTTOM_MARGIN / 2, shuffle); + 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 + * + * The current plotter is used. + */ + +bool history_redraw(struct history *history) +{ + if (!history->start) + return true; + return history_redraw_entry(history, history->start); +} + + +/** + * Recursively redraw a history_entry. + * + * \param history history containing the entry + * \param history_entry entry to render + */ + +bool history_redraw_entry(struct history *history, + struct history_entry *entry) +{ + size_t char_offset; + int actual_x; + struct history_entry *child; + colour c = entry == history->current ? 0x0000ff : 0x333333; + + if (!plot.bitmap(entry->x, entry->y, WIDTH, HEIGHT, entry->bitmap, + 0xffffff)) + return false; + if (!plot.rectangle(entry->x - 1, entry->y - 1, WIDTH + 1, HEIGHT + 1, + entry == history->current ? 2 : 1, c, false, false)) + return false; + + if (!nsfont_position_in_string(&css_base_style, entry->title, + strlen(entry->title), WIDTH, &char_offset, &actual_x)) + return false; + if (!plot.text(entry->x, entry->y + HEIGHT + 12, &css_base_style, + entry->title, char_offset, 0xffffff, c)) + return false; + + for (child = entry->forward; child; child = child->next) { + if (!plot.line(entry->x + WIDTH, entry->y + HEIGHT / 2, + child->x, child->y + HEIGHT / 2, 1, + 0x333333, false, false)) + return false; + if (!history_redraw_entry(history, child)) + 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 browser_window *bw, 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(bw, 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 entry->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->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; +} diff --git a/desktop/history_core.h b/desktop/history_core.h new file mode 100644 index 000000000..4889ad524 --- /dev/null +++ b/desktop/history_core.h @@ -0,0 +1,36 @@ +/* + * This file is part of NetSurf, http://netsurf.sourceforge.net/ + * Licensed under the GNU General Public License, + * http://www.opensource.org/licenses/gpl-license + * Copyright 2006 James Bursa + */ + +/** \file + * Browser history tree (interface). + */ + +#ifndef _NETSURF_DESKTOP_HISTORY_H_ +#define _NETSURF_DESKTOP_HISTORY_H_ + +#include + +struct content; +struct history; +struct browser_window; + +struct history *history_create(void); +void history_add(struct history *history, struct content *content, + char *frag_id); +void history_update(struct history *history, struct content *content); +void history_destroy(struct history *history); +void history_back(struct browser_window *bw, struct history *history); +void history_forward(struct browser_window *bw, struct history *history); +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); +bool history_click(struct browser_window *bw, struct history *history, + int x, int y, bool new_window); +const char *history_position_url(struct history *history, int x, int y); + +#endif diff --git a/makefile b/makefile index 6eb320e07..e13f0b501 100644 --- a/makefile +++ b/makefile @@ -31,8 +31,8 @@ OBJECTS_IMAGE = bmp.o bmpread.o gif.o gifread.o ico.o jpeg.o \ mng.o # image/ OBJECTS_RISCOS = $(OBJECTS_COMMON) $(OBJECTS_IMAGE) -OBJECTS_RISCOS += browser.o netsurf.o selection.o textinput.o \ - version.o # desktop/ +OBJECTS_RISCOS += browser.o history_core.o netsurf.o selection.o \ + textinput.o version.o # desktop/ OBJECTS_RISCOS += 401login.o artworks.o assert.o awrender.o bitmap.o \ buffer.o configure.o debugwin.o \ dialog.o download.o draw.o filename.o filetype.o font.o \ @@ -62,7 +62,7 @@ OBJECTS_DEBUGRO += artworks.o bitmap.o draw.o filetype.o font.o \ OBJECTS_GTK = $(OBJECTS_COMMON) $(OBJECTS_IMAGE) OBJECTS_GTK += filetyped.o # debug/ -OBJECTS_GTK += browser.o netsurf.o selection.o textinput.o \ +OBJECTS_GTK += browser.o history_core.o netsurf.o selection.o textinput.o \ version.o # desktop/ OBJECTS_GTK += font_pango.o gtk_bitmap.o gtk_gui.o \ gtk_schedule.o \ diff --git a/riscos/gui.c b/riscos/gui.c index d01ee6dfb..b5b7564dd 100644 --- a/riscos/gui.c +++ b/riscos/gui.c @@ -536,7 +536,7 @@ void ro_gui_choose_language(void) free(option_language); option_language = 0; } - + option_language = strdup(ro_gui_default_language()); assert(option_language); option_accept_language = strdup(option_language); @@ -721,7 +721,6 @@ void gui_quit(void) ro_gui_window_quit(); ro_gui_global_history_save(); ro_gui_hotlist_save(); - ro_gui_history_quit(); ro_gui_saveas_quit(); rufl_quit(); free(gui_sprites); @@ -1095,7 +1094,7 @@ void ro_gui_close_window_request(wimp_close *close) } free(filename); } else { - /* todo: go 'up' */ + /* todo: go 'up' */ } } if (ro_gui_shift_pressed()) @@ -1304,7 +1303,7 @@ void ro_gui_user_message(wimp_event_no event, wimp_message *message) /* attempt automatic routing */ if (ro_message_handle_message(event, message)) return; - + switch (message->action) { case message_DATA_LOAD: ro_msg_terminate_filename((wimp_full_message_data_xfer*)message); @@ -1337,7 +1336,6 @@ void ro_gui_user_message(wimp_event_no event, wimp_message *message) case message_MODE_CHANGE: ro_gui_get_screen_properties(); - ro_gui_history_mode_change(); rufl_invalidate_cache(); break; @@ -2146,7 +2144,7 @@ void ro_gui_view_source(struct content *content) warn_user("MiscError", "No document source"); return; } - + /* try to load local files directly. */ temp_name = url_to_path(content->url); if (temp_name) { diff --git a/riscos/gui.h b/riscos/gui.h index 7eb55b746..c33ced343 100644 --- a/riscos/gui.h +++ b/riscos/gui.h @@ -147,8 +147,6 @@ struct gui_window *ro_gui_toolbar_lookup(wimp_w window); struct gui_window *ro_gui_status_lookup(wimp_w window); bool ro_gui_window_keypress(struct gui_window *g, int key, bool toolbar); void ro_gui_scroll_request(wimp_scroll *scroll); -//#define window_x_units(x, state) (x - (state->visible.x0 - state->xscroll)) -//#define window_y_units(y, state) (y - (state->visible.y1 - state->yscroll)) int window_x_units(int x, wimp_window_state *state); int window_y_units(int y, wimp_window_state *state); bool window_screen_pos(struct gui_window *g, int x, int y, os_coord *pos); @@ -167,8 +165,6 @@ void ro_gui_window_iconise(struct gui_window *g, wimp_full_message_window_info * /* in history.c */ void ro_gui_history_init(void); -void ro_gui_history_quit(void); -void ro_gui_history_mode_change(void); void ro_gui_history_open(struct browser_window *bw, struct history *history, bool pointer); void ro_gui_history_mouse_at(wimp_pointer *pointer); @@ -220,7 +216,7 @@ void ro_plot_set_scale(float scale); /* in theme_install.c */ bool ro_gui_theme_install_apply(wimp_w w); -/* icon numbers for toolbar status window */ +/* icon numbers */ #define ICON_STATUS_RESIZE 0 #define ICON_STATUS_TEXT 1 diff --git a/riscos/history.c b/riscos/history.c index 8b9beaa12..ce8d5a75d 100644 --- a/riscos/history.c +++ b/riscos/history.c @@ -2,246 +2,43 @@ * This file is part of NetSurf, http://netsurf.sourceforge.net/ * Licensed under the GNU General Public License, * http://www.opensource.org/licenses/gpl-license - * Copyright 2004 James Bursa + * Copyright 2006 James Bursa * Copyright 2005 Richard Wilson */ /** \file - * Browser history tree and window (implementation). + * Browser history window (RISC OS implementation). + * + * There is only one history window, not one per browser window. */ #include #include #include -#include -#include "oslib/colourtrans.h" -#include "oslib/font.h" #include "oslib/wimp.h" -#include "netsurf/content/url_store.h" -#include "netsurf/image/bitmap.h" -#include "netsurf/riscos/bitmap.h" +#include "netsurf/desktop/history_core.h" +#include "netsurf/desktop/plotters.h" #include "netsurf/riscos/dialog.h" -#include "netsurf/riscos/image.h" #include "netsurf/riscos/options.h" #include "netsurf/riscos/gui.h" -#include "netsurf/riscos/thumbnail.h" -#include "netsurf/riscos/tinct.h" #include "netsurf/riscos/wimp.h" #include "netsurf/riscos/wimp_event.h" #include "netsurf/utils/log.h" #include "netsurf/utils/url.h" #include "netsurf/utils/utils.h" -#define SIZE 10 -#define WIDTH (THUMBNAIL_WIDTH << 1) -#define HEIGHT (THUMBNAIL_HEIGHT << 1) -#define MARGIN 32 -#define FULL_WIDTH (WIDTH + MARGIN + MARGIN) -#define FULL_HEIGHT (HEIGHT + MARGIN + MARGIN) - -/** A node in the history tree. */ -struct history_entry { - char *url; /**< Page URL. */ - char *frag_id; /** Fragment identifier */ - char *title; /**< Page title. */ - 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, y, width; - 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; -}; static struct browser_window *history_bw; static struct history *history_current = 0; -/* Position of mouse in window */ -static int mouse_x = 0, mouse_y = 0; +/* Last position of mouse in window. */ +static int mouse_x = 0; +/* Last position of mouse in window. */ +static int mouse_y = 0; wimp_w history_window; -font_f history_font; - -static void history_free_entry(struct history_entry *entry); -static void ro_gui_history_redraw_tree(struct history_entry *he, - int x0, int y0); -static struct history_entry * ro_gui_history_click_find( - struct history_entry *he, - int x, int y); -static void history_go(struct browser_window *bw, - struct history_entry *entry, bool new_window); + static void ro_gui_history_redraw(wimp_draw *redraw); static bool ro_gui_history_click(wimp_pointer *pointer); -/** - * Create a new history tree for a window. - * - * \return pointer to an opaque history structure, 0 on failure. - */ - -struct history *history_create(void) -{ - struct history *history; - - history = malloc(sizeof *history); - if (!history) { - warn_user("NoMemory", 0); - return 0; - } - - history->start = 0; - history->current = 0; - - return history; -} - - -/** - * 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 - * - * The page is added after the current entry and becomes current. - */ - -void history_add(struct history *history, struct content *content, char *frag_id) -{ - url_func_result res; - struct history_entry *entry; - char *url; - char *title; - char *split; - int width; - struct bitmap *bitmap; - - if (!history) - return; - - /* allocate space */ - entry = malloc(sizeof *entry); - res = url_normalize(content->url, &url); - if (res != URL_FUNC_OK) { - warn_user("NoMemory", 0); - return; - } - title = strdup(content->title ? content->title : url); - if (!entry || !url || !title) { - warn_user("NoMemory", 0); - free(entry); - free(url); - free(title); - return; - } - - /* truncate title to available width */ - font_scan_string(history_font, title, font_GIVEN_FONT | font_KERN, - WIDTH * 400, 0x7fffffff, - 0, 0, 0, &split, &width, 0, 0); - if (title[split - title]) { - title[split - title - 2] = 0x8c; /* ellipsis */ - title[split - title - 1] = 0; - } - - entry->url = url; - entry->frag_id = frag_id ? strdup(frag_id) : 0; - entry->title = title; - entry->back = history->current; - entry->next = 0; - entry->forward = entry->forward_pref = entry->forward_last = 0; - entry->children = 0; - entry->width = width / 400; - 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 = url_store_get_thumbnail(url); - if (!bitmap) { - bitmap = bitmap_create(WIDTH / 2, HEIGHT / 2, - BITMAP_NEW | BITMAP_CLEAR_MEMORY | - BITMAP_OPAQUE | BITMAP_PERSISTENT); - if (!bitmap) { - LOG(("Thumbnail initialisation failed.")); - return; - } - thumbnail_create(content, bitmap, url); - } - entry->bitmap = bitmap; -} - - -/** - * 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, struct content *content) -{ - if (!history || !history->current || !history->current->bitmap) - return; - - 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; - if (history_current == history) { - wimp_close_window(history_window); - history_current = 0; - } - 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); - free(entry->url); - if (entry->frag_id) - free(entry->frag_id); - free(entry->title); - free(entry); -} /** @@ -251,7 +48,6 @@ void history_free_entry(struct history_entry *entry) void ro_gui_history_init(void) { history_window = ro_gui_dialog_create("history"); - history_font = font_find_font("Homerton.Medium", 112, 128, 0, 0, 0, 0); ro_gui_wimp_event_register_redraw_window(history_window, ro_gui_history_redraw); ro_gui_wimp_event_register_mouse_click(history_window, @@ -260,106 +56,64 @@ void ro_gui_history_init(void) } -/** - * Free history window resources. - */ - -void ro_gui_history_quit(void) -{ - font_lose_font(history_font); -} - - -/** - * Update resources folowing a mode change - */ -void ro_gui_history_mode_change(void) -{ - font_lose_font(history_font); - history_font = font_find_font("Homerton.Medium", 112, 128, 0, 0, 0, 0); -} - /** * Open history window. * - * \param pointer whether to open the window at the pointer + * \param bw browser window to open history for + * \param history history to open + * \param at_pointer open the window at the pointer */ void ro_gui_history_open(struct browser_window *bw, - struct history *history, bool pointer) + struct history *history, bool at_pointer) { - bool done = false; - unsigned int i, j, max_y = 0; - int x; int width, height; - struct history_entry *row[SIZE], *row2[SIZE]; - struct history_entry *he; os_box box = {0, 0, 0, 0}; wimp_window_state state; + os_error *error; - if (!history || !history->start) - return; - - history_bw = bw; history_current = history; + history_bw = bw; - /* calculate layout */ - for (i = 0; i != SIZE; i++) - row[i] = row2[i] = 0; - row[0] = history->start; - history->start->x = 0; - history->start->y = 0; - for (x = 1; !done; x++) { - for (i = 0; i != SIZE; i++) { - if (row[i]) { - for (j = i; j != SIZE && row2[j]; j++) - ; - if (j == SIZE) { - if (row[i]->forward) - row[i]->forward->x = -1; - break; - } - for (he = row[i]->forward; he; he = he->next) { - row2[j++] = he; - if (j == SIZE) { - if (he->next) - he->next->x = -1; - break; - } - } - if (j == SIZE) - break; - } - } - done = true; - for (i = 0; i != SIZE; i++) { - row[i] = row2[i]; - if (row[i]) { - row[i]->x = x; - row[i]->y = i; - if (max_y < i) - max_y = i; - done = false; - } - row2[i] = 0; - } - } - - width = FULL_WIDTH * (x - 1); - height = FULL_HEIGHT * (max_y + 1); + history_size(history, &width, &height); + width *= 2; + height *= 2; + /* set extent */ box.x1 = width; box.y0 = -height; - wimp_set_extent(history_window, &box); + error = xwimp_set_extent(history_window, &box); + if (error) { + LOG(("xwimp_set_extent: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return; + } + + /* open full size */ state.w = history_window; - wimp_get_window_state(&state); + error = xwimp_get_window_state(&state); + if (error) { + LOG(("xwimp_get_window_state: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return; + } state.visible.x0 = 0; state.visible.y0 = 0; state.visible.x1 = width; state.visible.y1 = height; state.next = wimp_HIDDEN; - wimp_open_window((wimp_open *) &state); - ro_gui_dialog_open_persistent(bw->window->window, history_window, pointer); + error = xwimp_open_window((wimp_open *) &state); + if (error) { + LOG(("xwimp_open_window: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return; + } + + ro_gui_dialog_open_persistent(bw->window->window, history_window, + at_pointer); } @@ -370,98 +124,46 @@ void ro_gui_history_open(struct browser_window *bw, void ro_gui_history_redraw(wimp_draw *redraw) { osbool more; + os_error *error; - more = wimp_redraw_window(redraw); + plot = ro_plotters; + ro_plot_set_scale(1.0); - while (more) { - ro_gui_history_redraw_tree(history_current->start, - redraw->box.x0 - redraw->xscroll, - redraw->box.y1 - redraw->yscroll); - more = wimp_get_rectangle(redraw); + error = xwimp_redraw_window(redraw, &more); + if (error) { + LOG(("xwimp_redraw_window: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return; } -} - - -/** - * Redraw history tree recursively. - */ - -void ro_gui_history_redraw_tree(struct history_entry *he, - int x0, int y0) -{ - struct history_entry *c; - -/* os_plot(os_MOVE_TO, x0 + he->x * FULL_WIDTH + MARGIN, - y0 - he->y * FULL_HEIGHT - MARGIN); - os_plot(os_PLOT_RECTANGLE | os_PLOT_BY, WIDTH, -HEIGHT);*/ - - if (he == history_current->current) - colourtrans_set_gcol(os_COLOUR_RED, 0, os_ACTION_OVERWRITE, 0); - else - colourtrans_set_gcol(os_COLOUR_MID_DARK_GREY, 0, - os_ACTION_OVERWRITE, 0); - - os_plot(os_MOVE_TO, x0 + he->x * FULL_WIDTH + MARGIN - 1, - y0 - he->y * FULL_HEIGHT - MARGIN); - os_plot(os_PLOT_SOLID | os_PLOT_BY, WIDTH + 1, 0); - os_plot(os_PLOT_SOLID | os_PLOT_BY, 0, -HEIGHT - 1); - os_plot(os_PLOT_SOLID | os_PLOT_BY, -WIDTH - 1, 0); - os_plot(os_PLOT_SOLID | os_PLOT_BY, 0, HEIGHT + 1); - - if (he->bitmap) { - if (bitmap_get_buffer(he->bitmap)) { - image_redraw(he->bitmap->sprite_area, - x0 + he->x * FULL_WIDTH + MARGIN, - y0 - he->y * FULL_HEIGHT - MARGIN, - he->bitmap->width, he->bitmap->height, - he->bitmap->width, he->bitmap->height, - 0xffffff, - false, false, false, - IMAGE_PLOT_TINCT_OPAQUE); - } else { - url_store_add_thumbnail(he->url, NULL); - he->bitmap = NULL; - + while (more) { + ro_plot_origin_x = redraw->box.x0 - redraw->xscroll; + ro_plot_origin_y = redraw->box.y1 - redraw->yscroll; + history_redraw(history_current); + error = xwimp_get_rectangle(redraw, &more); + if (error) { + LOG(("xwimp_get_rectangle: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return; } } - - if (he == history_current->current) - wimp_set_font_colours(wimp_COLOUR_WHITE, wimp_COLOUR_RED); - else - wimp_set_font_colours(wimp_COLOUR_WHITE, wimp_COLOUR_BLACK); - - xfont_paint(history_font, he->title, - font_OS_UNITS | font_GIVEN_FONT | font_KERN, - x0 + he->x * FULL_WIDTH + (FULL_WIDTH - he->width) / 2, - y0 - he->y * FULL_HEIGHT - HEIGHT - MARGIN - 24, - NULL, NULL, 0); - - colourtrans_set_gcol(os_COLOUR_MID_DARK_GREY, 0, - os_ACTION_OVERWRITE, 0); - - for (c = he->forward; c; c = c->next) { - if (c->x == -1) - continue; - os_plot(os_MOVE_TO, x0 + c->x * FULL_WIDTH - MARGIN, - y0 - he->y * FULL_HEIGHT - FULL_HEIGHT / 2); - os_plot(os_PLOT_SOLID | os_PLOT_TO, - x0 + c->x * FULL_WIDTH + MARGIN, - y0 - c->y * FULL_HEIGHT - FULL_HEIGHT / 2); - ro_gui_history_redraw_tree(c, x0, y0); - } } + /** * Handle mouse movements over the history window. */ + void ro_gui_history_mouse_at(wimp_pointer *pointer) { int x, y; long width; - struct history_entry *he; + const char *url; wimp_window_state state; wimp_icon_state ic; os_box box = {0, 0, 0, 0}; + os_error *error; /* If the mouse hasn't moved, or if we don't want tooltips, exit */ if ((mouse_x == pointer->pos.x && mouse_y == pointer->pos.y) || @@ -474,188 +176,129 @@ void ro_gui_history_mouse_at(wimp_pointer *pointer) /* Find history tree entry under mouse */ state.w = history_window; - wimp_get_window_state(&state); - - x = (pointer->pos.x - (state.visible.x0 - state.xscroll)) / FULL_WIDTH; - y = -(pointer->pos.y - (state.visible.y1 - state.yscroll)) / FULL_HEIGHT; - he = ro_gui_history_click_find(history_current->start, x, y); - if (he) { - /* get width of string */ - xwimptextop_string_width(he->url, - strlen(he->url) > 256 ? 256 : strlen(he->url), - (int*)&width); - - ro_gui_set_icon_string(dialog_tooltip, 0, he->url); - - /* resize icon appropriately */ - ic.w = dialog_tooltip; - ic.i = 0; - wimp_get_icon_state(&ic); - wimp_resize_icon(dialog_tooltip, 0, - ic.icon.extent.x0, ic.icon.extent.y0, - width + 16, ic.icon.extent.y1); - - state.w = dialog_tooltip; - wimp_get_window_state(&state); - - /* update window extent */ - box.x1 = width + 16; - box.y0 = -36; - xwimp_set_extent(dialog_tooltip, &box); - - /* set visible area */ - state.visible.x0 = pointer->pos.x + 24; - state.visible.y0 = pointer->pos.y - 22 - 36; - state.visible.x1 = pointer->pos.x + 24 + width + 16; - state.visible.y1 = pointer->pos.y - 22; - state.next = wimp_TOP; - /* open window */ - wimp_open_window((wimp_open *) &state); - } - else { - /* not over a tree entry => close tooltip window. */ - wimp_close_window(dialog_tooltip); + error = xwimp_get_window_state(&state); + if (error) { + LOG(("xwimp_get_window_state: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return; } -} - -/** - * Handle mouse clicks in the history window. - * - * \return true if the event was handled, false to pass it on - */ -bool ro_gui_history_click(wimp_pointer *pointer) -{ - int x, y; - struct history_entry *he; - wimp_window_state state; - - if (pointer->buttons != wimp_CLICK_SELECT && - pointer->buttons != wimp_CLICK_ADJUST) - /* return if not select or adjust click */ - return true; - - state.w = history_window; - wimp_get_window_state(&state); - - x = (pointer->pos.x - (state.visible.x0 - state.xscroll)) / FULL_WIDTH; - y = -(pointer->pos.y - (state.visible.y1 - state.yscroll)) / FULL_HEIGHT; - he = ro_gui_history_click_find(history_current->start, x, y); - if (he) { - if (pointer->buttons == wimp_CLICK_SELECT) - history_current->current = he; - wimp_close_window(history_window); - history_current = 0; - history_go(history_bw, he, - pointer->buttons == wimp_CLICK_ADJUST); + x = (pointer->pos.x - (state.visible.x0 - state.xscroll)) / 2; + y = -(pointer->pos.y - (state.visible.y1 - state.yscroll)) / 2; + url = history_position_url(history_current, x, y); + if (!url) { + /* not over a tree entry => close tooltip window. */ + error = xwimp_close_window(dialog_tooltip); + if (error) { + LOG(("xwimp_close_window: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return; + } + return; } - return true; -} - -/** - * Search for an entry with the specified coordinates. - */ - -struct history_entry * ro_gui_history_click_find(struct history_entry *he, - int x, int y) -{ - struct history_entry *c, *d; - if (he->x == x && he->y == y) - return he; - for (c = he->forward; c; c = c->next) { - d = ro_gui_history_click_find(c, x, y); - if (d) - return d; + /* get width of string */ + error = xwimptextop_string_width(url, + strlen(url) > 256 ? 256 : strlen(url), + (int *) &width); + if (error) { + LOG(("xwimptextop_string_width: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return; } - return 0; -} + ro_gui_set_icon_string(dialog_tooltip, 0, url); -/** - * Go back in the history. - * - * \param bw browser window - * \param history history of the window - */ - -void history_back(struct browser_window *bw, struct history *history) -{ - if (!history || !history->current || !history->current->back) + /* resize icon appropriately */ + ic.w = dialog_tooltip; + ic.i = 0; + error = xwimp_get_icon_state(&ic); + if (error) { + LOG(("xwimp_get_icon_state: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); return; - history->current = history->current->back; - history_go(bw, history->current, false); -} - - -/** - * Go forward in the history. - * - * \param bw browser window - * \param history history of the window - */ - -void history_forward(struct browser_window *bw, struct history *history) -{ - if (!history || !history->current || !history->current->forward_pref) + } + error = xwimp_resize_icon(dialog_tooltip, 0, + ic.icon.extent.x0, ic.icon.extent.y0, + width + 16, ic.icon.extent.y1); + if (error) { + LOG(("xwimp_resize_icon: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); return; - history->current = history->current->forward_pref; - history_go(bw, history->current, false); -} + } + state.w = dialog_tooltip; + error = xwimp_get_window_state(&state); + if (error) { + LOG(("xwimp_get_window_state: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return; + } -/** - * 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 - */ + /* update window extent */ + box.x1 = width + 16; + box.y0 = -36; + error = xwimp_set_extent(dialog_tooltip, &box); + if (error) { + LOG(("xwimp_set_extent: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return; + } -bool history_back_available(struct history *history) { - return (history && history->current && history->current->back); + /* set visible area */ + state.visible.x0 = pointer->pos.x + 24; + state.visible.y0 = pointer->pos.y - 22 - 36; + state.visible.x1 = pointer->pos.x + 24 + width + 16; + state.visible.y1 = pointer->pos.y - 22; + state.next = wimp_TOP; + /* open window */ + error = xwimp_open_window((wimp_open *) &state); + if (error) { + LOG(("xwimp_open_window: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return; + } } /** - * Check whether it is pssible to go forwards in the history. + * Handle mouse clicks in the history window. * - * \param history history of the window - * \return true if the history can go forwards, false otherwise + * \return true if the event was handled, false to pass it on */ -bool history_forward_available(struct history *history) { - return (history && history->current && history->current->forward_pref); -} - -/** - * Open a history entry in the specified browser window - * - * \param bw browser window - * \param entry entry to open - * \param new_window open entry in new window - */ -void history_go(struct browser_window *bw, struct history_entry *entry, - bool new_window) +bool ro_gui_history_click(wimp_pointer *pointer) { - char *url; + int x, y; + wimp_window_state state; + os_error *error; - if (entry->frag_id) { - url = calloc(strlen(entry->url) + strlen(entry->frag_id) + 5, - sizeof(char)); - if (!url) { - warn_user("NoMemory", 0); - return; - } - sprintf(url, "%s#%s", entry->url, entry->frag_id); + if (pointer->buttons != wimp_CLICK_SELECT && + pointer->buttons != wimp_CLICK_ADJUST) + /* return if not select or adjust click */ + return true; + + state.w = history_window; + error = xwimp_get_window_state(&state); + if (error) { + LOG(("xwimp_get_window_state: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return true; } - else - url = entry->url; - if (new_window) - browser_window_create(url, bw, 0); - else - browser_window_go_post(bw, url, 0, 0, false, 0, false); + x = (pointer->pos.x - (state.visible.x0 - state.xscroll)) / 2; + y = -(pointer->pos.y - (state.visible.y1 - state.yscroll)) / 2; + history_click(history_bw, history_current, x, y, + pointer->buttons == wimp_CLICK_ADJUST); - if (entry->frag_id) - free(url); + return true; } diff --git a/riscos/thumbnail.h b/riscos/thumbnail.h index 6943f2bbb..da0528383 100644 --- a/riscos/thumbnail.h +++ b/riscos/thumbnail.h @@ -13,6 +13,4 @@ #include "oslib/osspriteop.h" #include "netsurf/image/bitmap.h" -bool thumbnail_create(struct content *content, struct bitmap *bitmap, - const char *url); osspriteop_area *thumbnail_convert_8bpp(struct bitmap *bitmap); -- cgit v1.2.3