diff --git a/desktop/browser_history.c b/desktop/browser_history.c index 71fc97493..dbbc67daf 100644 --- a/desktop/browser_history.c +++ b/desktop/browser_history.c @@ -31,56 +31,20 @@ #include "utils/log.h" #include "utils/utils.h" #include "netsurf/layout.h" -#include "netsurf/plotters.h" #include "netsurf/content.h" #include "content/hlcache.h" #include "content/urldb.h" #include "netsurf/bitmap.h" -#include "desktop/system_colour.h" #include "desktop/gui_internal.h" #include "desktop/browser_history.h" #include "desktop/browser_private.h" -#include "desktop/local_history.h" #define WIDTH 100 #define HEIGHT 86 #define RIGHT_MARGIN 50 #define BOTTOM_MARGIN 30 -struct history_page { - nsurl *url; /**< Page URL, never 0. */ - lwc_string *frag_id; /** Fragment identifier, or 0. */ - char *title; /**< Page title, never 0. */ -}; - -/** A node in the history tree. */ -struct history_entry { - struct history_page page; - struct history_entry *back; /**< Parent. */ - struct history_entry *next; /**< Next sibling. */ - struct history_entry *forward; /**< First child. */ - struct history_entry *forward_pref; /**< Child in direction of - current entry. */ - struct history_entry *forward_last; /**< Last child. */ - unsigned int children; /**< Number of children. */ - int x; /**< Position of node. */ - int y; /**< Position of node. */ - struct bitmap *bitmap; /**< Thumbnail bitmap, or 0. */ -}; - -/** History tree for a window. */ -struct history { - /** First page in tree (page that window opened with). */ - struct history_entry *start; - /** Current position in tree. */ - struct history_entry *current; - /** Width of layout. */ - int width; - /** Height of layout. */ - int height; -}; - /** * Clone a history entry @@ -237,188 +201,9 @@ static void browser_window_history__layout(struct history *history) history->height += BOTTOM_MARGIN / 2; } -/** plot style for drawing lines between nodes */ -static plot_style_t pstyle_line = { - .stroke_type = PLOT_OP_TYPE_SOLID, - .stroke_width = 2, -}; - -/** plot style for drawing background */ -static plot_style_t pstyle_bg = { - .fill_type = PLOT_OP_TYPE_SOLID, -}; - -/** plot style for drawing rectangle round unselected nodes */ -static plot_style_t pstyle_rect = { - .stroke_type = PLOT_OP_TYPE_SOLID, - .stroke_width = 1, -}; - -/** plot style for drawing rectangle round selected nodes */ -static plot_style_t pstyle_rect_sel = { - .stroke_type = PLOT_OP_TYPE_SOLID, - .stroke_width = 3, -}; - -/** plot style for font on unselected nodes */ -static plot_font_style_t pfstyle_node = { - .family = PLOT_FONT_FAMILY_SANS_SERIF, - .size = 8 * FONT_SIZE_SCALE, - .weight = 400, - .flags = FONTF_NONE, -}; - -/** plot style for font on unselected nodes */ -static plot_font_style_t pfstyle_node_sel = { - .family = PLOT_FONT_FAMILY_SANS_SERIF, - .size = 8 * FONT_SIZE_SCALE, - .weight = 900, - .flags = FONTF_NONE, -}; - -/** - * Recursively redraw a history_entry. - * - * \param history history containing the entry - * \param entry entry to render - * \param clip redraw area - * \param x window x offset - * \param y window y offset - * \param ctx current redraw context - */ -static bool -browser_window_history__redraw_entry(struct history *history, - struct history_entry *entry, struct rect *clip, - int x, int y, const struct redraw_context *ctx) -{ - size_t char_offset; - int actual_x; - struct history_entry *child; - int tailsize = 5; - - plot_style_t *pstyle; - plot_font_style_t *pfstyle; - struct rect rect; - nserror res; - - /* setup plot styles */ - if (entry == history->current) { - pstyle = &pstyle_rect_sel; - pfstyle = &pfstyle_node_sel; - } else { - pstyle = &pstyle_rect; - pfstyle = &pfstyle_node; - } - - /* Only attempt to plot bitmap if it is present */ - if (entry->bitmap != NULL) { - res = ctx->plot->bitmap(ctx, - entry->bitmap, - entry->x + x, - entry->y + y, - WIDTH, HEIGHT, - 0xffffff, - 0); - if (res != NSERROR_OK) { - return false; - } - } - - rect.x0 = entry->x - 1 + x; - rect.y0 = entry->y - 1 + y; - rect.x1 = entry->x + x + WIDTH; - rect.y1 = entry->y + y + HEIGHT; - res = ctx->plot->rectangle(ctx, pstyle, &rect); - if (res != NSERROR_OK) { - return false; - } - - res = guit->layout->position(plot_style_font, entry->page.title, - strlen(entry->page.title), WIDTH, - &char_offset, &actual_x); - if (res != NSERROR_OK) { - return false; - } - - res = ctx->plot->text(ctx, - pfstyle, - entry->x + x, - entry->y + HEIGHT + 12 + y, - entry->page.title, - char_offset); - if (res != NSERROR_OK) { - return false; - } - - /* for each child node draw a line and recurse redraw into it */ - for (child = entry->forward; child; child = child->next) { - rect.x0 = entry->x + WIDTH + x; - rect.y0 = entry->y + HEIGHT / 2 + y; - rect.x1 = entry->x + WIDTH + tailsize + x; - rect.y1 = entry->y + HEIGHT / 2 + y; - res = ctx->plot->line(ctx, &pstyle_line, &rect); - if (res != NSERROR_OK) { - return false; - } - - rect.x0 = entry->x + WIDTH + tailsize + x; - rect.y0 = entry->y + HEIGHT / 2 + y; - rect.x1 = child->x - tailsize + x; - rect.y1 = child->y + HEIGHT / 2 + y; - res = ctx->plot->line(ctx, &pstyle_line, &rect); - if (res != NSERROR_OK) { - return false; - } - - rect.x0 = child->x - tailsize + x; - rect.y0 = child->y + HEIGHT / 2 + y; - rect.x1 = child->x + x; - rect.y1 = child->y + HEIGHT / 2 + y; - res = ctx->plot->line(ctx, &pstyle_line, &rect); - if (res != NSERROR_OK) { - return false; - } - - if (!browser_window_history__redraw_entry(history, child, - clip, x, y, ctx)) { - return false; - } - } - - return true; -} -/** - * Find the history entry at a position. - * - * \param entry entry to search from - * \param x coordinate - * \param y coordinate - * \return an entry if found, 0 if none - */ -static struct history_entry *browser_window_history__find_position( - struct history_entry *entry, int x, int y) -{ - struct history_entry *child; - struct history_entry *found; - - if (!entry) - return 0; - - if (entry->x <= x && x <= entry->x + WIDTH && - entry->y <= y && y <= entry->y + HEIGHT) - return entry; - - for (child = entry->forward; child; child = child->next) { - found = browser_window_history__find_position(child, x, y); - if (found) - return found; - } - - return 0; -} /** * Enumerate subentries in history @@ -459,29 +244,8 @@ static bool browser_window_history__enumerate_entry( /* exported interface documented in desktop/browser_history.h */ nserror browser_window_history_create(struct browser_window *bw) { - nserror res; struct history *history; - res = ns_system_colour_char("Window", &pstyle_bg.fill_colour); - if (res != NSERROR_OK) { - return res; - } - pfstyle_node.background = pstyle_bg.fill_colour; - pfstyle_node_sel.background = pstyle_bg.fill_colour; - - res = ns_system_colour_char("GrayText", &pstyle_line.stroke_colour); - if (res != NSERROR_OK) { - return res; - } - pstyle_rect.stroke_colour = pstyle_line.stroke_colour; - pfstyle_node.foreground = pstyle_line.stroke_colour; - - res = ns_system_colour_char("Highlight", &pstyle_rect_sel.stroke_colour); - if (res != NSERROR_OK) { - return res; - } - pfstyle_node_sel.foreground = pstyle_rect_sel.stroke_colour; - bw->history = NULL; history = calloc(1, sizeof *history); @@ -749,87 +513,6 @@ nserror browser_window_history_go(struct browser_window *bw, } -/* exported interface documented in desktop/browser_history.h */ -void browser_window_history_size(struct browser_window *bw, - int *width, int *height) -{ - assert(bw != NULL); - assert(bw->history != NULL); - - *width = bw->history->width; - *height = bw->history->height; -} - - -/* exported interface documented in desktop/browser_history.h */ -bool browser_window_history_redraw_rectangle(struct browser_window *bw, - struct rect *clip, int x, int y, - const struct redraw_context *ctx) -{ - struct history *history; - struct rect r = { - .x0 = clip->x0 + x, - .y0 = clip->y0 + y, - .x1 = clip->x1 + x, - .y1 = clip->y1 + y, - }; - - assert(bw != NULL); - history = bw->history; - - if (!history->start) - return true; - - ctx->plot->clip(ctx, &r); - ctx->plot->rectangle(ctx, &pstyle_bg, &r); - - return browser_window_history__redraw_entry( - history, history->start, - clip, x, y, ctx); -} - - -/* exported interface documented in desktop/browser_history.h */ -bool browser_window_history_click(struct browser_window *bw, - int x, int y, bool new_window) -{ - struct history_entry *entry; - struct history *history; - - assert(bw != NULL); - history = bw->history; - - entry = browser_window_history__find_position(history->start, x, y); - if (!entry) - return false; - if (entry == history->current) - return false; - - browser_window_history_go(bw, entry, new_window); - - return true; -} - - -/* exported interface documented in desktop/browser_history.h */ -nsurl *browser_window_history_position_url(struct browser_window *bw, - int x, int y) -{ - struct history_entry *entry; - struct history *history; - - assert(bw != NULL); - history = bw->history; - - entry = browser_window_history__find_position(history->start, x, y); - if (!entry) { - return NULL; - } - - return nsurl_ref(entry->page.url); -} - - /* exported interface documented in desktop/browser_history.h */ void browser_window_history_enumerate_forward(const struct browser_window *bw, browser_window_history_enumerate_cb cb, void *user_data) diff --git a/desktop/browser_private.h b/desktop/browser_private.h index a54393fee..8bbc573eb 100644 --- a/desktop/browser_private.h +++ b/desktop/browser_private.h @@ -35,8 +35,48 @@ struct box; struct hlcache_handle; struct gui_window; -struct history; struct selection; +struct nsurl; + +/** + * history entry page information + */ +struct history_page { + struct nsurl *url; /**< Page URL, never NULL. */ + lwc_string *frag_id; /** Fragment identifier, or NULL. */ + char *title; /**< Page title, never NULL. */ +}; + +/** + * 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 data. @@ -269,6 +309,8 @@ nserror browser_window_history_create(struct browser_window *bw); */ nserror browser_window_history_clone(const struct browser_window *existing, struct browser_window *clone); + + /** * Insert a url into the history tree. * diff --git a/desktop/local_history.c b/desktop/local_history.c index ffe01e091..fe7f4a917 100644 --- a/desktop/local_history.c +++ b/desktop/local_history.c @@ -22,27 +22,249 @@ */ #include +#include #include "utils/errors.h" #include "utils/nsurl.h" #include "netsurf/types.h" +#include "netsurf/layout.h" #include "netsurf/core_window.h" +#include "netsurf/plotters.h" +#include "desktop/gui_internal.h" +#include "desktop/system_colour.h" +#include "desktop/browser_private.h" #include "desktop/browser_history.h" #include "desktop/local_history.h" +#define WIDTH 100 +#define HEIGHT 86 + +/** + * local history viewer context + */ struct local_history_session { struct browser_window *bw; struct core_window_callback_table *cw_t; void *core_window_handle; }; + +/** + * plot style for drawing lines between nodes + */ +static plot_style_t pstyle_line = { + .stroke_type = PLOT_OP_TYPE_SOLID, + .stroke_width = 2, +}; + + +/** + * plot style for drawing background + */ +static plot_style_t pstyle_bg = { + .fill_type = PLOT_OP_TYPE_SOLID, +}; + + +/** + * plot style for drawing rectangle round unselected nodes + */ +static plot_style_t pstyle_rect = { + .stroke_type = PLOT_OP_TYPE_SOLID, + .stroke_width = 1, +}; + + +/** + * plot style for drawing rectangle round selected nodes + */ +static plot_style_t pstyle_rect_sel = { + .stroke_type = PLOT_OP_TYPE_SOLID, + .stroke_width = 3, +}; + + +/** + * plot style for font on unselected nodes + */ +static plot_font_style_t pfstyle_node = { + .family = PLOT_FONT_FAMILY_SANS_SERIF, + .size = 8 * FONT_SIZE_SCALE, + .weight = 400, + .flags = FONTF_NONE, +}; + + +/** + * plot style for font on unselected nodes + */ +static plot_font_style_t pfstyle_node_sel = { + .family = PLOT_FONT_FAMILY_SANS_SERIF, + .size = 8 * FONT_SIZE_SCALE, + .weight = 900, + .flags = FONTF_NONE, +}; + + +/** + * Recursively redraw a history entry. + * + * \param history history containing the entry + * \param entry entry to render + * \param clip redraw area + * \param x window x offset + * \param y window y offset + * \param ctx current redraw context + */ +static nserror +redraw_entry(struct history *history, + struct history_entry *entry, + struct rect *clip, + int x, int y, + const struct redraw_context *ctx) +{ + size_t char_offset; + int actual_x; + struct history_entry *child; + int tailsize = 5; + + plot_style_t *pstyle; + plot_font_style_t *pfstyle; + struct rect rect; + nserror res; + + /* setup plot styles */ + if (entry == history->current) { + pstyle = &pstyle_rect_sel; + pfstyle = &pfstyle_node_sel; + } else { + pstyle = &pstyle_rect; + pfstyle = &pfstyle_node; + } + + /* Only attempt to plot bitmap if it is present */ + if (entry->bitmap != NULL) { + res = ctx->plot->bitmap(ctx, + entry->bitmap, + entry->x + x, + entry->y + y, + WIDTH, HEIGHT, + 0xffffff, + 0); + if (res != NSERROR_OK) { + return res; + } + } + + rect.x0 = entry->x - 1 + x; + rect.y0 = entry->y - 1 + y; + rect.x1 = entry->x + x + WIDTH; + rect.y1 = entry->y + y + HEIGHT; + res = ctx->plot->rectangle(ctx, pstyle, &rect); + if (res != NSERROR_OK) { + return res; + } + + res = guit->layout->position(plot_style_font, entry->page.title, + strlen(entry->page.title), WIDTH, + &char_offset, &actual_x); + if (res != NSERROR_OK) { + return res; + } + + res = ctx->plot->text(ctx, + pfstyle, + entry->x + x, + entry->y + HEIGHT + 12 + y, + entry->page.title, + char_offset); + if (res != NSERROR_OK) { + return res; + } + + /* for each child node draw a line and recurse redraw into it */ + for (child = entry->forward; child; child = child->next) { + rect.x0 = entry->x + WIDTH + x; + rect.y0 = entry->y + HEIGHT / 2 + y; + rect.x1 = entry->x + WIDTH + tailsize + x; + rect.y1 = entry->y + HEIGHT / 2 + y; + res = ctx->plot->line(ctx, &pstyle_line, &rect); + if (res != NSERROR_OK) { + return res; + } + + rect.x0 = entry->x + WIDTH + tailsize + x; + rect.y0 = entry->y + HEIGHT / 2 + y; + rect.x1 = child->x - tailsize + x; + rect.y1 = child->y + HEIGHT / 2 + y; + res = ctx->plot->line(ctx, &pstyle_line, &rect); + if (res != NSERROR_OK) { + return res; + } + + rect.x0 = child->x - tailsize + x; + rect.y0 = child->y + HEIGHT / 2 + y; + rect.x1 = child->x + x; + rect.y1 = child->y + HEIGHT / 2 + y; + res = ctx->plot->line(ctx, &pstyle_line, &rect); + if (res != NSERROR_OK) { + return res; + } + + res = redraw_entry(history, child, clip, x, y, ctx); + if (res != NSERROR_OK) { + return res; + } + } + + return NSERROR_OK; +} + + +/** + * Find the history entry at a position. + * + * \param entry entry to search from + * \param x coordinate + * \param y coordinate + * \return an entry if found, 0 if none + */ +static struct history_entry * +find_entry_position(struct history_entry *entry, int x, int y) +{ + struct history_entry *child; + struct history_entry *found; + + if (!entry) { + return NULL; + } + + 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 = find_entry_position(child, x, y); + if (found) { + return found; + } + } + + return NULL; +} + + /* exported interface documented in desktop/local_history.h */ nserror local_history_init(struct core_window_callback_table *cw_t, void *core_window_handle, struct browser_window *bw, struct local_history_session **session) { + nserror res; struct local_history_session *nses; nses = calloc(1, sizeof(struct local_history_session)); @@ -55,6 +277,27 @@ nserror local_history_init(struct core_window_callback_table *cw_t, local_history_set(nses, bw); + res = ns_system_colour_char("Window", &pstyle_bg.fill_colour); + if (res != NSERROR_OK) { + return res; + } + pfstyle_node.background = pstyle_bg.fill_colour; + pfstyle_node_sel.background = pstyle_bg.fill_colour; + + res = ns_system_colour_char("GrayText", &pstyle_line.stroke_colour); + if (res != NSERROR_OK) { + return res; + } + pstyle_rect.stroke_colour = pstyle_line.stroke_colour; + pfstyle_node.foreground = pstyle_line.stroke_colour; + + res = ns_system_colour_char("Highlight", &pstyle_rect_sel.stroke_colour); + if (res != NSERROR_OK) { + return res; + } + pfstyle_node_sel.foreground = pstyle_rect_sel.stroke_colour; + + *session = nses; return NSERROR_OK; } @@ -76,26 +319,69 @@ local_history_redraw(struct local_history_session *session, struct rect *clip, const struct redraw_context *ctx) { - if (session->bw != NULL) { - browser_window_history_redraw_rectangle(session->bw, - clip, x, y, ctx); + struct rect r = { + .x0 = clip->x0 + x, + .y0 = clip->y0 + y, + .x1 = clip->x1 + x, + .y1 = clip->y1 + y, + }; + + if (session->bw == NULL) { + return NSERROR_OK; } - return NSERROR_OK; + + if (session->bw->history->start == NULL) { + return NSERROR_OK; + } + + ctx->plot->clip(ctx, &r); + ctx->plot->rectangle(ctx, &pstyle_bg, &r); + + return redraw_entry(session->bw->history, + session->bw->history->start, + clip, + x, y, + ctx); } /* exported interface documented in desktop/local_history.h */ -void +nserror local_history_mouse_action(struct local_history_session *session, enum browser_mouse_state mouse, int x, int y) { - if (mouse & BROWSER_MOUSE_PRESS_1) { - browser_window_history_click(session->bw, x, y, false); - } else if (mouse & BROWSER_MOUSE_PRESS_2) { - browser_window_history_click(session->bw, x, y, true); + struct history_entry *entry; + bool new_window; + + if (session->bw == NULL) { + return NSERROR_BAD_PARAMETER; } + if ((mouse & (BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_PRESS_2)) == 0) { + return NSERROR_NOT_IMPLEMENTED; + } + + entry = find_entry_position(session->bw->history->start, x, y); + if (entry == NULL) { + return NSERROR_NOT_FOUND; + } + + if (entry == session->bw->history->current) { + return NSERROR_PERMISSION; + } + + if (mouse & BROWSER_MOUSE_PRESS_1) { + new_window = false; + } else if (mouse & BROWSER_MOUSE_PRESS_2) { + new_window = true; + } else { + new_window = false; + } + + browser_window_history_go(session->bw, entry, new_window); + + return NSERROR_OK; } /* exported interface documented in desktop/local_history.h */ @@ -110,15 +396,13 @@ nserror local_history_set(struct local_history_session *session, struct browser_window *bw) { - int width; - int height; - session->bw = bw; if (bw != NULL) { - browser_window_history_size(session->bw, &width, &height); + assert(session->bw->history != NULL); session->cw_t->update_size(session->core_window_handle, - width, height); + session->bw->history->width, + session->bw->history->height); } return NSERROR_OK; @@ -131,10 +415,8 @@ local_history_get_size(struct local_history_session *session, int *width, int *height) { - - browser_window_history_size(session->bw, width, height); - *width += 20; - *height += 20; + *width = session->bw->history->width + 20; + *height = session->bw->history->height + 20; return NSERROR_OK; } @@ -146,13 +428,18 @@ local_history_get_url(struct local_history_session *session, int x, int y, nsurl **url_out) { - nsurl *url; - url = browser_window_history_position_url(session->bw, x, y); - if (url == NULL) { + struct history_entry *entry; + + if (session->bw == NULL) { + return NSERROR_BAD_PARAMETER; + } + + entry = find_entry_position(session->bw->history->start, x, y); + if (entry == NULL) { return NSERROR_NOT_FOUND; } - *url_out = url; + *url_out = nsurl_ref(entry->page.url); return NSERROR_OK; } diff --git a/desktop/local_history.h b/desktop/local_history.h index 9bfe0f2c1..7f85a633e 100644 --- a/desktop/local_history.h +++ b/desktop/local_history.h @@ -87,8 +87,12 @@ nserror local_history_redraw(struct local_history_session *session, int x, int y * \param[in] mouse The current mouse state * \param[in] x The current mouse X coordinate * \param[in] y The current mouse Y coordinate + * \return NSERROR_OK if mouse action was processed. + * NSERROR_NOT_FOUND if nothing under the pointer where it was clicked + * NSERROR_NOT_IMPLEMENTED if the action was not processed. + * NSERROR_PERMISSION if the clicked item was the current page */ -void local_history_mouse_action(struct local_history_session *session, enum browser_mouse_state mouse, int x, int y); +nserror local_history_mouse_action(struct local_history_session *session, enum browser_mouse_state mouse, int x, int y); /** @@ -137,48 +141,4 @@ nserror local_history_get_size(struct local_history_session *session, int *width nserror local_history_get_url(struct local_history_session *session, int x, int y, struct nsurl **url_out); -/* depricated local history viewing interfaces */ - -/** - * Get the dimensions of a history. - * - * \param bw browser window with history object. - * \param width updated to width - * \param height updated to height - */ -void browser_window_history_size(struct browser_window *bw, int *width, int *height); - -/** - * Redraw part of a history area. - * - * \param bw browser window with history object. - * \param clip redraw area - * \param x start X co-ordinate on plot canvas - * \param y start Y co-ordinate on plot canvas - * \param ctx current redraw context - */ -bool browser_window_history_redraw_rectangle(struct browser_window *bw, struct rect *clip, int x, int y, const struct redraw_context *ctx); - -/** - * Handle a mouse click in a history. - * - * \param bw browser window containing history - * \param x click coordinate - * \param y click coordinate - * \param new_window open a new window instead of using bw - * \return true if action was taken, false if click was not on an entry - */ -bool browser_window_history_click(struct browser_window *bw, int x, int y, bool new_window); - -/** - * Determine the URL of the entry at a position. - * - * \param bw browser window containing history - * \param x x coordinate. - * \param y y coordinate. - * \return nsurl at position or NULL if no entry. - */ -struct nsurl *browser_window_history_position_url(struct browser_window *bw, int x, int y); - - #endif