From 8b2a23081f5fdf09e4448a79e85b07b715549eda Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Mon, 7 Apr 2008 09:00:21 +0000 Subject: Various text selection improvements: + Fix redraw bug where parts of old selections would get left behind + Enable selection of list marker boxes (bullet points and numbers) + Improve formatting of copied-to-clipboard or saved text selections + Select click anywhere outside current selection now clears current selection svn path=/trunk/netsurf/; revision=4079 --- desktop/browser.c | 26 +++++++++-------- desktop/selection.c | 84 ++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 71 insertions(+), 39 deletions(-) (limited to 'desktop') diff --git a/desktop/browser.c b/desktop/browser.c index ee3e7eed5..ccc68a92f 100644 --- a/desktop/browser.c +++ b/desktop/browser.c @@ -312,7 +312,7 @@ void browser_window_go_post(struct browser_window *bw, const char *url, /* Compare new URL with existing one (ignoring fragments) */ if (bw->current_content && bw->current_content->url) { - res = url_compare(bw->current_content->url, url2, + res = url_compare(bw->current_content->url, url2, true, &same_url); if (res == URL_FUNC_NOMEM) { free(url2); @@ -326,7 +326,7 @@ void browser_window_go_post(struct browser_window *bw, const char *url, /* if we're simply moving to another ID on the same page, * don't bother to fetch, just update the window. */ - if (same_url && !post_urlenc && !post_multipart && + if (same_url && !post_urlenc && !post_multipart && !strchr(url2, '?')) { free(url2); browser_window_update(bw, false); @@ -652,7 +652,7 @@ void browser_window_refresh(void *p) (bw->current_content->status == CONTENT_STATUS_READY || bw->current_content->status == CONTENT_STATUS_DONE)); - /* Ignore if the refresh URL has gone + /* Ignore if the refresh URL has gone * (may happen if a fetch error occurred) */ if (!bw->current_content->refresh) return; @@ -1437,7 +1437,7 @@ void browser_window_mouse_action_html(struct browser_window *bw, &idx, &pixel_offset); - selection_click(bw->sel, mouse, + selection_click(bw->sel, mouse, text_box->byte_offset + idx); if (selection_dragging(bw->sel)) { @@ -1465,7 +1465,7 @@ void browser_window_mouse_action_html(struct browser_window *bw, int pixel_offset; size_t idx; - if (mouse & (BROWSER_MOUSE_DRAG_1 | + if (mouse & (BROWSER_MOUSE_DRAG_1 | BROWSER_MOUSE_DRAG_2)) selection_init(bw->sel, gadget_box); @@ -1476,7 +1476,7 @@ void browser_window_mouse_action_html(struct browser_window *bw, &idx, &pixel_offset); - selection_click(bw->sel, mouse, + selection_click(bw->sel, mouse, text_box->byte_offset + idx); if (selection_dragging(bw->sel)) @@ -1564,17 +1564,17 @@ void browser_window_mouse_action_html(struct browser_window *bw, &idx, &pixel_offset); - if (selection_click(bw->sel, mouse, + if (selection_click(bw->sel, mouse, text_box->byte_offset + idx)) { - /* key presses must be directed at the - * main browser window, paste text + /* key presses must be directed at the + * main browser window, paste text * operations ignored */ browser_window_remove_caret(bw); if (selection_dragging(bw->sel)) { - bw->drag_type = + bw->drag_type = DRAGGING_SELECTION; - status = + status = messages_get("Selecting"); } else status = c->status_message; @@ -1582,6 +1582,8 @@ void browser_window_mouse_action_html(struct browser_window *bw, done = true; } } + else if (mouse & BROWSER_MOUSE_CLICK_1) + selection_clear(bw->sel, true); } if (!done) { @@ -1827,7 +1829,7 @@ void browser_window_mouse_track_html(struct browser_window *bw, &idx, &pixel_offset); - selection_track(bw->sel, mouse, + selection_track(bw->sel, mouse, box->byte_offset + idx); } } diff --git a/desktop/selection.c b/desktop/selection.c index d744c3c3e..168d28673 100644 --- a/desktop/selection.c +++ b/desktop/selection.c @@ -31,6 +31,7 @@ #include "desktop/plotters.h" #include "desktop/selection.h" #include "render/box.h" +#include "render/font.h" #include "render/form.h" #include "render/textplain.h" #include "utils/log.h" @@ -85,8 +86,7 @@ static bool redraw_handler(const char *text, size_t length, struct box *box, size_t whitespace_length); static void selection_redraw(struct selection *s, unsigned start_idx, unsigned end_idx); -static unsigned selection_label_subtree(struct selection *s, struct box *node, - unsigned idx); +static unsigned selection_label_subtree(struct box *box, unsigned idx); static bool save_handler(const char *text, size_t length, struct box *box, void *handle, const char *whitespace_text, size_t whitespace_length); @@ -94,7 +94,8 @@ static bool selected_part(struct box *box, unsigned start_idx, unsigned end_idx, unsigned *start_offset, unsigned *end_offset); static bool traverse_tree(struct box *box, unsigned start_idx, unsigned end_idx, unsigned int num_space, seln_traverse_handler handler, - void *handle, seln_whitespace *before, bool *first); + void *handle, seln_whitespace *before, bool *first, + bool do_marker); static struct box *get_box(struct box *b, unsigned offset, int *pidx); @@ -166,7 +167,7 @@ void selection_reinit(struct selection *s, struct box *root) s->root = root; if (root) { - s->max_idx = selection_label_subtree(s, root, root_idx); + s->max_idx = selection_label_subtree(root, root_idx); } else { struct content *c = s->bw->current_content; @@ -216,19 +217,23 @@ void selection_init(struct selection *s, struct box *root) * \return updated position */ -unsigned selection_label_subtree(struct selection *s, struct box *node, - unsigned idx) +unsigned selection_label_subtree(struct box *box, unsigned idx) { - struct box *child = node->children; + struct box *child = box->children; - node->byte_offset = idx; + box->byte_offset = idx; - if (node->text && !node->object) - idx += node->length + node->space; + if (box->text && !box->object) + idx += box->length + box->space; while (child) { - if (!IS_INPUT(child)) - idx = selection_label_subtree(s, child, idx); + if (!IS_INPUT(child)) { + if (child->list_marker) + idx = selection_label_subtree( + child->list_marker, idx); + + idx = selection_label_subtree(child, idx); + } child = child->next; } @@ -258,7 +263,7 @@ bool selection_click(struct selection *s, browser_mouse_state mouse, if (selection_defined(s)) { if (idx > s->start_idx) { - if (idx < s->end_idx) + if (idx <= s->end_idx) pos = 0; else pos = 1; @@ -442,19 +447,38 @@ bool selected_part(struct box *box, unsigned start_idx, unsigned end_idx, * \param handle handle to pass * \param before type of whitespace to place before next encountered text * \param first whether this is the first box with text + * \param do_marker whether deal enter any marker box * \return false iff traversal abandoned part-way through */ bool traverse_tree(struct box *box, unsigned start_idx, unsigned end_idx, unsigned int num_space, seln_traverse_handler handler, - void *handle, seln_whitespace *before, bool *first) + void *handle, seln_whitespace *before, bool *first, + bool do_marker) { struct box *child; const char *whitespace_text = ""; size_t whitespace_length = 0; - /* we can prune this subtree, it's after the selection */ assert(box); + + /* If selection starts inside marker */ + if (box->parent->list_marker == box && !do_marker) { + /* set box to main list element */ + box = box->parent; + } + + /* If box has a list marker */ + if (box->list_marker) { + /* do the marker box before continuing with the rest of the + * list element */ + if (!traverse_tree(box->list_marker, start_idx, end_idx, + num_space, handler, handle, before, first, + true)) + return false; + } + + /* we can prune this subtree, it's after the selection */ if (box->byte_offset >= end_idx) return true; @@ -465,20 +489,23 @@ bool traverse_tree(struct box *box, unsigned start_idx, unsigned end_idx, * out what whitespace should be placed before the next bit of text */ if (before) { if (*before < WHITESPACE_TWO_NEW_LINES && + /* significant box type */ (box->type == BOX_BLOCK || box->type == BOX_TABLE || box->type == BOX_FLOAT_LEFT || box->type == BOX_FLOAT_RIGHT) && - (!box->list_marker || - box->list_marker && - *before == WHITESPACE_TAB)) { + /* and not a list element */ + !box->list_marker && + /* and not a marker... */ + (!do_marker || + /* ...unless marker follows WHITESPACE_TAB */ + (do_marker && *before == WHITESPACE_TAB))) { *before = WHITESPACE_TWO_NEW_LINES; } else if (*before <= WHITESPACE_ONE_NEW_LINE && (box->type == BOX_TABLE_ROW || box->type == BOX_BR || - (box->type != BOX_INLINE && - box->list_marker) || + (box->type != BOX_INLINE && do_marker) || (box->parent->style && (box->parent->style->white_space == CSS_WHITE_SPACE_PRE || @@ -491,10 +518,10 @@ bool traverse_tree(struct box *box, unsigned start_idx, unsigned end_idx, *before = WHITESPACE_ONE_NEW_LINE; } else if (*before < WHITESPACE_TAB && - box->type == BOX_TABLE_CELL) { + (box->type == BOX_TABLE_CELL || + box->list_marker)) { *before = WHITESPACE_TAB; } - if (*first) { whitespace_text = ""; } else { @@ -523,7 +550,6 @@ bool traverse_tree(struct box *box, unsigned start_idx, unsigned end_idx, else { whitespace_text = NULL; } - if (num_space == NUMBER_SPACE(box->byte_offset) && box->type != BOX_BR) { unsigned start_offset; @@ -561,7 +587,7 @@ bool traverse_tree(struct box *box, unsigned start_idx, unsigned end_idx, struct box *next = child->next; if (!traverse_tree(child, start_idx, end_idx, num_space, - handler, handle, before, first)) + handler, handle, before, first, false)) return false; child = next; @@ -594,7 +620,7 @@ bool selection_traverse(struct selection *s, seln_traverse_handler handler, if (s->root) return traverse_tree(s->root, s->start_idx, s->end_idx, NUMBER_SPACE(s->max_idx), handler, handle, - &before, &first); + &before, &first, false); c = s->bw->current_content; if (!c) return true; @@ -630,7 +656,7 @@ bool redraw_handler(const char *text, size_t length, struct box *box, { if (box) { struct rdw_info *r = (struct rdw_info*)handle; - int width, height; + int width, height, space_width; int x, y; /* \todo - it should be possible to reduce the redrawn area by @@ -640,6 +666,10 @@ bool redraw_handler(const char *text, size_t length, struct box *box, width = box->padding[LEFT] + box->width + box->padding[RIGHT]; height = box->padding[TOP] + box->height + box->padding[BOTTOM]; + if (box->type == BOX_TEXT && box->space && + nsfont_width(box->style, " ", 1, &space_width)) + width += space_width; + if (r->inited) { if (x < r->r.x0) r->r.x0 = x; if (y < r->r.y0) r->r.y0 = y; @@ -676,7 +706,7 @@ void selection_redraw(struct selection *s, unsigned start_idx, unsigned end_idx) if (s->root) { if (!traverse_tree(s->root, start_idx, end_idx, NUMBER_SPACE(s->max_idx), redraw_handler, &rdw, - NULL, NULL)) + NULL, NULL, false)) return; } else { -- cgit v1.2.3