summaryrefslogtreecommitdiff
path: root/desktop/local_history.c
diff options
context:
space:
mode:
Diffstat (limited to 'desktop/local_history.c')
-rw-r--r--desktop/local_history.c258
1 files changed, 207 insertions, 51 deletions
diff --git a/desktop/local_history.c b/desktop/local_history.c
index 3219de90c..5227c97e1 100644
--- a/desktop/local_history.c
+++ b/desktop/local_history.c
@@ -24,22 +24,26 @@
#include <stdlib.h>
#include <string.h>
-#include "utils/errors.h"
#include "utils/nsurl.h"
+#include "utils/errors.h"
+
#include "netsurf/types.h"
#include "netsurf/layout.h"
+#include "netsurf/browser_window.h"
#include "netsurf/core_window.h"
#include "netsurf/plotters.h"
+#include "netsurf/keypress.h"
+
+#include "utils/nscolour.h"
+#include "desktop/cw_helper.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_private.h"
#include "desktop/local_history.h"
-#define WIDTH 100
-#define HEIGHT 86
-
/**
* local history viewer context
*/
@@ -47,6 +51,7 @@ struct local_history_session {
struct browser_window *bw;
struct core_window_callback_table *cw_t;
void *core_window_handle;
+ struct history_entry *cursor;
};
@@ -55,7 +60,7 @@ struct local_history_session {
*/
static plot_style_t pstyle_line = {
.stroke_type = PLOT_OP_TYPE_SOLID,
- .stroke_width = 2,
+ .stroke_width = plot_style_int_to_fixed(2),
};
@@ -72,7 +77,7 @@ static plot_style_t pstyle_bg = {
*/
static plot_style_t pstyle_rect = {
.stroke_type = PLOT_OP_TYPE_SOLID,
- .stroke_width = 1,
+ .stroke_width = plot_style_int_to_fixed(1),
};
@@ -81,7 +86,16 @@ static plot_style_t pstyle_rect = {
*/
static plot_style_t pstyle_rect_sel = {
.stroke_type = PLOT_OP_TYPE_SOLID,
- .stroke_width = 3,
+ .stroke_width = plot_style_int_to_fixed(3),
+};
+
+
+/**
+ * plot style for drawing rectangle round the cursor node
+ */
+static plot_style_t pstyle_rect_cursor = {
+ .stroke_type = PLOT_OP_TYPE_DASH,
+ .stroke_width = plot_style_int_to_fixed(3),
};
@@ -90,7 +104,7 @@ static plot_style_t pstyle_rect_sel = {
*/
static plot_font_style_t pfstyle_node = {
.family = PLOT_FONT_FAMILY_SANS_SERIF,
- .size = 8 * FONT_SIZE_SCALE,
+ .size = 8 * PLOT_STYLE_SCALE,
.weight = 400,
.flags = FONTF_NONE,
};
@@ -101,7 +115,7 @@ static plot_font_style_t pfstyle_node = {
*/
static plot_font_style_t pfstyle_node_sel = {
.family = PLOT_FONT_FAMILY_SANS_SERIF,
- .size = 8 * FONT_SIZE_SCALE,
+ .size = 8 * PLOT_STYLE_SCALE,
.weight = 900,
.flags = FONTF_NONE,
};
@@ -120,6 +134,7 @@ static plot_font_style_t pfstyle_node_sel = {
static nserror
redraw_entry(struct history *history,
struct history_entry *entry,
+ struct history_entry *cursor,
struct rect *clip,
int x, int y,
const struct redraw_context *ctx)
@@ -149,7 +164,8 @@ redraw_entry(struct history *history,
entry->page.bitmap,
entry->x + x,
entry->y + y,
- WIDTH, HEIGHT,
+ LOCAL_HISTORY_WIDTH,
+ LOCAL_HISTORY_HEIGHT,
0xffffff,
0);
if (res != NSERROR_OK) {
@@ -159,15 +175,27 @@ redraw_entry(struct history *history,
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;
+ rect.x1 = entry->x + x + LOCAL_HISTORY_WIDTH;
+ rect.y1 = entry->y + y + LOCAL_HISTORY_HEIGHT;
+
+ /* Border */
+ if (entry != cursor) {
+ /* Not cursor position */
+ res = ctx->plot->rectangle(ctx, pstyle, &rect);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+ } else {
+ /* Cursor position */
+ rect.x0 -= 1;
+ rect.y0 -= 1;
+ rect.x1 += 1;
+ rect.y1 += 1;
+ ctx->plot->rectangle(ctx, &pstyle_rect_cursor, &rect);
}
res = guit->layout->position(plot_style_font, entry->page.title,
- strlen(entry->page.title), WIDTH,
+ strlen(entry->page.title), LOCAL_HISTORY_WIDTH,
&char_offset, &actual_x);
if (res != NSERROR_OK) {
return res;
@@ -176,7 +204,7 @@ redraw_entry(struct history *history,
res = ctx->plot->text(ctx,
pfstyle,
entry->x + x,
- entry->y + HEIGHT + 12 + y,
+ entry->y + LOCAL_HISTORY_HEIGHT + 12 + y,
entry->page.title,
char_offset);
if (res != NSERROR_OK) {
@@ -185,34 +213,34 @@ redraw_entry(struct history *history,
/* 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;
+ rect.x0 = entry->x + LOCAL_HISTORY_WIDTH + x;
+ rect.y0 = entry->y + LOCAL_HISTORY_HEIGHT / 2 + y;
+ rect.x1 = entry->x + LOCAL_HISTORY_WIDTH + tailsize + x;
+ rect.y1 = entry->y + LOCAL_HISTORY_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.x0 = entry->x + LOCAL_HISTORY_WIDTH + tailsize + x;
+ rect.y0 = entry->y + LOCAL_HISTORY_HEIGHT / 2 + y;
rect.x1 = child->x - tailsize + x;
- rect.y1 = child->y + HEIGHT / 2 + y;
+ rect.y1 = child->y + LOCAL_HISTORY_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.y0 = child->y + LOCAL_HISTORY_HEIGHT / 2 + y;
rect.x1 = child->x + x;
- rect.y1 = child->y + HEIGHT / 2 + y;
+ rect.y1 = child->y + LOCAL_HISTORY_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);
+ res = redraw_entry(history, child, cursor, clip, x, y, ctx);
if (res != NSERROR_OK) {
return res;
}
@@ -241,9 +269,9 @@ find_entry_position(struct history_entry *entry, int x, int y)
}
if ((entry->x <= x) &&
- (x <= entry->x + WIDTH) &&
+ (x <= entry->x + LOCAL_HISTORY_WIDTH) &&
(entry->y <= y) &&
- (y <= entry->y + HEIGHT)) {
+ (y <= entry->y + LOCAL_HISTORY_HEIGHT)) {
return entry;
}
@@ -257,6 +285,27 @@ find_entry_position(struct history_entry *entry, int x, int y)
return NULL;
}
+/* exported interface documented in desktop/local_history.h */
+nserror
+local_history_scroll_to_cursor(struct local_history_session *session)
+{
+ rect cursor;
+
+ if (session->cursor == NULL) {
+ return NSERROR_OK;
+ }
+
+ cursor.x0 = session->cursor->x - LOCAL_HISTORY_RIGHT_MARGIN / 2;
+ cursor.y0 = session->cursor->y - LOCAL_HISTORY_BOTTOM_MARGIN / 2;
+ cursor.x1 = cursor.x0 + LOCAL_HISTORY_WIDTH +
+ LOCAL_HISTORY_RIGHT_MARGIN / 2;
+ cursor.y1 = cursor.y0 + LOCAL_HISTORY_HEIGHT +
+ LOCAL_HISTORY_BOTTOM_MARGIN / 2;
+
+ return cw_helper_scroll_visible(session->cw_t,
+ session->core_window_handle,
+ &cursor);
+}
/* exported interface documented in desktop/local_history.h */
nserror
@@ -265,28 +314,19 @@ local_history_init(struct core_window_callback_table *cw_t,
struct browser_window *bw,
struct local_history_session **session)
{
- nserror res;
struct local_history_session *nses;
- 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;
+ pstyle_bg.fill_colour = nscolours[NSCOLOUR_WIN_EVEN_BG];
+ pstyle_line.stroke_colour = nscolours[NSCOLOUR_WIN_EVEN_BORDER];
- 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;
+ pstyle_rect_sel.stroke_colour = nscolours[NSCOLOUR_WIN_EVEN_BORDER];
+ pstyle_rect_cursor.stroke_colour = nscolours[NSCOLOUR_SEL_BG];
- 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;
+ pfstyle_node.foreground = nscolours[NSCOLOUR_WIN_EVEN_FG];
+ pfstyle_node.background = nscolours[NSCOLOUR_WIN_EVEN_BG];
+ pfstyle_node_sel.foreground = nscolours[NSCOLOUR_WIN_EVEN_FG];
+ pfstyle_node_sel.background = nscolours[NSCOLOUR_WIN_EVEN_BG];
nses = calloc(1, sizeof(struct local_history_session));
if (nses == NULL) {
@@ -338,11 +378,13 @@ local_history_redraw(struct local_history_session *session,
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);
+ return redraw_entry(
+ session->bw->history,
+ session->bw->history->start,
+ session->cursor,
+ clip,
+ x, y,
+ ctx);
}
/* exported interface documented in desktop/local_history.h */
@@ -385,10 +427,120 @@ local_history_mouse_action(struct local_history_session *session,
return NSERROR_OK;
}
+/**
+ * Determine the point on the parent line where this history line branches.
+ *
+ * If `branch_point` gets set then there is a guarantee that (a) `ent` is
+ * a transitive child (forward) of that point. and (b) `branch_point` has a
+ * parent.
+ *
+ * \param[in] ent The entry to work backward from
+ * \param[out] branch_point The entry to set to the branch point if one is found
+ */
+static void
+_local_history_find_branch_point(struct history_entry *ent,
+ struct history_entry **branch_point)
+{
+ if (ent->back == NULL) {
+ /* We're at the root, nothing to do */
+ return;
+ }
+ /* Start from our immediate parent */
+ ent = ent->back;
+ while (ent->back != NULL) {
+ if (ent->back->forward != ent->back->forward_last) {
+ /* This point is a branch */
+ *branch_point = ent;
+ break;
+ }
+ ent = ent->back;
+ }
+}
+
/* exported interface documented in desktop/local_history.h */
bool
local_history_keypress(struct local_history_session *session, uint32_t key)
{
+ switch (key) {
+ case NS_KEY_NL:
+ case NS_KEY_CR:
+ /* pressed enter */
+ if (session->cursor != session->bw->history->current) {
+ browser_window_history_go(session->bw, session->cursor,
+ false);
+ local_history_scroll_to_cursor(session);
+ session->cw_t->invalidate(session->core_window_handle, NULL);
+ }
+ /* We have handled this keypress */
+ return true;
+ case NS_KEY_LEFT:
+ /* Go to parent */
+ if (session->cursor->back != NULL) {
+ session->cursor = session->cursor->back;
+ local_history_scroll_to_cursor(session);
+ session->cw_t->invalidate(session->core_window_handle, NULL);
+ }
+ /* We have handled this keypress */
+ return true;
+ case NS_KEY_RIGHT:
+ /* Go to preferred child if there is one */
+ if (session->cursor->forward_pref != NULL) {
+ session->cursor = session->cursor->forward_pref;
+ local_history_scroll_to_cursor(session);
+ session->cw_t->invalidate(session->core_window_handle, NULL);
+ }
+ /* We have handled this keypress */
+ return true;
+ case NS_KEY_DOWN:
+ /* Go to next sibling down, if there is one */
+ if (session->cursor->next != NULL) {
+ session->cursor = session->cursor->next;
+ } else {
+ struct history_entry *branch_point = NULL;
+ _local_history_find_branch_point(
+ session->cursor,
+ &branch_point);
+ if (branch_point != NULL) {
+ if (branch_point->next != NULL) {
+ branch_point = branch_point->next;
+ }
+ session->cursor = branch_point;
+ }
+ }
+ /* We have handled this keypress */
+ local_history_scroll_to_cursor(session);
+ session->cw_t->invalidate(session->core_window_handle, NULL);
+ return true;
+ case NS_KEY_UP:
+ /* Go to next sibling up, if there is one */
+ if (session->cursor->back != NULL) {
+ struct history_entry *ent = session->cursor->back->forward;
+ while (ent != session->cursor &&
+ ent->next != NULL &&
+ ent->next != session->cursor) {
+ ent = ent->next;
+ }
+ if (session->cursor != ent) {
+ session->cursor = ent;
+ } else {
+ struct history_entry *branch_point = NULL;
+ _local_history_find_branch_point(
+ session->cursor,
+ &branch_point);
+ if (branch_point != NULL) {
+ struct history_entry *ent = branch_point->back->forward;
+ while (ent->next != NULL && ent->next != branch_point) {
+ ent = ent->next;
+ }
+ session->cursor = ent;
+ }
+ }
+ }
+ /* We have handled this keypress */
+ local_history_scroll_to_cursor(session);
+ session->cw_t->invalidate(session->core_window_handle, NULL);
+ return true;
+ }
return false;
}
@@ -398,12 +550,16 @@ local_history_set(struct local_history_session *session,
struct browser_window *bw)
{
session->bw = bw;
+ session->cursor = NULL;
+
if (bw != NULL) {
assert(session->bw->history != NULL);
+ session->cursor = bw->history->current;
session->cw_t->update_size(session->core_window_handle,
session->bw->history->width,
session->bw->history->height);
+ local_history_scroll_to_cursor(session);
}
return NSERROR_OK;