mirror of
https://github.com/netsurf-browser/netsurf
synced 2024-11-27 16:59:36 +03:00
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
This commit is contained in:
parent
8de0baae0b
commit
8b2a23081f
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
27
render/box.c
27
render/box.c
@ -335,6 +335,17 @@ non_float_children:
|
||||
}
|
||||
}
|
||||
|
||||
/* marker boxes */
|
||||
if (box->list_marker) {
|
||||
if (box_contains_point(box->list_marker, x - bx, y - by)) {
|
||||
*box_x = bx + box->list_marker->x -
|
||||
box->list_marker->scroll_x;
|
||||
*box_y = by + box->list_marker->y -
|
||||
box->list_marker->scroll_y;
|
||||
return box->list_marker;
|
||||
}
|
||||
}
|
||||
|
||||
siblings:
|
||||
/* siblings and siblings of ancestors */
|
||||
while (box) {
|
||||
@ -405,6 +416,22 @@ bool box_contains_point(struct box *box, int x, int y)
|
||||
y < box->y + box->padding[TOP] + box->height +
|
||||
box->border[BOTTOM] + box->padding[BOTTOM])
|
||||
return true;
|
||||
if (box->list_marker && box->list_marker->x <= x +
|
||||
box->list_marker->border[LEFT] &&
|
||||
x < box->list_marker->x +
|
||||
box->list_marker->padding[LEFT] +
|
||||
box->list_marker->width +
|
||||
box->list_marker->border[RIGHT] +
|
||||
box->list_marker->padding[RIGHT] &&
|
||||
box->list_marker->y <= y +
|
||||
box->list_marker->border[TOP] &&
|
||||
y < box->list_marker->y +
|
||||
box->list_marker->padding[TOP] +
|
||||
box->list_marker->height +
|
||||
box->list_marker->border[BOTTOM] +
|
||||
box->list_marker->padding[BOTTOM]) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if (box->x + box->descendant_x0 <= x &&
|
||||
x < box->x + box->descendant_x1 &&
|
||||
|
Loading…
Reference in New Issue
Block a user