Gitweb links:
...log
http://git.netsurf-browser.org/netsurf.git/shortlog/6108d210d508e754904c46f687adbc87ab98dc78
...commit
http://git.netsurf-browser.org/netsurf.git/commit/6108d210d508e754904c46f687adbc87ab98dc78
...tree
http://git.netsurf-browser.org/netsurf.git/tree/6108d210d508e754904c46f687adbc87ab98dc78
The branch, master has been updated
via 6108d210d508e754904c46f687adbc87ab98dc78 (commit)
via 1161029d2952e5e11062d750a0a681643574428e (commit)
via 2ea577c47ecca38a0b2d15b15d242c771ce59e29 (commit)
via a8c540ea597fb17426c5458fa464f9c505c3bda8 (commit)
via cfe57002febe0f58dfc87f0173ad42126f1362f4 (commit)
via e65e41e2d6efccba983cd63aadfb10b5b4a935b2 (commit)
via 36b9262e1481fc24d302b58f03006e733b2e6d16 (commit)
from 0432d9556187d00fd7f78963afcefc4b7dd71f2a (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff
http://git.netsurf-browser.org/netsurf.git/commit/?id=6108d210d508e754904c46f687adbc87ab98dc78
commit 6108d210d508e754904c46f687adbc87ab98dc78
Author: Vincent Sanders <[email protected]>
Commit: Vincent Sanders <[email protected]>
remove all direct access to selection structure
diff --git a/content/handlers/html/interaction.c
b/content/handlers/html/interaction.c
index 0a963dd..79846ae 100644
--- a/content/handlers/html/interaction.c
+++ b/content/handlers/html/interaction.c
@@ -1247,7 +1247,7 @@ default_mouse_action(html_content *html,
selection_clear(&html->sel, true);
}
- if (selection_defined(&html->sel)) {
+ if (selection_active(&html->sel)) {
sel_owner.none = false;
html_set_selection(html,
HTML_SELECTION_SELF,
@@ -1586,13 +1586,8 @@ bool html_keypress(struct content *c, uint32_t key)
return true;
case NS_KEY_ESCAPE:
- if (selection_defined(sel)) {
- selection_clear(sel, true);
- return true;
- }
-
/* if there's no selection, leave Escape for the caller */
- return false;
+ return selection_clear(sel, true);
}
return false;
diff --git a/content/handlers/html/redraw.c b/content/handlers/html/redraw.c
index 7c96c90..08a284b 100644
--- a/content/handlers/html/redraw.c
+++ b/content/handlers/html/redraw.c
@@ -184,8 +184,7 @@ text_redraw(const char *utf8_text,
unsigned end_idx;
/* first try the browser window's current selection */
- if (selection_defined(sel) &&
- selection_highlighted(sel,
+ if (selection_highlighted(sel,
offset,
offset + len,
&start_idx,
diff --git a/content/handlers/text/textplain.c
b/content/handlers/text/textplain.c
index 6f03466..8bc05e6 100644
--- a/content/handlers/text/textplain.c
+++ b/content/handlers/text/textplain.c
@@ -810,21 +810,14 @@ static bool textplain_keypress(struct content *c,
uint32_t key)
return true;
case NS_KEY_ESCAPE:
- if (selection_defined(sel)) {
- selection_clear(sel, true);
- return true;
- }
-
/* if there's no selection, leave Escape for the caller */
- return false;
+ return selection_clear(sel, true);
}
return false;
}
-
-
/**
* Redraw a text string with highlighting
* (for selection/search)
@@ -871,8 +864,7 @@ text_draw(const char *utf8_text,
unsigned end_idx;
/* first try the browser window's current selection */
- if (selection_defined(sel) &&
- selection_highlighted(sel,
+ if (selection_highlighted(sel,
offset,
offset + len,
&start_idx,
@@ -1167,16 +1159,16 @@ textplain_redraw(struct content *c,
struct selection *sel = &text->sel;
bool highlighted = false;
- if (selection_defined(sel)) {
- unsigned start_idx, end_idx;
- if (selection_highlighted(sel,
- tab_ofst,
- tab_ofst + 1,
- &start_idx,
- &end_idx))
- highlighted = true;
+ unsigned start_idx, end_idx;
+ if (selection_highlighted(sel,
+ tab_ofst,
+ tab_ofst + 1,
+ &start_idx,
+ &end_idx)) {
+ highlighted = true;
}
+
if (!highlighted &&
(c->textsearch.context != NULL)) {
unsigned start_idx, end_idx;
@@ -1682,9 +1674,3 @@ size_t textplain_size(struct content *c)
return text->utf8_data_size;
}
-
-
-
-
-
-
diff --git a/content/textsearch.c b/content/textsearch.c
index 056da2b..18f9073 100644
--- a/content/textsearch.c
+++ b/content/textsearch.c
@@ -165,7 +165,6 @@ static void free_matches(struct textsearch_context
*textsearch)
static void search_show_all(bool all, struct textsearch_context *context)
{
struct list_entry *a;
- nserror res;
for (a = context->found->next; a; a = a->next) {
bool add = true;
@@ -628,7 +627,6 @@ content_textsearch_ishighlighted(struct textsearch_context
*textsearch,
for (cur = textsearch->found->next; cur != NULL; cur = cur->next) {
if (cur->sel &&
- selection_defined(cur->sel) &&
selection_highlighted(cur->sel,
start_offset,
end_offset,
diff --git a/desktop/selection.c b/desktop/selection.c
index 1fac7e2..06cfdae 100644
--- a/desktop/selection.c
+++ b/desktop/selection.c
@@ -22,32 +22,17 @@
* implementation of text selection within browser windows.
*/
-#include <assert.h>
-#include <stdio.h>
#include <stdlib.h>
-#include <stdbool.h>
-#include <string.h>
-#include <dom/dom.h>
-#include "utils/log.h"
-#include "utils/utf8.h"
-#include "utils/utils.h"
-#include "netsurf/form.h"
-#include "html/box.h"
-#include "html/box_inspect.h"
-#include "html/private.h"
-#include "html/font.h"
-#include "text/textplain.h"
+#include "netsurf/clipboard.h"
#include "netsurf/browser_window.h"
+#include "netsurf/window.h"
+#include "utils/utils.h"
+#include "content/content_protected.h"
-#include "netsurf/mouse.h"
#include "desktop/browser_private.h"
-#include "netsurf/plotters.h"
-#include "desktop/save_text.h"
-#include "desktop/selection.h"
-#include "netsurf/clipboard.h"
-#include "netsurf/window.h"
#include "desktop/gui_internal.h"
+#include "desktop/selection.h"
struct selection_string {
@@ -334,7 +319,7 @@ selection_click(struct selection *s,
top = browser_window_get_root(top);
- if (selection_defined(s)) {
+ if (s->defined) {
if (idx > s->start_idx) {
if (idx <= s->end_idx) {
pos = 0;
@@ -376,7 +361,7 @@ selection_click(struct selection *s,
} else if (mouse & BROWSER_MOUSE_DRAG_2) {
/* adjust selection, but only if there is one */
- if (!selection_defined(s)) {
+ if (!s->defined) {
return false; /* ignore Adjust drags */
}
@@ -396,7 +381,7 @@ selection_click(struct selection *s,
} else if (mouse & BROWSER_MOUSE_CLICK_2) {
/* ignore Adjust clicks when there's no selection */
- if (!selection_defined(s)) {
+ if (!s->defined) {
return false;
}
@@ -521,7 +506,7 @@ bool selection_copy_to_clipboard(struct selection *s)
/* exported interface documented in desktop/selection.h */
-void selection_clear(struct selection *s, bool redraw)
+bool selection_clear(struct selection *s, bool redraw)
{
int old_start, old_end;
bool was_defined;
@@ -539,6 +524,8 @@ void selection_clear(struct selection *s, bool redraw)
if (redraw && was_defined) {
selection_redraw(s, old_start, old_end);
}
+
+ return was_defined;
}
@@ -569,9 +556,11 @@ selection_highlighted(const struct selection *s,
unsigned *start_idx,
unsigned *end_idx)
{
- /* caller should have checked first for efficiency */
assert(s);
- assert(s->defined);
+
+ if (!s->defined) {
+ return false;
+ }
if ((end <= s->start_idx) ||
(start >= s->end_idx)) {
@@ -583,3 +572,24 @@ selection_highlighted(const struct selection *s,
return true;
}
+
+/* exported interface documented in desktop/selection.h */
+bool selection_active(struct selection *s)
+{
+ return s->defined;
+}
+
+bool selection_dragging(struct selection *s)
+{
+ return s->drag_state != DRAG_NONE;
+}
+
+bool selection_dragging_start(struct selection *s)
+{
+ return s->drag_state == DRAG_START;
+}
+
+void selection_drag_end(struct selection *s)
+{
+ s->drag_state = DRAG_NONE;
+}
diff --git a/desktop/selection.h b/desktop/selection.h
index 4f3e8b0..86ff395 100644
--- a/desktop/selection.h
+++ b/desktop/selection.h
@@ -20,8 +20,8 @@
* Text selection within browser windows (interface).
*/
-#ifndef _NETSURF_DESKTOP_SELECTION_H_
-#define _NETSURF_DESKTOP_SELECTION_H_
+#ifndef NETSURF_DESKTOP_SELECTION_H_
+#define NETSURF_DESKTOP_SELECTION_H_
#include <stdbool.h>
#include "netsurf/mouse.h"
@@ -37,13 +37,7 @@ typedef enum {
DRAG_END
} seln_drag_state;
-
-/* this structure should be treated as opaque outside selection.c
- (it's defined here to accelerate selection_defined(s) for reduced
- impact on redraw code) */
-
-struct selection
-{
+struct selection {
struct content *c;
struct box *root;
@@ -57,19 +51,19 @@ struct selection
seln_drag_state drag_state;
};
+/**
+ * determine if a selecion is active
+ */
+bool selection_active(struct selection *s);
-/* bool selection_defined(struct selection *s); */
-#define selection_defined(s) ((s)->defined)
-
-/* bool selection_dragging(struct selection *s); */
-#define selection_dragging(s) ((s)->drag_state != DRAG_NONE)
+bool selection_dragging(struct selection *s);
-/* bool selection_dragging_start(struct selection *s); */
-#define selection_dragging_start(s) ((s)->drag_state == DRAG_START)
+bool selection_dragging_start(struct selection *s);
-/** Handles completion of a drag operation */
-/* void selection_drag_end(struct selection *s); */
-#define selection_drag_end(s) ((s)->drag_state = DRAG_NONE)
+/**
+ * Handles completion of a drag operation
+ */
+void selection_drag_end(struct selection *s);
/**
* Creates a new selection object associated with a browser window.
@@ -129,8 +123,9 @@ void selection_reinit(struct selection *s);
* \param s selection object
* \param redraw true iff the previously selected region of the browser
* window should be redrawn
+ * \return true if selection was cleared false if not
*/
-void selection_clear(struct selection *s, bool redraw);
+bool selection_clear(struct selection *s, bool redraw);
/**
* Selects all the text within the box subtree controlled by
commitdiff
http://git.netsurf-browser.org/netsurf.git/commit/?id=1161029d2952e5e11062d750a0a681643574428e
commit 1161029d2952e5e11062d750a0a681643574428e
Author: Vincent Sanders <[email protected]>
Commit: Vincent Sanders <[email protected]>
remove unecessary content handler specific selection creation
diff --git a/content/content_protected.h b/content/content_protected.h
index b855c77..dbea229 100644
--- a/content/content_protected.h
+++ b/content/content_protected.h
@@ -139,11 +139,6 @@ struct content_handler {
*/
nserror (*textselection_get_end)(struct content *c, unsigned *end_idx);
- /**
- * create a selection object
- */
- nserror (*create_selection)(struct content *c, struct selection
**sel_out);
-
/**
* handler dependant content sensitive internal data interface.
*/
diff --git a/content/handlers/html/html.c b/content/handlers/html/html.c
index 5ae6ee5..a133d15 100644
--- a/content/handlers/html/html.c
+++ b/content/handlers/html/html.c
@@ -2338,7 +2338,6 @@ static const content_handler html_content_handler = {
.textselection_redraw = html_textselection_redraw,
.textselection_copy = html_textselection_copy,
.textselection_get_end = html_textselection_get_end,
- .create_selection = html_create_selection,
.no_share = true,
};
diff --git a/content/handlers/html/textselection.c
b/content/handlers/html/textselection.c
index becebb8..c0b27eb 100644
--- a/content/handlers/html/textselection.c
+++ b/content/handlers/html/textselection.c
@@ -258,22 +258,6 @@ coords_from_range(struct box *box,
}
-/**
- * create a selection object suitable for this content
- */
-nserror
-html_create_selection(struct content *c, struct selection **sel_out)
-{
- struct selection *sel;
- sel = selection_create(c);
- if (sel == NULL) {
- return NSERROR_NOMEM;
- }
-
- *sel_out = sel;
- return NSERROR_OK;
-}
-
/* exported interface documented in html/textselection.h */
nserror
html_textselection_redraw(struct content *c,
diff --git a/content/handlers/html/textselection.h
b/content/handlers/html/textselection.h
index 95d7078..46db045 100644
--- a/content/handlers/html/textselection.h
+++ b/content/handlers/html/textselection.h
@@ -27,11 +27,6 @@
struct content;
struct selection;
-/**
- * create a selection object suitable for this content
- */
-nserror html_create_selection(struct content *c, struct selection **sel_out);
-
nserror html_textselection_redraw(struct content *c, unsigned start_idx,
unsigned end_idx);
nserror html_textselection_copy(struct content *c, unsigned start_idx,
unsigned end_idx, struct selection_string *selstr);
diff --git a/content/handlers/text/textplain.c
b/content/handlers/text/textplain.c
index c91b81d..6f03466 100644
--- a/content/handlers/text/textplain.c
+++ b/content/handlers/text/textplain.c
@@ -1569,23 +1569,6 @@ textplain_textsearch_bounds(struct content *c,
/**
- * create a selection object suitable for this content
- */
-static nserror
-textplain_create_selection(struct content *c, struct selection **sel_out)
-{
- struct selection *sel;
- sel = selection_create(c);
- if (sel == NULL) {
- return NSERROR_NOMEM;
- }
-
- *sel_out = sel;
- return NSERROR_OK;
-}
-
-
-/**
* invalidate a region based on offsets into the text cauing a redraw
*/
static nserror
@@ -1655,7 +1638,6 @@ static const content_handler textplain_content_handler = {
.textselection_redraw = textplain_textselection_redraw,
.textselection_copy = textplain_textselection_copy,
.textselection_get_end = textplain_textselection_get_end,
- .create_selection = textplain_create_selection,
.no_share = true,
};
diff --git a/content/textsearch.c b/content/textsearch.c
index 4ad23cf..056da2b 100644
--- a/content/textsearch.c
+++ b/content/textsearch.c
@@ -179,9 +179,8 @@ static void search_show_all(bool all, struct
textsearch_context *context)
if (add && !a->sel) {
- res = context->c->handler->create_selection(context->c,
- &a->sel);
- if (res == NSERROR_OK) {
+ a->sel = selection_create(context->c);
+ if (a->sel != NULL) {
selection_set_position(a->sel,
a->start_idx,
a->end_idx);
@@ -426,8 +425,7 @@ content_textsearch_create(struct content *c,
content_type type;
if ((c->handler->textsearch_find == NULL) ||
- (c->handler->textsearch_bounds == NULL) ||
- (c->handler->create_selection == NULL)){
+ (c->handler->textsearch_bounds == NULL)) {
/*
* content has no free text find handler so searching
* is unsupported.
commitdiff
http://git.netsurf-browser.org/netsurf.git/commit/?id=2ea577c47ecca38a0b2d15b15d242c771ce59e29
commit 2ea577c47ecca38a0b2d15b15d242c771ce59e29
Author: Vincent Sanders <[email protected]>
Commit: Vincent Sanders <[email protected]>
remove unused is_html parameter to text selection routines
diff --git a/content/handlers/html/html.c b/content/handlers/html/html.c
index 2c471ae..5ae6ee5 100644
--- a/content/handlers/html/html.c
+++ b/content/handlers/html/html.c
@@ -493,7 +493,7 @@ html_create_html_data(html_content *c, const http_parameter
*params)
return NSERROR_NOMEM;
}
- selection_prepare(&c->sel, (struct content *)c, true);
+ selection_prepare(&c->sel, (struct content *)c);
nerror = http_parameter_list_find_item(params, corestring_lwc_charset,
&charset);
if (nerror == NSERROR_OK) {
diff --git a/content/handlers/html/textselection.c
b/content/handlers/html/textselection.c
index 06e28e1..becebb8 100644
--- a/content/handlers/html/textselection.c
+++ b/content/handlers/html/textselection.c
@@ -265,13 +265,11 @@ nserror
html_create_selection(struct content *c, struct selection **sel_out)
{
struct selection *sel;
- sel = selection_create(c, true);
+ sel = selection_create(c);
if (sel == NULL) {
return NSERROR_NOMEM;
}
- selection_init(sel);
-
*sel_out = sel;
return NSERROR_OK;
}
diff --git a/content/handlers/text/textplain.c
b/content/handlers/text/textplain.c
index 1165bcf..c91b81d 100644
--- a/content/handlers/text/textplain.c
+++ b/content/handlers/text/textplain.c
@@ -169,7 +169,7 @@ textplain_create_internal(textplain_content *c, lwc_string
*encoding)
c->formatted_width = 0;
c->bw = NULL;
- selection_prepare(&c->sel, (struct content *)c, false);
+ selection_prepare(&c->sel, (struct content *)c);
return NSERROR_OK;
@@ -1575,13 +1575,11 @@ static nserror
textplain_create_selection(struct content *c, struct selection **sel_out)
{
struct selection *sel;
- sel = selection_create(c, false);
+ sel = selection_create(c);
if (sel == NULL) {
return NSERROR_NOMEM;
}
- selection_init(sel);
-
*sel_out = sel;
return NSERROR_OK;
}
diff --git a/desktop/selection.c b/desktop/selection.c
index 40edff8..1fac7e2 100644
--- a/desktop/selection.c
+++ b/desktop/selection.c
@@ -49,13 +49,6 @@
#include "netsurf/window.h"
#include "desktop/gui_internal.h"
-/**
- * Text selection works by labelling each node in the box tree with its
- * start index in the textual representation of the tree's content.
- */
-
-#define SPACE_LEN(b) ((b->space == 0) ? 0 : 1)
-
struct selection_string {
char *buffer;
@@ -67,8 +60,6 @@ struct selection_string {
};
-
-
/**
* Redraws the given range of text.
*
@@ -254,24 +245,24 @@ selection_string_append(const char *text,
/* exported interface documented in desktop/selection.h */
-struct selection *selection_create(struct content *c, bool is_html)
+struct selection *selection_create(struct content *c)
{
- struct selection *s;
- s = calloc(1, sizeof(struct selection));
- if (s) {
- selection_prepare(s, c, is_html);
+ struct selection *sel;
+ sel = calloc(1, sizeof(struct selection));
+ if (sel) {
+ selection_prepare(sel, c);
+ selection_init(sel);
}
- return s;
+ return sel;
}
/* exported interface documented in desktop/selection.h */
-void selection_prepare(struct selection *s, struct content *c, bool is_html)
+void selection_prepare(struct selection *s, struct content *c)
{
if (s) {
s->c = c;
- s->is_html = is_html;
s->root = NULL;
s->drag_state = DRAG_NONE;
s->max_idx = 0;
diff --git a/desktop/selection.h b/desktop/selection.h
index e570d83..4f3e8b0 100644
--- a/desktop/selection.h
+++ b/desktop/selection.h
@@ -53,7 +53,6 @@ struct selection
unsigned end_idx;
bool defined;
- bool is_html;
seln_drag_state drag_state;
};
@@ -79,7 +78,7 @@ struct selection
*
* \return new selection context
*/
-struct selection *selection_create(struct content *c, bool is_html);
+struct selection *selection_create(struct content *c);
/**
* Prepare a newly created selection object for use.
@@ -88,9 +87,8 @@ struct selection *selection_create(struct content *c, bool
is_html);
*
* \param s selection object
* \param c content
- * \param is_html true if content is html false if content is textplain
*/
-void selection_prepare(struct selection *s, struct content *c, bool is_html);
+void selection_prepare(struct selection *s, struct content *c);
/**
* Destroys a selection object clearing it if nesessary
commitdiff
http://git.netsurf-browser.org/netsurf.git/commit/?id=a8c540ea597fb17426c5458fa464f9c505c3bda8
commit a8c540ea597fb17426c5458fa464f9c505c3bda8
Author: Vincent Sanders <[email protected]>
Commit: Vincent Sanders <[email protected]>
move content specific selection end to content handlers
diff --git a/content/content_protected.h b/content/content_protected.h
index 02bc861..b855c77 100644
--- a/content/content_protected.h
+++ b/content/content_protected.h
@@ -131,6 +131,15 @@ struct content_handler {
nserror (*textselection_copy)(struct content *c, unsigned start_idx,
unsigned end_idx, struct selection_string *selstr);
/**
+ * get maximum index of text section.
+ *
+ * \param[in] c The content to measure
+ * \param[out] end_idx pointer to value to recive result
+ * \return NSERROR_OK and \a end_idx updated else error code
+ */
+ nserror (*textselection_get_end)(struct content *c, unsigned *end_idx);
+
+ /**
* create a selection object
*/
nserror (*create_selection)(struct content *c, struct selection
**sel_out);
diff --git a/content/handlers/html/html.c b/content/handlers/html/html.c
index 136c4ee..2c471ae 100644
--- a/content/handlers/html/html.c
+++ b/content/handlers/html/html.c
@@ -1056,7 +1056,7 @@ static void html_reformat(struct content *c, int width,
int height)
if (c->height < layout->y + layout->descendant_y1)
c->height = layout->y + layout->descendant_y1;
- selection_reinit(&htmlc->sel, htmlc->layout);
+ selection_reinit(&htmlc->sel);
htmlc->reflowing = false;
htmlc->had_initial_layout = true;
@@ -1304,7 +1304,7 @@ html_open(struct content *c,
html->drag_owner.no_owner = true;
/* text selection */
- selection_init(&html->sel, html->layout);
+ selection_init(&html->sel);
html->selection_type = HTML_SELECTION_NONE;
html->selection_owner.none = true;
@@ -2337,6 +2337,7 @@ static const content_handler html_content_handler = {
.textsearch_bounds = html_textsearch_bounds,
.textselection_redraw = html_textselection_redraw,
.textselection_copy = html_textselection_copy,
+ .textselection_get_end = html_textselection_get_end,
.create_selection = html_create_selection,
.no_share = true,
};
diff --git a/content/handlers/html/textselection.c
b/content/handlers/html/textselection.c
index 67fd25b..06e28e1 100644
--- a/content/handlers/html/textselection.c
+++ b/content/handlers/html/textselection.c
@@ -264,14 +264,13 @@ coords_from_range(struct box *box,
nserror
html_create_selection(struct content *c, struct selection **sel_out)
{
- html_content *html = (html_content *)c;
struct selection *sel;
sel = selection_create(c, true);
if (sel == NULL) {
return NSERROR_NOMEM;
}
- selection_init(sel, html->layout);
+ selection_init(sel);
*sel_out = sel;
return NSERROR_OK;
@@ -528,3 +527,47 @@ html_textselection_copy(struct content *c,
}
return NSERROR_OK;
}
+
+
+/**
+ * Label each text box in the given box subtree with its position
+ * in a textual representation of the content.
+ *
+ * \param box The box at root of subtree
+ * \param idx current position within textual representation
+ * \return updated position
+ */
+static unsigned selection_label_subtree(struct box *box, unsigned idx)
+{
+ struct box *child = box->children;
+
+ box->byte_offset = idx;
+
+ if (box->text) {
+ idx += box->length + SPACE_LEN(box);
+ }
+
+ while (child) {
+ if (child->list_marker) {
+ idx = selection_label_subtree(child->list_marker, idx);
+ }
+
+ idx = selection_label_subtree(child, idx);
+ child = child->next;
+ }
+
+ return idx;
+}
+
+/* exported interface documented in html/textselection.h */
+nserror
+html_textselection_get_end(struct content *c, unsigned *end_idx)
+{
+ html_content *html = (html_content *)c;
+ unsigned root_idx;
+
+ root_idx = 0;
+
+ *end_idx = selection_label_subtree(html->layout, root_idx);
+ return NSERROR_OK;
+}
diff --git a/content/handlers/html/textselection.h
b/content/handlers/html/textselection.h
index 4a866b0..95d7078 100644
--- a/content/handlers/html/textselection.h
+++ b/content/handlers/html/textselection.h
@@ -36,4 +36,13 @@ nserror html_textselection_redraw(struct content *c,
unsigned start_idx, unsigne
nserror html_textselection_copy(struct content *c, unsigned start_idx,
unsigned end_idx, struct selection_string *selstr);
+/**
+ * get maximum index of text section.
+ *
+ * \param[in] c The content to measure
+ * \param[out] end_idx pointer to value to recive result
+ * \return NSERROR_OK and \a end_idx updated else error code
+ */
+nserror html_textselection_get_end(struct content *c, unsigned *end_idx);
+
#endif
diff --git a/content/handlers/text/textplain.c
b/content/handlers/text/textplain.c
index 5142291..1165bcf 100644
--- a/content/handlers/text/textplain.c
+++ b/content/handlers/text/textplain.c
@@ -1228,7 +1228,7 @@ textplain_open(struct content *c,
text->bw = bw;
/* text selection */
- selection_init(&text->sel, NULL);
+ selection_init(&text->sel);
return NSERROR_OK;
}
@@ -1580,7 +1580,7 @@ textplain_create_selection(struct content *c, struct
selection **sel_out)
return NSERROR_NOMEM;
}
- selection_init(sel, NULL);
+ selection_init(sel);
*sel_out = sel;
return NSERROR_OK;
@@ -1626,6 +1626,13 @@ textplain_textselection_copy(struct content *c,
return NSERROR_OK;
}
+static nserror
+textplain_textselection_get_end(struct content *c, unsigned *end_idx)
+{
+ *end_idx = textplain_size(c);
+ return NSERROR_OK;
+}
+
/**
* plain text content handler table
*/
@@ -1649,6 +1656,7 @@ static const content_handler textplain_content_handler = {
.textsearch_bounds = textplain_textsearch_bounds,
.textselection_redraw = textplain_textselection_redraw,
.textselection_copy = textplain_textselection_copy,
+ .textselection_get_end = textplain_textselection_get_end,
.create_selection = textplain_create_selection,
.no_share = true,
};
diff --git a/desktop/selection.c b/desktop/selection.c
index 6839724..40edff8 100644
--- a/desktop/selection.c
+++ b/desktop/selection.c
@@ -67,35 +67,6 @@ struct selection_string {
};
-/**
- * Label each text box in the given box subtree with its position
- * in a textual representation of the content.
- *
- * \param box The box at root of subtree
- * \param idx current position within textual representation
- * \return updated position
- */
-static unsigned selection_label_subtree(struct box *box, unsigned idx)
-{
- struct box *child = box->children;
-
- box->byte_offset = idx;
-
- if (box->text) {
- idx += box->length + SPACE_LEN(box);
- }
-
- while (child) {
- if (child->list_marker) {
- idx = selection_label_subtree(child->list_marker, idx);
- }
-
- idx = selection_label_subtree(child, idx);
- child = child->next;
- }
-
- return idx;
-}
/**
@@ -322,23 +293,12 @@ void selection_destroy(struct selection *s)
/* exported interface documented in desktop/selection.h */
-void selection_reinit(struct selection *s, struct box *root)
+void selection_reinit(struct selection *s)
{
- unsigned root_idx;
-
- assert(s);
+ s->max_idx = 0;
- root_idx = 0;
-
- s->root = root;
- if (root) {
- s->max_idx = selection_label_subtree(root, root_idx);
- } else {
- if (s->is_html == false) {
- s->max_idx = textplain_size(s->c);
- } else {
- s->max_idx = 0;
- }
+ if (s->c->handler->textselection_get_end != NULL) {
+ s->c->handler->textselection_get_end(s->c, &s->max_idx);
}
if (s->defined) {
@@ -354,8 +314,7 @@ void selection_reinit(struct selection *s, struct box *root)
/* exported interface documented in desktop/selection.h */
-void
-selection_init(struct selection *s, struct box *root)
+void selection_init(struct selection *s)
{
if (s->defined) {
selection_clear(s, true);
@@ -366,7 +325,7 @@ selection_init(struct selection *s, struct box *root)
s->end_idx = 0;
s->drag_state = DRAG_NONE;
- selection_reinit(s, root);
+ selection_reinit(s);
}
diff --git a/desktop/selection.h b/desktop/selection.h
index cb9289a..e570d83 100644
--- a/desktop/selection.h
+++ b/desktop/selection.h
@@ -108,9 +108,8 @@ void selection_destroy(struct selection *s);
* Used from text and html content handlers
*
* \param s selection object
- * \param root the root box for html document or NULL for text/plain
*/
-void selection_init(struct selection *s, struct box *root);
+void selection_init(struct selection *s);
/**
* Initialise the selection object to use the given box subtree as its root,
@@ -121,9 +120,8 @@ void selection_init(struct selection *s, struct box *root);
* Used from html content handler
*
* \param s selection object
- * \param root the root box for html document or NULL for text/plain
*/
-void selection_reinit(struct selection *s, struct box *root);
+void selection_reinit(struct selection *s);
/**
* Clears the current selection, optionally causing the screen to be updated.
commitdiff
http://git.netsurf-browser.org/netsurf.git/commit/?id=cfe57002febe0f58dfc87f0173ad42126f1362f4
commit cfe57002febe0f58dfc87f0173ad42126f1362f4
Author: Vincent Sanders <[email protected]>
Commit: Vincent Sanders <[email protected]>
remove unused css length usage in selection
diff --git a/content/handlers/html/html.c b/content/handlers/html/html.c
index a8ae9e4..136c4ee 100644
--- a/content/handlers/html/html.c
+++ b/content/handlers/html/html.c
@@ -1304,7 +1304,7 @@ html_open(struct content *c,
html->drag_owner.no_owner = true;
/* text selection */
- selection_init(&html->sel, html->layout, &html->len_ctx);
+ selection_init(&html->sel, html->layout);
html->selection_type = HTML_SELECTION_NONE;
html->selection_owner.none = true;
diff --git a/content/handlers/html/private.h b/content/handlers/html/private.h
index ff20be8..43b0e84 100644
--- a/content/handlers/html/private.h
+++ b/content/handlers/html/private.h
@@ -29,6 +29,7 @@
#include "netsurf/types.h"
#include "content/content_protected.h"
#include "desktop/selection.h"
+#include "content/handlers/css/utils.h"
struct gui_layout_table;
diff --git a/content/handlers/html/textselection.c
b/content/handlers/html/textselection.c
index 11e9dee..67fd25b 100644
--- a/content/handlers/html/textselection.c
+++ b/content/handlers/html/textselection.c
@@ -271,7 +271,7 @@ html_create_selection(struct content *c, struct selection
**sel_out)
return NSERROR_NOMEM;
}
- selection_init(sel, html->layout, &html->len_ctx);
+ selection_init(sel, html->layout);
*sel_out = sel;
return NSERROR_OK;
diff --git a/content/handlers/text/textplain.c
b/content/handlers/text/textplain.c
index 275efda..5142291 100644
--- a/content/handlers/text/textplain.c
+++ b/content/handlers/text/textplain.c
@@ -42,6 +42,7 @@
#include "content/content_factory.h"
#include "content/hlcache.h"
#include "content/textsearch.h"
+#include "content/handlers/css/utils.h"
#include "desktop/selection.h"
#include "desktop/gui_internal.h"
@@ -1227,7 +1228,7 @@ textplain_open(struct content *c,
text->bw = bw;
/* text selection */
- selection_init(&text->sel, NULL, NULL);
+ selection_init(&text->sel, NULL);
return NSERROR_OK;
}
@@ -1579,7 +1580,7 @@ textplain_create_selection(struct content *c, struct
selection **sel_out)
return NSERROR_NOMEM;
}
- selection_init(sel, NULL, NULL);
+ selection_init(sel, NULL);
*sel_out = sel;
return NSERROR_OK;
diff --git a/content/textsearch.c b/content/textsearch.c
index ae3c8a2..4ad23cf 100644
--- a/content/textsearch.c
+++ b/content/textsearch.c
@@ -23,6 +23,8 @@
*/
#include <stdbool.h>
+#include <stddef.h>
+#include <stdlib.h>
#include "utils/errors.h"
#include "utils/utils.h"
diff --git a/desktop/selection.c b/desktop/selection.c
index d4fa7ca..6839724 100644
--- a/desktop/selection.c
+++ b/desktop/selection.c
@@ -355,9 +355,7 @@ void selection_reinit(struct selection *s, struct box *root)
/* exported interface documented in desktop/selection.h */
void
-selection_init(struct selection *s,
- struct box *root,
- const nscss_len_ctx *len_ctx)
+selection_init(struct selection *s, struct box *root)
{
if (s->defined) {
selection_clear(s, true);
@@ -367,13 +365,6 @@ selection_init(struct selection *s,
s->start_idx = 0;
s->end_idx = 0;
s->drag_state = DRAG_NONE;
- if (len_ctx != NULL) {
- s->len_ctx = *len_ctx;
- } else {
- s->len_ctx.vw = 0;
- s->len_ctx.vh = 0;
- s->len_ctx.root_style = NULL;
- }
selection_reinit(s, root);
}
diff --git a/desktop/selection.h b/desktop/selection.h
index cc8d8da..cb9289a 100644
--- a/desktop/selection.h
+++ b/desktop/selection.h
@@ -25,7 +25,6 @@
#include <stdbool.h>
#include "netsurf/mouse.h"
-#include "content/handlers/css/utils.h"
struct box;
struct browser_window;
@@ -47,7 +46,6 @@ struct selection
{
struct content *c;
struct box *root;
- nscss_len_ctx len_ctx;
unsigned max_idx; /* total bytes in text representation */
@@ -112,7 +110,7 @@ void selection_destroy(struct selection *s);
* \param s selection object
* \param root the root box for html document or NULL for text/plain
*/
-void selection_init(struct selection *s, struct box *root, const nscss_len_ctx
*len_ctx);
+void selection_init(struct selection *s, struct box *root);
/**
* Initialise the selection object to use the given box subtree as its root,
commitdiff
http://git.netsurf-browser.org/netsurf.git/commit/?id=e65e41e2d6efccba983cd63aadfb10b5b4a935b2
commit e65e41e2d6efccba983cd63aadfb10b5b4a935b2
Author: Vincent Sanders <[email protected]>
Commit: Vincent Sanders <[email protected]>
move content handler specific selection copying into handlers
diff --git a/content/content_protected.h b/content/content_protected.h
index 9a3654b..02bc861 100644
--- a/content/content_protected.h
+++ b/content/content_protected.h
@@ -47,6 +47,7 @@ struct browser_window_features;
struct textsearch_context;
struct box;
struct selection;
+struct selection_string;
typedef struct content_handler content_handler;
@@ -112,7 +113,10 @@ struct content_handler {
nserror (*textsearch_bounds)(struct content *c, unsigned start_idx,
unsigned end_idx, struct box *start_ptr, struct box *end_ptr, struct rect
*bounds_out);
/**
- * cause a region of the content to be marked invalid and hence redraw
+ * redraw an area of selected text
+ *
+ * The defined text selection will cause an area of the
+ * content to be marked as invalid and hence redrawn.
*
* \param c The content being redrawn
* \param start_idx The start index of the text region to be redrawn
@@ -122,6 +126,11 @@ struct content_handler {
nserror (*textselection_redraw)(struct content *c, unsigned start_idx,
unsigned end_idx);
/**
+ * copy selected text into selection string possibly with formatting
+ */
+ nserror (*textselection_copy)(struct content *c, unsigned start_idx,
unsigned end_idx, struct selection_string *selstr);
+
+ /**
* create a selection object
*/
nserror (*create_selection)(struct content *c, struct selection
**sel_out);
diff --git a/content/handlers/html/html.c b/content/handlers/html/html.c
index 2a3cb17..a8ae9e4 100644
--- a/content/handlers/html/html.c
+++ b/content/handlers/html/html.c
@@ -2336,6 +2336,7 @@ static const content_handler html_content_handler = {
.textsearch_find = html_textsearch_find,
.textsearch_bounds = html_textsearch_bounds,
.textselection_redraw = html_textselection_redraw,
+ .textselection_copy = html_textselection_copy,
.create_selection = html_create_selection,
.no_share = true,
};
diff --git a/content/handlers/html/textselection.c
b/content/handlers/html/textselection.c
index bbd5573..11e9dee 100644
--- a/content/handlers/html/textselection.c
+++ b/content/handlers/html/textselection.c
@@ -277,6 +277,7 @@ html_create_selection(struct content *c, struct selection
**sel_out)
return NSERROR_OK;
}
+/* exported interface documented in html/textselection.h */
nserror
html_textselection_redraw(struct content *c,
unsigned start_idx,
@@ -301,3 +302,229 @@ html_textselection_redraw(struct content *c,
return NSERROR_OK;
}
+
+/**
+ * Selection traversal routine for appending text to a string
+ *
+ * \param text pointer to text being added, or NULL for newline
+ * \param length length of text to be appended (bytes)
+ * \param box pointer to text box, or NULL if from textplain
+ * \param len_ctx Length conversion context
+ * \param handle selection string to append to
+ * \param whitespace_text whitespace to place before text for formatting
+ * may be NULL
+ * \param whitespace_length length of whitespace_text
+ * \return true iff successful and traversal should continue
+ */
+static bool
+selection_copy(const char *text,
+ size_t length,
+ struct box *box,
+ const nscss_len_ctx *len_ctx,
+ struct selection_string *handle,
+ const char *whitespace_text,
+ size_t whitespace_length)
+{
+ bool add_space = false;
+ plot_font_style_t style;
+ plot_font_style_t *pstyle = NULL;
+
+ /* add any whitespace which precedes the text from this box */
+ if (whitespace_text != NULL &&
+ whitespace_length > 0) {
+ if (!selection_string_append(whitespace_text,
+ whitespace_length,
+ false,
+ pstyle,
+ handle)) {
+ return false;
+ }
+ }
+
+ if (box != NULL) {
+ /* HTML */
+ add_space = (box->space != 0);
+
+ if (box->style != NULL) {
+ /* Override default font style */
+ font_plot_style_from_css(len_ctx, box->style, &style);
+ pstyle = &style;
+ } else {
+ /* If there's no style, there must be no text */
+ assert(box->text == NULL);
+ }
+ }
+
+ /* add the text from this box */
+ if (!selection_string_append(text, length, add_space, pstyle, handle)) {
+ return false;
+ }
+
+ return true;
+}
+
+
+/**
+ * Traverse the given box subtree, calling selection copy for all
+ * boxes that lie (partially) within the given range
+ *
+ * \param box box subtree
+ * \param len_ctx Length conversion context.
+ * \param start_idx start of range within textual representation (bytes)
+ * \param end_idx end of range
+ * \param handler handler function to call
+ * \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
+ */
+static bool
+traverse_tree(struct box *box,
+ const nscss_len_ctx *len_ctx,
+ unsigned start_idx,
+ unsigned end_idx,
+ struct selection_string *selstr,
+ save_text_whitespace *before,
+ bool *first,
+ bool do_marker)
+{
+ struct box *child;
+ const char *whitespace_text = "";
+ size_t whitespace_length = 0;
+
+ assert(box);
+
+ /* If selection starts inside marker */
+ if (box->parent &&
+ 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,
+ len_ctx,
+ start_idx,
+ end_idx,
+ selstr,
+ before,
+ first,
+ true)) {
+ return false;
+ }
+ }
+
+ /* we can prune this subtree, it's after the selection */
+ if (box->byte_offset >= end_idx) {
+ return true;
+ }
+
+ /* read before calling the handler in case it modifies the tree */
+ child = box->children;
+
+ /* If nicely formatted output of the selected text is required, work
+ * out what whitespace should be placed before the next bit of text */
+ if (before) {
+ save_text_solve_whitespace(box,
+ first,
+ before,
+ &whitespace_text,
+ &whitespace_length);
+ } else {
+ whitespace_text = NULL;
+ }
+
+ if ((box->type != BOX_BR) &&
+ !((box->type == BOX_FLOAT_LEFT ||
+ box->type == BOX_FLOAT_RIGHT) &&
+ !box->text)) {
+ unsigned start_offset;
+ unsigned end_offset;
+
+ if (selected_part(box,
+ start_idx,
+ end_idx,
+ &start_offset,
+ &end_offset)) {
+ if (!selection_copy(box->text + start_offset,
+ min(box->length, end_offset) -
start_offset,
+ box,
+ len_ctx,
+ selstr,
+ whitespace_text,
+ whitespace_length)) {
+ return false;
+ }
+ if (before) {
+ *first = false;
+ *before = WHITESPACE_NONE;
+ }
+ }
+ }
+
+ /* find the first child that could lie partially within the selection;
+ * this is important at the top-levels of the tree for pruning subtrees
+ * that lie entirely before the selection */
+
+ if (child) {
+ struct box *next = child->next;
+
+ while (next && next->byte_offset < start_idx) {
+ child = next;
+ next = child->next;
+ }
+
+ while (child) {
+ /* read before calling the handler in case it modifies
+ * the tree */
+ struct box *next = child->next;
+
+ if (!traverse_tree(child,
+ len_ctx,
+ start_idx,
+ end_idx,
+ selstr,
+ before,
+ first,
+ false)) {
+ return false;
+ }
+
+ child = next;
+ }
+ }
+
+ return true;
+}
+
+/* exported interface documented in html/textselection.h */
+nserror
+html_textselection_copy(struct content *c,
+ unsigned start_idx,
+ unsigned end_idx,
+ struct selection_string *selstr)
+{
+ html_content *html = (html_content *)c;
+ save_text_whitespace before = WHITESPACE_NONE;
+ bool first = true;
+ bool res;
+
+ res = traverse_tree(html->layout,
+ &html->len_ctx,
+ start_idx,
+ end_idx,
+ selstr,
+ &before,
+ &first,
+ false);
+
+ if (res == false) {
+ return NSERROR_NOMEM;
+ }
+ return NSERROR_OK;
+}
diff --git a/content/handlers/html/textselection.h
b/content/handlers/html/textselection.h
index 0287f3c..4a866b0 100644
--- a/content/handlers/html/textselection.h
+++ b/content/handlers/html/textselection.h
@@ -34,4 +34,6 @@ nserror html_create_selection(struct content *c, struct
selection **sel_out);
nserror html_textselection_redraw(struct content *c, unsigned start_idx,
unsigned end_idx);
+nserror html_textselection_copy(struct content *c, unsigned start_idx,
unsigned end_idx, struct selection_string *selstr);
+
#endif
diff --git a/content/handlers/text/textplain.c
b/content/handlers/text/textplain.c
index d8f61be..275efda 100644
--- a/content/handlers/text/textplain.c
+++ b/content/handlers/text/textplain.c
@@ -1514,6 +1514,43 @@ textplain_coords_from_range(struct content *c,
/**
+ * Return a pointer to the raw UTF-8 data, as opposed to the reformatted
+ * text to fit the window width. Thus only hard newlines are preserved
+ * in the saved/copied text of a selection.
+ *
+ * \param[in] c content of type CONTENT_TEXTPLAIN
+ * \param[in] start starting byte offset within UTF-8 text
+ * \param[in] end ending byte offset
+ * \param[out] plen receives validated length
+ * \return pointer to text, or NULL if no text
+ */
+static char *
+textplain_get_raw_data(struct content *c,
+ unsigned start,
+ unsigned end,
+ size_t *plen)
+{
+ textplain_content *text = (textplain_content *) c;
+ size_t utf8_size;
+
+ assert(c != NULL);
+
+ utf8_size = text->utf8_data_size;
+
+ /* any text at all? */
+ if (!utf8_size) return NULL;
+
+ /* clamp to valid offset range */
+ if (start >= utf8_size) start = utf8_size;
+ if (end >= utf8_size) end = utf8_size;
+
+ *plen = end - start;
+
+ return text->utf8_data + start;
+}
+
+
+/**
* get bounds of a free text search match
*/
static nserror
@@ -1570,6 +1607,23 @@ textplain_textselection_redraw(struct content *c,
return NSERROR_OK;
}
+static nserror
+textplain_textselection_copy(struct content *c,
+ unsigned start_idx,
+ unsigned end_idx,
+ struct selection_string *selstr)
+{
+ const char *text;
+ size_t length;
+ bool res;
+
+ text = textplain_get_raw_data(c, start_idx, end_idx, &length);
+ res = selection_string_append(text, length, false, NULL, selstr);
+ if (res == false) {
+ return NSERROR_NOMEM;
+ }
+ return NSERROR_OK;
+}
/**
* plain text content handler table
@@ -1593,6 +1647,7 @@ static const content_handler textplain_content_handler = {
.textsearch_find = textplain_textsearch_find,
.textsearch_bounds = textplain_textsearch_bounds,
.textselection_redraw = textplain_textselection_redraw,
+ .textselection_copy = textplain_textselection_copy,
.create_selection = textplain_create_selection,
.no_share = true,
};
@@ -1643,28 +1698,4 @@ size_t textplain_size(struct content *c)
-/* exported interface documented in html/textplain.h */
-char *
-textplain_get_raw_data(struct content *c,
- unsigned start,
- unsigned end,
- size_t *plen)
-{
- textplain_content *text = (textplain_content *) c;
- size_t utf8_size;
- assert(c != NULL);
-
- utf8_size = text->utf8_data_size;
-
- /* any text at all? */
- if (!utf8_size) return NULL;
-
- /* clamp to valid offset range */
- if (start >= utf8_size) start = utf8_size;
- if (end >= utf8_size) end = utf8_size;
-
- *plen = end - start;
-
- return text->utf8_data + start;
-}
diff --git a/content/handlers/text/textplain.h
b/content/handlers/text/textplain.h
index 206c583..b94ee33 100644
--- a/content/handlers/text/textplain.h
+++ b/content/handlers/text/textplain.h
@@ -46,18 +46,4 @@ nserror textplain_init(void);
size_t textplain_size(struct content *c);
-/**
- * Return a pointer to the raw UTF-8 data, as opposed to the reformatted
- * text to fit the window width. Thus only hard newlines are preserved
- * in the saved/copied text of a selection.
- *
- * \param[in] c content of type CONTENT_TEXTPLAIN
- * \param[in] start starting byte offset within UTF-8 text
- * \param[in] end ending byte offset
- * \param[out] plen receives validated length
- * \return pointer to text, or NULL if no text
- */
-char *textplain_get_raw_data(struct content *c, unsigned start, unsigned end,
size_t *plen);
-
-
#endif
diff --git a/desktop/selection.c b/desktop/selection.c
index 11cd1fb..d4fa7ca 100644
--- a/desktop/selection.c
+++ b/desktop/selection.c
@@ -57,11 +57,6 @@
#define SPACE_LEN(b) ((b->space == 0) ? 0 : 1)
-struct rdw_info {
- bool inited;
- struct rect r;
-};
-
struct selection_string {
char *buffer;
size_t buffer_len;
@@ -72,15 +67,6 @@ struct selection_string {
};
-typedef bool (*seln_traverse_handler)(const char *text,
- size_t length,
- struct box *box,
- const nscss_len_ctx *len_ctx,
- void *handle,
- const char *whitespace_text,
- size_t whitespace_length);
-
-
/**
* Label each text box in the given box subtree with its position
* in a textual representation of the content.
@@ -113,206 +99,6 @@ static unsigned selection_label_subtree(struct box *box,
unsigned idx)
/**
- * Tests whether a text box lies partially within the given range of
- * byte offsets, returning the start and end indexes of the bytes
- * that are enclosed.
- *
- * \param box box to be tested
- * \param start_idx byte offset of start of range
- * \param end_idx byte offset of end of range
- * \param start_offset receives the start offset of the selected part
- * \param end_offset receives the end offset of the selected part
- * \return true iff the range encloses at least part of the box
- */
-static bool
-selected_part(struct box *box,
- unsigned start_idx,
- unsigned end_idx,
- unsigned *start_offset,
- unsigned *end_offset)
-{
- size_t box_length = box->length + SPACE_LEN(box);
-
- if (box_length > 0) {
- if ((box->byte_offset >= start_idx) &&
- (box->byte_offset + box_length <= end_idx)) {
-
- /* fully enclosed */
- *start_offset = 0;
- *end_offset = box_length;
- return true;
- } else if ((box->byte_offset + box_length > start_idx) &&
- (box->byte_offset < end_idx)) {
- /* partly enclosed */
- int offset = 0;
- int len;
-
- if (box->byte_offset < start_idx) {
- offset = start_idx - box->byte_offset;
- }
-
- len = box_length - offset;
-
- if (box->byte_offset + box_length > end_idx) {
- len = end_idx - (box->byte_offset + offset);
- }
-
- *start_offset = offset;
- *end_offset = offset + len;
-
- return true;
- }
- }
- return false;
-}
-
-
-/**
- * Traverse the given box subtree, calling the handler function (with
- * its handle) for all boxes that lie (partially) within the given
- * range
- *
- * \param box box subtree
- * \param len_ctx Length conversion context.
- * \param start_idx start of range within textual representation (bytes)
- * \param end_idx end of range
- * \param handler handler function to call
- * \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
- */
-static bool
-traverse_tree(struct box *box,
- const nscss_len_ctx *len_ctx,
- unsigned start_idx,
- unsigned end_idx,
- seln_traverse_handler handler,
- void *handle,
- save_text_whitespace *before,
- bool *first,
- bool do_marker)
-{
- struct box *child;
- const char *whitespace_text = "";
- size_t whitespace_length = 0;
-
- assert(box);
-
- /* If selection starts inside marker */
- if (box->parent &&
- 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,
- len_ctx,
- start_idx,
- end_idx,
- 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;
- }
-
- /* read before calling the handler in case it modifies the tree */
- child = box->children;
-
- /* If nicely formatted output of the selected text is required, work
- * out what whitespace should be placed before the next bit of text */
- if (before) {
- save_text_solve_whitespace(box,
- first,
- before,
- &whitespace_text,
- &whitespace_length);
- } else {
- whitespace_text = NULL;
- }
-
- if ((box->type != BOX_BR) &&
- !((box->type == BOX_FLOAT_LEFT ||
- box->type == BOX_FLOAT_RIGHT) &&
- !box->text)) {
- unsigned start_offset;
- unsigned end_offset;
-
- if (selected_part(box,
- start_idx,
- end_idx,
- &start_offset,
- &end_offset)) {
- if (!handler(box->text + start_offset,
- min(box->length, end_offset) -
start_offset,
- box,
- len_ctx,
- handle,
- whitespace_text,
- whitespace_length)) {
- return false;
- }
- if (before) {
- *first = false;
- *before = WHITESPACE_NONE;
- }
- }
- }
-
- /* find the first child that could lie partially within the selection;
- * this is important at the top-levels of the tree for pruning subtrees
- * that lie entirely before the selection */
-
- if (child) {
- struct box *next = child->next;
-
- while (next && next->byte_offset < start_idx) {
- child = next;
- next = child->next;
- }
-
- while (child) {
- /* read before calling the handler in case it modifies
- * the tree */
- struct box *next = child->next;
-
- if (!traverse_tree(child,
- len_ctx,
- start_idx,
- end_idx,
- handler,
- handle,
- before,
- first,
- false)) {
- return false;
- }
-
- child = next;
- }
- }
-
- return true;
-}
-
-
-
-
-/**
* Redraws the given range of text.
*
* \param s selection object
@@ -404,35 +190,22 @@ static void selection_set_end(struct selection *s,
unsigned offset)
* \return false iff traversal abandoned part-way through
*/
static bool
-selection_traverse(struct selection *s,
- seln_traverse_handler handler,
- void *handle)
+selection_copy(struct selection *s, struct selection_string *selstr)
{
- save_text_whitespace before = WHITESPACE_NONE;
- bool first = true;
- const char *text;
- size_t length;
-
- if (!s->defined) {
- return true; /* easy case, nothing to do */
- }
+ nserror res;
- if (s->root) {
- /* HTML */
- return traverse_tree(s->root, &s->len_ctx,
- s->start_idx, s->end_idx,
- handler, handle,
- &before, &first, false);
+ if (s->c->handler->textselection_copy != NULL) {
+ res = s->c->handler->textselection_copy(s->c,
+ s->start_idx,
+ s->end_idx,
+ selstr);
+ } else {
+ res = NSERROR_NOT_IMPLEMENTED;
}
- /* Text */
- text = textplain_get_raw_data(s->c, s->start_idx, s->end_idx, &length);
-
- if (text &&
- !handler(text, length, NULL, NULL, handle, NULL, 0)) {
+ if (res != NSERROR_OK) {
return false;
}
-
return true;
}
@@ -447,7 +220,7 @@ selection_traverse(struct selection *s,
* \param sel_string string to append to, may be resized
* \return true iff successful
*/
-static bool
+bool
selection_string_append(const char *text,
size_t length,
bool space,
@@ -509,67 +282,6 @@ selection_string_append(const char *text,
}
-/**
- * Selection traversal routine for appending text to a string
- *
- * \param text pointer to text being added, or NULL for newline
- * \param length length of text to be appended (bytes)
- * \param box pointer to text box, or NULL if from textplain
- * \param len_ctx Length conversion context
- * \param handle selection string to append to
- * \param whitespace_text whitespace to place before text for formatting
- * may be NULL
- * \param whitespace_length length of whitespace_text
- * \return true iff successful and traversal should continue
- */
-static bool
-selection_copy_handler(const char *text,
- size_t length,
- struct box *box,
- const nscss_len_ctx *len_ctx,
- void *handle,
- const char *whitespace_text,
- size_t whitespace_length)
-{
- bool add_space = false;
- plot_font_style_t style;
- plot_font_style_t *pstyle = NULL;
-
- /* add any whitespace which precedes the text from this box */
- if (whitespace_text != NULL &&
- whitespace_length > 0) {
- if (!selection_string_append(whitespace_text,
- whitespace_length,
- false,
- pstyle,
- handle)) {
- return false;
- }
- }
-
- if (box != NULL) {
- /* HTML */
- add_space = (box->space != 0);
-
- if (box->style != NULL) {
- /* Override default font style */
- font_plot_style_from_css(len_ctx, box->style, &style);
- pstyle = &style;
- } else {
- /* If there's no style, there must be no text */
- assert(box->text == NULL);
- }
- }
-
- /* add the text from this box */
- if (!selection_string_append(text, length, add_space, pstyle, handle)) {
- return false;
- }
-
- return true;
-}
-
-
/* exported interface documented in desktop/selection.h */
struct selection *selection_create(struct content *c, bool is_html)
{
@@ -821,7 +533,7 @@ char *selection_get_copy(struct selection *s)
if (s == NULL || !s->defined)
return NULL;
- if (!selection_traverse(s, selection_copy_handler, &sel_string)) {
+ if (!selection_copy(s, &sel_string)) {
free(sel_string.buffer);
free(sel_string.styles);
return NULL;
@@ -849,7 +561,7 @@ bool selection_copy_to_clipboard(struct selection *s)
return false;
}
- if (!selection_traverse(s, selection_copy_handler, &sel_string)) {
+ if (!selection_copy(s, &sel_string)) {
free(sel_string.buffer);
free(sel_string.styles);
return false;
diff --git a/desktop/selection.h b/desktop/selection.h
index cfaf59b..cc8d8da 100644
--- a/desktop/selection.h
+++ b/desktop/selection.h
@@ -29,6 +29,8 @@
struct box;
struct browser_window;
+struct plot_font_style;
+struct selection_string;
typedef enum {
DRAG_NONE,
@@ -218,4 +220,11 @@ char *selection_get_copy(struct selection *s);
*/
bool selection_highlighted(const struct selection *s, unsigned start, unsigned
end, unsigned *start_idx, unsigned *end_idx);
+bool
+selection_string_append(const char *text,
+ size_t length,
+ bool space,
+ struct plot_font_style *style,
+ struct selection_string *sel_string);
+
#endif
commitdiff
http://git.netsurf-browser.org/netsurf.git/commit/?id=36b9262e1481fc24d302b58f03006e733b2e6d16
commit 36b9262e1481fc24d302b58f03006e733b2e6d16
Author: Vincent Sanders <[email protected]>
Commit: Vincent Sanders <[email protected]>
split selection redraw into content handler specific implementations
diff --git a/content/content_protected.h b/content/content_protected.h
index 881a432..9a3654b 100644
--- a/content/content_protected.h
+++ b/content/content_protected.h
@@ -112,6 +112,16 @@ struct content_handler {
nserror (*textsearch_bounds)(struct content *c, unsigned start_idx,
unsigned end_idx, struct box *start_ptr, struct box *end_ptr, struct rect
*bounds_out);
/**
+ * cause a region of the content to be marked invalid and hence redraw
+ *
+ * \param c The content being redrawn
+ * \param start_idx The start index of the text region to be redrawn
+ * \param end_idx The end index of teh text region to be redrawn
+ * \return NSERROR_OK on success else error code
+ */
+ nserror (*textselection_redraw)(struct content *c, unsigned start_idx,
unsigned end_idx);
+
+ /**
* create a selection object
*/
nserror (*create_selection)(struct content *c, struct selection
**sel_out);
diff --git a/content/handlers/html/Makefile b/content/handlers/html/Makefile
index 233fb13..8bb329b 100644
--- a/content/handlers/html/Makefile
+++ b/content/handlers/html/Makefile
@@ -20,4 +20,5 @@ S_HTML := box_construct.c \
redraw.c \
redraw_border.c \
script.c \
- table.c
+ table.c \
+ textselection.c
diff --git a/content/handlers/html/html.c b/content/handlers/html/html.c
index 33320aa..2a3cb17 100644
--- a/content/handlers/html/html.c
+++ b/content/handlers/html/html.c
@@ -70,6 +70,7 @@
#include "html/form_internal.h"
#include "html/imagemap.h"
#include "html/layout.h"
+#include "html/textselection.h"
#define CHUNK 4096
@@ -2304,26 +2305,6 @@ html_textsearch_bounds(struct content *c,
/**
- * create a selection object suitable for this content
- */
-static nserror
-html_create_selection(struct content *c, struct selection **sel_out)
-{
- html_content *html = (html_content *)c;
- struct selection *sel;
- sel = selection_create(c, true);
- if (sel == NULL) {
- return NSERROR_NOMEM;
- }
-
- selection_init(sel, html->layout, &html->len_ctx);
-
- *sel_out = sel;
- return NSERROR_OK;
-}
-
-
-/**
* HTML content handler function table
*/
static const content_handler html_content_handler = {
@@ -2354,6 +2335,7 @@ static const content_handler html_content_handler = {
.saw_insecure_objects = html_saw_insecure_objects,
.textsearch_find = html_textsearch_find,
.textsearch_bounds = html_textsearch_bounds,
+ .textselection_redraw = html_textselection_redraw,
.create_selection = html_create_selection,
.no_share = true,
};
diff --git a/content/handlers/html/textselection.c
b/content/handlers/html/textselection.c
new file mode 100644
index 0000000..bbd5573
--- /dev/null
+++ b/content/handlers/html/textselection.c
@@ -0,0 +1,303 @@
+/*
+ * Copyright 2006 James Bursa <[email protected]>
+ * Copyright 2006 Richard Wilson <[email protected]>
+ * Copyright 2008 Michael Drake <[email protected]>
+ * Copyright 2009 Paul Blokus <[email protected]>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * implementation of user interaction with a CONTENT_HTML.
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+
+#include <dom/dom.h>
+
+#include "utils/corestrings.h"
+#include "utils/messages.h"
+#include "utils/utils.h"
+#include "utils/log.h"
+#include "utils/nsoption.h"
+#include "netsurf/content.h"
+#include "netsurf/browser_window.h"
+#include "netsurf/mouse.h"
+#include "netsurf/misc.h"
+#include "netsurf/layout.h"
+#include "netsurf/keypress.h"
+#include "content/hlcache.h"
+#include "content/textsearch.h"
+#include "desktop/frames.h"
+#include "desktop/scrollbar.h"
+#include "desktop/selection.h"
+#include "desktop/textarea.h"
+#include "javascript/js.h"
+#include "desktop/gui_internal.h"
+#include "desktop/save_text.h"
+
+#include "html/box.h"
+#include "html/box_textarea.h"
+#include "html/box_inspect.h"
+#include "html/font.h"
+#include "html/form_internal.h"
+#include "html/private.h"
+#include "html/imagemap.h"
+#include "html/textselection.h"
+
+#define SPACE_LEN(b) ((b->space == 0) ? 0 : 1)
+
+
+
+struct rdw_info {
+ bool inited;
+ struct rect r;
+};
+
+
+
+/**
+ * Tests whether a text box lies partially within the given range of
+ * byte offsets, returning the start and end indexes of the bytes
+ * that are enclosed.
+ *
+ * \param box box to be tested
+ * \param start_idx byte offset of start of range
+ * \param end_idx byte offset of end of range
+ * \param start_offset receives the start offset of the selected part
+ * \param end_offset receives the end offset of the selected part
+ * \return true iff the range encloses at least part of the box
+ */
+static bool
+selected_part(struct box *box,
+ unsigned start_idx,
+ unsigned end_idx,
+ unsigned *start_offset,
+ unsigned *end_offset)
+{
+ size_t box_length = box->length + SPACE_LEN(box);
+
+ if (box_length > 0) {
+ if ((box->byte_offset >= start_idx) &&
+ (box->byte_offset + box_length <= end_idx)) {
+
+ /* fully enclosed */
+ *start_offset = 0;
+ *end_offset = box_length;
+ return true;
+ } else if ((box->byte_offset + box_length > start_idx) &&
+ (box->byte_offset < end_idx)) {
+ /* partly enclosed */
+ int offset = 0;
+ int len;
+
+ if (box->byte_offset < start_idx) {
+ offset = start_idx - box->byte_offset;
+ }
+
+ len = box_length - offset;
+
+ if (box->byte_offset + box_length > end_idx) {
+ len = end_idx - (box->byte_offset + offset);
+ }
+
+ *start_offset = offset;
+ *end_offset = offset + len;
+
+ return true;
+ }
+ }
+ return false;
+}
+
+
+/**
+ * Traverse the given box subtree, calling the handler function (with
+ * its handle) for all boxes that lie (partially) within the given
+ * range
+ *
+ * \param box box subtree
+ * \param start_idx start of range within textual representation (bytes)
+ * \param end_idx end of range
+ * \param rdwi redraw range to fill in
+ * \param do_marker whether deal enter any marker box
+ * \return false iff traversal abandoned part-way through
+ */
+static bool
+coords_from_range(struct box *box,
+ unsigned start_idx,
+ unsigned end_idx,
+ struct rdw_info *rdwi,
+ bool do_marker)
+{
+ struct box *child;
+
+ assert(box);
+
+ /* If selection starts inside marker */
+ if (box->parent &&
+ 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 (!coords_from_range(box->list_marker,
+ start_idx,
+ end_idx,
+ rdwi,
+ true)) {
+ return false;
+ }
+ }
+
+ /* we can prune this subtree, it's after the selection */
+ if (box->byte_offset >= end_idx) {
+ return true;
+ }
+
+ /* read before calling the handler in case it modifies the tree */
+ child = box->children;
+
+ if ((box->type != BOX_BR) &&
+ !((box->type == BOX_FLOAT_LEFT ||
+ box->type == BOX_FLOAT_RIGHT) &&
+ !box->text)) {
+ unsigned start_offset;
+ unsigned end_offset;
+
+ if (selected_part(box, start_idx, end_idx, &start_offset,
&end_offset)) {
+ int width, height;
+ int x, y;
+
+ /**
+ * \todo it should be possible to reduce the redrawn
+ * area using the offsets
+ */
+ box_coords(box, &x, &y);
+
+ 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 != 0)) {
+ width += box->space;
+ }
+
+ if (rdwi->inited) {
+ if (x < rdwi->r.x0) {
+ rdwi->r.x0 = x;
+ }
+ if (y < rdwi->r.y0) {
+ rdwi->r.y0 = y;
+ }
+ if (x + width > rdwi->r.x1) {
+ rdwi->r.x1 = x + width;
+ }
+ if (y + height > rdwi->r.y1) {
+ rdwi->r.y1 = y + height;
+ }
+ } else {
+ rdwi->inited = true;
+ rdwi->r.x0 = x;
+ rdwi->r.y0 = y;
+ rdwi->r.x1 = x + width;
+ rdwi->r.y1 = y + height;
+ }
+ }
+ }
+
+ /* find the first child that could lie partially within the selection;
+ * this is important at the top-levels of the tree for pruning subtrees
+ * that lie entirely before the selection */
+
+ if (child) {
+ struct box *next = child->next;
+
+ while (next && next->byte_offset < start_idx) {
+ child = next;
+ next = child->next;
+ }
+
+ while (child) {
+ /* read before calling the handler in case it modifies
+ * the tree */
+ struct box *next = child->next;
+
+ if (!coords_from_range(child,
+ start_idx,
+ end_idx,
+ rdwi,
+ false)) {
+ return false;
+ }
+
+ child = next;
+ }
+ }
+
+ return true;
+}
+
+
+/**
+ * create a selection object suitable for this content
+ */
+nserror
+html_create_selection(struct content *c, struct selection **sel_out)
+{
+ html_content *html = (html_content *)c;
+ struct selection *sel;
+ sel = selection_create(c, true);
+ if (sel == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ selection_init(sel, html->layout, &html->len_ctx);
+
+ *sel_out = sel;
+ return NSERROR_OK;
+}
+
+nserror
+html_textselection_redraw(struct content *c,
+ unsigned start_idx,
+ unsigned end_idx)
+{
+ html_content *html = (html_content *)c;
+ struct rdw_info rdw;
+
+ rdw.inited = false;
+
+ if (!coords_from_range(html->layout, start_idx, end_idx, &rdw, false)) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ if (rdw.inited) {
+ content__request_redraw(c,
+ rdw.r.x0,
+ rdw.r.y0,
+ rdw.r.x1 - rdw.r.x0,
+ rdw.r.y1 - rdw.r.y0);
+ }
+
+ return NSERROR_OK;
+}
diff --git a/content/handlers/html/textselection.h
b/content/handlers/html/textselection.h
new file mode 100644
index 0000000..0287f3c
--- /dev/null
+++ b/content/handlers/html/textselection.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2020 Vincent Sanders <[email protected]>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * HTML text selection handling
+ */
+
+#ifndef NETSURF_HTML_TEXTSELECTION_H
+#define NETSURF_HTML_TEXTSELECTION_H
+
+struct content;
+struct selection;
+
+/**
+ * create a selection object suitable for this content
+ */
+nserror html_create_selection(struct content *c, struct selection **sel_out);
+
+nserror html_textselection_redraw(struct content *c, unsigned start_idx,
unsigned end_idx);
+
+#endif
diff --git a/content/handlers/text/textplain.c
b/content/handlers/text/textplain.c
index 534b91d..d8f61be 100644
--- a/content/handlers/text/textplain.c
+++ b/content/handlers/text/textplain.c
@@ -1452,6 +1452,68 @@ textplain_textsearch_find(struct content *c,
/**
+ * Given a range of byte offsets within a UTF8 textplain content,
+ * return a box that fully encloses the text
+ *
+ * \param[in] c content of type CONTENT_TEXTPLAIN
+ * \param[in] start byte offset of start of text range
+ * \param[in] end byte offset of end
+ * \param[out] r rectangle to be completed
+ */
+static void
+textplain_coords_from_range(struct content *c,
+ unsigned start,
+ unsigned end,
+ struct rect *r)
+{
+ textplain_content *text = (textplain_content *) c;
+ float line_height = textplain_line_height();
+ char *utf8_data;
+ struct textplain_line *line;
+ unsigned lineno = 0;
+ unsigned nlines;
+
+ assert(c != NULL);
+ assert(start <= end);
+ assert(end <= text->utf8_data_size);
+
+ utf8_data = text->utf8_data;
+ nlines = text->physical_line_count;
+ line = text->physical_line;
+
+ /* find start */
+ lineno = textplain_find_line(c, start);
+
+ r->y0 = (int)(MARGIN + lineno * line_height);
+
+ if (lineno + 1 <= nlines || line[lineno + 1].start >= end) {
+ /* \todo - it may actually be more efficient just to
+ * run forwards most of the time
+ */
+
+ /* find end */
+ lineno = textplain_find_line(c, end);
+
+ r->x0 = 0;
+ r->x1 = text->formatted_width;
+ } else {
+ /* single line */
+ const char *text = utf8_data + line[lineno].start;
+
+ r->x0 = textplain_coord_from_offset(text,
+ start - line[lineno].start,
+ line[lineno].length);
+
+ r->x1 = textplain_coord_from_offset(text,
+ end - line[lineno].start,
+ line[lineno].length);
+ }
+
+ r->y1 = (int)(MARGIN + (lineno + 1) * line_height);
+}
+
+
+/**
* get bounds of a free text search match
*/
static nserror
@@ -1488,6 +1550,28 @@ textplain_create_selection(struct content *c, struct
selection **sel_out)
/**
+ * invalidate a region based on offsets into the text cauing a redraw
+ */
+static nserror
+textplain_textselection_redraw(struct content *c,
+ unsigned start_idx,
+ unsigned end_idx)
+{
+ struct rect r;
+
+ if (end_idx <= start_idx) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ textplain_coords_from_range(c, start_idx, end_idx, &r);
+
+ content__request_redraw(c, r.x0, r.y0, r.x1 - r.x0, r.y1 - r.y0);
+
+ return NSERROR_OK;
+}
+
+
+/**
* plain text content handler table
*/
static const content_handler textplain_content_handler = {
@@ -1508,6 +1592,7 @@ static const content_handler textplain_content_handler = {
.type = textplain_content_type,
.textsearch_find = textplain_textsearch_find,
.textsearch_bounds = textplain_textsearch_bounds,
+ .textselection_redraw = textplain_textselection_redraw,
.create_selection = textplain_create_selection,
.no_share = true,
};
@@ -1555,58 +1640,7 @@ size_t textplain_size(struct content *c)
}
-/* exported interface documented in html/textplain.h */
-void
-textplain_coords_from_range(struct content *c,
- unsigned start,
- unsigned end,
- struct rect *r)
-{
- textplain_content *text = (textplain_content *) c;
- float line_height = textplain_line_height();
- char *utf8_data;
- struct textplain_line *line;
- unsigned lineno = 0;
- unsigned nlines;
-
- assert(c != NULL);
- assert(start <= end);
- assert(end <= text->utf8_data_size);
-
- utf8_data = text->utf8_data;
- nlines = text->physical_line_count;
- line = text->physical_line;
- /* find start */
- lineno = textplain_find_line(c, start);
-
- r->y0 = (int)(MARGIN + lineno * line_height);
-
- if (lineno + 1 <= nlines || line[lineno + 1].start >= end) {
- /* \todo - it may actually be more efficient just to
- * run forwards most of the time
- */
-
- /* find end */
- lineno = textplain_find_line(c, end);
-
- r->x0 = 0;
- r->x1 = text->formatted_width;
- } else {
- /* single line */
- const char *text = utf8_data + line[lineno].start;
-
- r->x0 = textplain_coord_from_offset(text,
- start - line[lineno].start,
- line[lineno].length);
-
- r->x1 = textplain_coord_from_offset(text,
- end - line[lineno].start,
- line[lineno].length);
- }
-
- r->y1 = (int)(MARGIN + (lineno + 1) * line_height);
-}
/* exported interface documented in html/textplain.h */
diff --git a/content/handlers/text/textplain.h
b/content/handlers/text/textplain.h
index 716397a..206c583 100644
--- a/content/handlers/text/textplain.h
+++ b/content/handlers/text/textplain.h
@@ -47,19 +47,6 @@ size_t textplain_size(struct content *c);
/**
- * Given a range of byte offsets within a UTF8 textplain content,
- * return a box that fully encloses the text
- *
- * \param[in] c content of type CONTENT_TEXTPLAIN
- * \param[in] start byte offset of start of text range
- * \param[in] end byte offset of end
- * \param[out] r rectangle to be completed
- */
-void textplain_coords_from_range(struct content *c,
- unsigned start, unsigned end, struct rect *r);
-
-
-/**
* Return a pointer to the raw UTF-8 data, as opposed to the reformatted
* text to fit the window width. Thus only hard newlines are preserved
* in the saved/copied text of a selection.
diff --git a/desktop/selection.c b/desktop/selection.c
index 5955054..11cd1fb 100644
--- a/desktop/selection.c
+++ b/desktop/selection.c
@@ -310,63 +310,6 @@ traverse_tree(struct box *box,
}
-/**
- * Selection traversal handler for redrawing the screen when the selection
- * has been altered.
- *
- * \param text pointer to text string
- * \param length length of text to be appended (bytes)
- * \param box pointer to text box being (partially) added
- * \param handle unused handle, we don't need one
- * \param whitespace_text whitespace to place before text for formatting
- * may be NULL
- * \param whitespace_length length of whitespace_text
- * \return true iff successful and traversal should continue
- */
-static bool
-redraw_handler(const char *text,
- size_t length,
- struct box *box,
- const nscss_len_ctx *len_ctx,
- void *handle,
- const char *whitespace_text,
- size_t whitespace_length)
-{
- struct rdw_info *r = (struct rdw_info*)handle;
- int width, height;
- int x, y;
-
- if (!box) {
- return true;
- }
-
- /* \todo - it should be possible to reduce the redrawn area by
- * considering the 'text', 'length' and 'space' parameters */
- box_coords(box, &x, &y);
-
- 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 != 0)) {
- width += box->space;
- }
-
- if (r->inited) {
- if (x < r->r.x0) r->r.x0 = x;
- if (y < r->r.y0) r->r.y0 = y;
- if (x + width > r->r.x1) r->r.x1 = x + width;
- if (y + height > r->r.y1) r->r.y1 = y + height;
- } else {
- r->inited = true;
- r->r.x0 = x;
- r->r.y0 = y;
- r->r.x1 = x + width;
- r->r.y1 = y + height;
- }
-
- return true;
-}
/**
@@ -376,43 +319,20 @@ redraw_handler(const char *text,
* \param start_idx start offset (bytes) within the textual representation
* \param end_idx end offset (bytes) within the textual representation
*/
-static void
+static nserror
selection_redraw(struct selection *s, unsigned start_idx, unsigned end_idx)
{
- struct rdw_info rdw;
-
- assert(end_idx >= start_idx);
- rdw.inited = false;
+ nserror res;
- if (s->root) {
- if (!traverse_tree(s->root,
- &s->len_ctx,
- start_idx,
- end_idx,
- redraw_handler,
- &rdw,
- NULL,
- NULL,
- false))
- return;
+ if (s->c->handler->textselection_redraw != NULL) {
+ res = s->c->handler->textselection_redraw(s->c,
+ start_idx,
+ end_idx);
} else {
- if ((s->is_html == false) &&
- (end_idx > start_idx)) {
- textplain_coords_from_range(s->c,
- start_idx,
- end_idx,
- &rdw.r);
- rdw.inited = true;
- }
+ res = NSERROR_NOT_IMPLEMENTED;
}
- if (rdw.inited) {
- content__request_redraw(s->c,
- rdw.r.x0,
- rdw.r.y0,
- rdw.r.x1 - rdw.r.x0,
- rdw.r.y1 - rdw.r.y0);
- }
+ return res;
}
-----------------------------------------------------------------------
Summary of changes:
content/content_protected.h | 27 +-
content/handlers/html/Makefile | 3 +-
content/handlers/html/html.c | 31 +-
content/handlers/html/interaction.c | 9 +-
content/handlers/html/private.h | 1 +
content/handlers/html/redraw.c | 3 +-
content/handlers/html/textselection.c | 555 +++++++++++++++++++
.../html/{box_special.h => textselection.h} | 20 +-
content/handlers/text/textplain.c | 260 +++++----
content/handlers/text/textplain.h | 27 -
content/textsearch.c | 12 +-
desktop/selection.c | 561 +++-----------------
desktop/selection.h | 58 +-
13 files changed, 862 insertions(+), 705 deletions(-)
create mode 100644 content/handlers/html/textselection.c
copy content/handlers/html/{box_special.h => textselection.h} (55%)
diff --git a/content/content_protected.h b/content/content_protected.h
index 881a432..dbea229 100644
--- a/content/content_protected.h
+++ b/content/content_protected.h
@@ -47,6 +47,7 @@ struct browser_window_features;
struct textsearch_context;
struct box;
struct selection;
+struct selection_string;
typedef struct content_handler content_handler;
@@ -112,9 +113,31 @@ struct content_handler {
nserror (*textsearch_bounds)(struct content *c, unsigned start_idx,
unsigned end_idx, struct box *start_ptr, struct box *end_ptr, struct rect
*bounds_out);
/**
- * create a selection object
+ * redraw an area of selected text
+ *
+ * The defined text selection will cause an area of the
+ * content to be marked as invalid and hence redrawn.
+ *
+ * \param c The content being redrawn
+ * \param start_idx The start index of the text region to be redrawn
+ * \param end_idx The end index of teh text region to be redrawn
+ * \return NSERROR_OK on success else error code
+ */
+ nserror (*textselection_redraw)(struct content *c, unsigned start_idx,
unsigned end_idx);
+
+ /**
+ * copy selected text into selection string possibly with formatting
+ */
+ nserror (*textselection_copy)(struct content *c, unsigned start_idx,
unsigned end_idx, struct selection_string *selstr);
+
+ /**
+ * get maximum index of text section.
+ *
+ * \param[in] c The content to measure
+ * \param[out] end_idx pointer to value to recive result
+ * \return NSERROR_OK and \a end_idx updated else error code
*/
- nserror (*create_selection)(struct content *c, struct selection
**sel_out);
+ nserror (*textselection_get_end)(struct content *c, unsigned *end_idx);
/**
* handler dependant content sensitive internal data interface.
diff --git a/content/handlers/html/Makefile b/content/handlers/html/Makefile
index 233fb13..8bb329b 100644
--- a/content/handlers/html/Makefile
+++ b/content/handlers/html/Makefile
@@ -20,4 +20,5 @@ S_HTML := box_construct.c \
redraw.c \
redraw_border.c \
script.c \
- table.c
+ table.c \
+ textselection.c
diff --git a/content/handlers/html/html.c b/content/handlers/html/html.c
index 33320aa..a133d15 100644
--- a/content/handlers/html/html.c
+++ b/content/handlers/html/html.c
@@ -70,6 +70,7 @@
#include "html/form_internal.h"
#include "html/imagemap.h"
#include "html/layout.h"
+#include "html/textselection.h"
#define CHUNK 4096
@@ -492,7 +493,7 @@ html_create_html_data(html_content *c, const http_parameter
*params)
return NSERROR_NOMEM;
}
- selection_prepare(&c->sel, (struct content *)c, true);
+ selection_prepare(&c->sel, (struct content *)c);
nerror = http_parameter_list_find_item(params, corestring_lwc_charset,
&charset);
if (nerror == NSERROR_OK) {
@@ -1055,7 +1056,7 @@ static void html_reformat(struct content *c, int width,
int height)
if (c->height < layout->y + layout->descendant_y1)
c->height = layout->y + layout->descendant_y1;
- selection_reinit(&htmlc->sel, htmlc->layout);
+ selection_reinit(&htmlc->sel);
htmlc->reflowing = false;
htmlc->had_initial_layout = true;
@@ -1303,7 +1304,7 @@ html_open(struct content *c,
html->drag_owner.no_owner = true;
/* text selection */
- selection_init(&html->sel, html->layout, &html->len_ctx);
+ selection_init(&html->sel);
html->selection_type = HTML_SELECTION_NONE;
html->selection_owner.none = true;
@@ -2304,26 +2305,6 @@ html_textsearch_bounds(struct content *c,
/**
- * create a selection object suitable for this content
- */
-static nserror
-html_create_selection(struct content *c, struct selection **sel_out)
-{
- html_content *html = (html_content *)c;
- struct selection *sel;
- sel = selection_create(c, true);
- if (sel == NULL) {
- return NSERROR_NOMEM;
- }
-
- selection_init(sel, html->layout, &html->len_ctx);
-
- *sel_out = sel;
- return NSERROR_OK;
-}
-
-
-/**
* HTML content handler function table
*/
static const content_handler html_content_handler = {
@@ -2354,7 +2335,9 @@ static const content_handler html_content_handler = {
.saw_insecure_objects = html_saw_insecure_objects,
.textsearch_find = html_textsearch_find,
.textsearch_bounds = html_textsearch_bounds,
- .create_selection = html_create_selection,
+ .textselection_redraw = html_textselection_redraw,
+ .textselection_copy = html_textselection_copy,
+ .textselection_get_end = html_textselection_get_end,
.no_share = true,
};
diff --git a/content/handlers/html/interaction.c
b/content/handlers/html/interaction.c
index 0a963dd..79846ae 100644
--- a/content/handlers/html/interaction.c
+++ b/content/handlers/html/interaction.c
@@ -1247,7 +1247,7 @@ default_mouse_action(html_content *html,
selection_clear(&html->sel, true);
}
- if (selection_defined(&html->sel)) {
+ if (selection_active(&html->sel)) {
sel_owner.none = false;
html_set_selection(html,
HTML_SELECTION_SELF,
@@ -1586,13 +1586,8 @@ bool html_keypress(struct content *c, uint32_t key)
return true;
case NS_KEY_ESCAPE:
- if (selection_defined(sel)) {
- selection_clear(sel, true);
- return true;
- }
-
/* if there's no selection, leave Escape for the caller */
- return false;
+ return selection_clear(sel, true);
}
return false;
diff --git a/content/handlers/html/private.h b/content/handlers/html/private.h
index ff20be8..43b0e84 100644
--- a/content/handlers/html/private.h
+++ b/content/handlers/html/private.h
@@ -29,6 +29,7 @@
#include "netsurf/types.h"
#include "content/content_protected.h"
#include "desktop/selection.h"
+#include "content/handlers/css/utils.h"
struct gui_layout_table;
diff --git a/content/handlers/html/redraw.c b/content/handlers/html/redraw.c
index 7c96c90..08a284b 100644
--- a/content/handlers/html/redraw.c
+++ b/content/handlers/html/redraw.c
@@ -184,8 +184,7 @@ text_redraw(const char *utf8_text,
unsigned end_idx;
/* first try the browser window's current selection */
- if (selection_defined(sel) &&
- selection_highlighted(sel,
+ if (selection_highlighted(sel,
offset,
offset + len,
&start_idx,
diff --git a/content/handlers/html/textselection.c
b/content/handlers/html/textselection.c
new file mode 100644
index 0000000..c0b27eb
--- /dev/null
+++ b/content/handlers/html/textselection.c
@@ -0,0 +1,555 @@
+/*
+ * Copyright 2006 James Bursa <[email protected]>
+ * Copyright 2006 Richard Wilson <[email protected]>
+ * Copyright 2008 Michael Drake <[email protected]>
+ * Copyright 2009 Paul Blokus <[email protected]>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * implementation of user interaction with a CONTENT_HTML.
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+
+#include <dom/dom.h>
+
+#include "utils/corestrings.h"
+#include "utils/messages.h"
+#include "utils/utils.h"
+#include "utils/log.h"
+#include "utils/nsoption.h"
+#include "netsurf/content.h"
+#include "netsurf/browser_window.h"
+#include "netsurf/mouse.h"
+#include "netsurf/misc.h"
+#include "netsurf/layout.h"
+#include "netsurf/keypress.h"
+#include "content/hlcache.h"
+#include "content/textsearch.h"
+#include "desktop/frames.h"
+#include "desktop/scrollbar.h"
+#include "desktop/selection.h"
+#include "desktop/textarea.h"
+#include "javascript/js.h"
+#include "desktop/gui_internal.h"
+#include "desktop/save_text.h"
+
+#include "html/box.h"
+#include "html/box_textarea.h"
+#include "html/box_inspect.h"
+#include "html/font.h"
+#include "html/form_internal.h"
+#include "html/private.h"
+#include "html/imagemap.h"
+#include "html/textselection.h"
+
+#define SPACE_LEN(b) ((b->space == 0) ? 0 : 1)
+
+
+
+struct rdw_info {
+ bool inited;
+ struct rect r;
+};
+
+
+
+/**
+ * Tests whether a text box lies partially within the given range of
+ * byte offsets, returning the start and end indexes of the bytes
+ * that are enclosed.
+ *
+ * \param box box to be tested
+ * \param start_idx byte offset of start of range
+ * \param end_idx byte offset of end of range
+ * \param start_offset receives the start offset of the selected part
+ * \param end_offset receives the end offset of the selected part
+ * \return true iff the range encloses at least part of the box
+ */
+static bool
+selected_part(struct box *box,
+ unsigned start_idx,
+ unsigned end_idx,
+ unsigned *start_offset,
+ unsigned *end_offset)
+{
+ size_t box_length = box->length + SPACE_LEN(box);
+
+ if (box_length > 0) {
+ if ((box->byte_offset >= start_idx) &&
+ (box->byte_offset + box_length <= end_idx)) {
+
+ /* fully enclosed */
+ *start_offset = 0;
+ *end_offset = box_length;
+ return true;
+ } else if ((box->byte_offset + box_length > start_idx) &&
+ (box->byte_offset < end_idx)) {
+ /* partly enclosed */
+ int offset = 0;
+ int len;
+
+ if (box->byte_offset < start_idx) {
+ offset = start_idx - box->byte_offset;
+ }
+
+ len = box_length - offset;
+
+ if (box->byte_offset + box_length > end_idx) {
+ len = end_idx - (box->byte_offset + offset);
+ }
+
+ *start_offset = offset;
+ *end_offset = offset + len;
+
+ return true;
+ }
+ }
+ return false;
+}
+
+
+/**
+ * Traverse the given box subtree, calling the handler function (with
+ * its handle) for all boxes that lie (partially) within the given
+ * range
+ *
+ * \param box box subtree
+ * \param start_idx start of range within textual representation (bytes)
+ * \param end_idx end of range
+ * \param rdwi redraw range to fill in
+ * \param do_marker whether deal enter any marker box
+ * \return false iff traversal abandoned part-way through
+ */
+static bool
+coords_from_range(struct box *box,
+ unsigned start_idx,
+ unsigned end_idx,
+ struct rdw_info *rdwi,
+ bool do_marker)
+{
+ struct box *child;
+
+ assert(box);
+
+ /* If selection starts inside marker */
+ if (box->parent &&
+ 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 (!coords_from_range(box->list_marker,
+ start_idx,
+ end_idx,
+ rdwi,
+ true)) {
+ return false;
+ }
+ }
+
+ /* we can prune this subtree, it's after the selection */
+ if (box->byte_offset >= end_idx) {
+ return true;
+ }
+
+ /* read before calling the handler in case it modifies the tree */
+ child = box->children;
+
+ if ((box->type != BOX_BR) &&
+ !((box->type == BOX_FLOAT_LEFT ||
+ box->type == BOX_FLOAT_RIGHT) &&
+ !box->text)) {
+ unsigned start_offset;
+ unsigned end_offset;
+
+ if (selected_part(box, start_idx, end_idx, &start_offset,
&end_offset)) {
+ int width, height;
+ int x, y;
+
+ /**
+ * \todo it should be possible to reduce the redrawn
+ * area using the offsets
+ */
+ box_coords(box, &x, &y);
+
+ 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 != 0)) {
+ width += box->space;
+ }
+
+ if (rdwi->inited) {
+ if (x < rdwi->r.x0) {
+ rdwi->r.x0 = x;
+ }
+ if (y < rdwi->r.y0) {
+ rdwi->r.y0 = y;
+ }
+ if (x + width > rdwi->r.x1) {
+ rdwi->r.x1 = x + width;
+ }
+ if (y + height > rdwi->r.y1) {
+ rdwi->r.y1 = y + height;
+ }
+ } else {
+ rdwi->inited = true;
+ rdwi->r.x0 = x;
+ rdwi->r.y0 = y;
+ rdwi->r.x1 = x + width;
+ rdwi->r.y1 = y + height;
+ }
+ }
+ }
+
+ /* find the first child that could lie partially within the selection;
+ * this is important at the top-levels of the tree for pruning subtrees
+ * that lie entirely before the selection */
+
+ if (child) {
+ struct box *next = child->next;
+
+ while (next && next->byte_offset < start_idx) {
+ child = next;
+ next = child->next;
+ }
+
+ while (child) {
+ /* read before calling the handler in case it modifies
+ * the tree */
+ struct box *next = child->next;
+
+ if (!coords_from_range(child,
+ start_idx,
+ end_idx,
+ rdwi,
+ false)) {
+ return false;
+ }
+
+ child = next;
+ }
+ }
+
+ return true;
+}
+
+
+/* exported interface documented in html/textselection.h */
+nserror
+html_textselection_redraw(struct content *c,
+ unsigned start_idx,
+ unsigned end_idx)
+{
+ html_content *html = (html_content *)c;
+ struct rdw_info rdw;
+
+ rdw.inited = false;
+
+ if (!coords_from_range(html->layout, start_idx, end_idx, &rdw, false)) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ if (rdw.inited) {
+ content__request_redraw(c,
+ rdw.r.x0,
+ rdw.r.y0,
+ rdw.r.x1 - rdw.r.x0,
+ rdw.r.y1 - rdw.r.y0);
+ }
+
+ return NSERROR_OK;
+}
+
+/**
+ * Selection traversal routine for appending text to a string
+ *
+ * \param text pointer to text being added, or NULL for newline
+ * \param length length of text to be appended (bytes)
+ * \param box pointer to text box, or NULL if from textplain
+ * \param len_ctx Length conversion context
+ * \param handle selection string to append to
+ * \param whitespace_text whitespace to place before text for formatting
+ * may be NULL
+ * \param whitespace_length length of whitespace_text
+ * \return true iff successful and traversal should continue
+ */
+static bool
+selection_copy(const char *text,
+ size_t length,
+ struct box *box,
+ const nscss_len_ctx *len_ctx,
+ struct selection_string *handle,
+ const char *whitespace_text,
+ size_t whitespace_length)
+{
+ bool add_space = false;
+ plot_font_style_t style;
+ plot_font_style_t *pstyle = NULL;
+
+ /* add any whitespace which precedes the text from this box */
+ if (whitespace_text != NULL &&
+ whitespace_length > 0) {
+ if (!selection_string_append(whitespace_text,
+ whitespace_length,
+ false,
+ pstyle,
+ handle)) {
+ return false;
+ }
+ }
+
+ if (box != NULL) {
+ /* HTML */
+ add_space = (box->space != 0);
+
+ if (box->style != NULL) {
+ /* Override default font style */
+ font_plot_style_from_css(len_ctx, box->style, &style);
+ pstyle = &style;
+ } else {
+ /* If there's no style, there must be no text */
+ assert(box->text == NULL);
+ }
+ }
+
+ /* add the text from this box */
+ if (!selection_string_append(text, length, add_space, pstyle, handle)) {
+ return false;
+ }
+
+ return true;
+}
+
+
+/**
+ * Traverse the given box subtree, calling selection copy for all
+ * boxes that lie (partially) within the given range
+ *
+ * \param box box subtree
+ * \param len_ctx Length conversion context.
+ * \param start_idx start of range within textual representation (bytes)
+ * \param end_idx end of range
+ * \param handler handler function to call
+ * \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
+ */
+static bool
+traverse_tree(struct box *box,
+ const nscss_len_ctx *len_ctx,
+ unsigned start_idx,
+ unsigned end_idx,
+ struct selection_string *selstr,
+ save_text_whitespace *before,
+ bool *first,
+ bool do_marker)
+{
+ struct box *child;
+ const char *whitespace_text = "";
+ size_t whitespace_length = 0;
+
+ assert(box);
+
+ /* If selection starts inside marker */
+ if (box->parent &&
+ 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,
+ len_ctx,
+ start_idx,
+ end_idx,
+ selstr,
+ before,
+ first,
+ true)) {
+ return false;
+ }
+ }
+
+ /* we can prune this subtree, it's after the selection */
+ if (box->byte_offset >= end_idx) {
+ return true;
+ }
+
+ /* read before calling the handler in case it modifies the tree */
+ child = box->children;
+
+ /* If nicely formatted output of the selected text is required, work
+ * out what whitespace should be placed before the next bit of text */
+ if (before) {
+ save_text_solve_whitespace(box,
+ first,
+ before,
+ &whitespace_text,
+ &whitespace_length);
+ } else {
+ whitespace_text = NULL;
+ }
+
+ if ((box->type != BOX_BR) &&
+ !((box->type == BOX_FLOAT_LEFT ||
+ box->type == BOX_FLOAT_RIGHT) &&
+ !box->text)) {
+ unsigned start_offset;
+ unsigned end_offset;
+
+ if (selected_part(box,
+ start_idx,
+ end_idx,
+ &start_offset,
+ &end_offset)) {
+ if (!selection_copy(box->text + start_offset,
+ min(box->length, end_offset) -
start_offset,
+ box,
+ len_ctx,
+ selstr,
+ whitespace_text,
+ whitespace_length)) {
+ return false;
+ }
+ if (before) {
+ *first = false;
+ *before = WHITESPACE_NONE;
+ }
+ }
+ }
+
+ /* find the first child that could lie partially within the selection;
+ * this is important at the top-levels of the tree for pruning subtrees
+ * that lie entirely before the selection */
+
+ if (child) {
+ struct box *next = child->next;
+
+ while (next && next->byte_offset < start_idx) {
+ child = next;
+ next = child->next;
+ }
+
+ while (child) {
+ /* read before calling the handler in case it modifies
+ * the tree */
+ struct box *next = child->next;
+
+ if (!traverse_tree(child,
+ len_ctx,
+ start_idx,
+ end_idx,
+ selstr,
+ before,
+ first,
+ false)) {
+ return false;
+ }
+
+ child = next;
+ }
+ }
+
+ return true;
+}
+
+/* exported interface documented in html/textselection.h */
+nserror
+html_textselection_copy(struct content *c,
+ unsigned start_idx,
+ unsigned end_idx,
+ struct selection_string *selstr)
+{
+ html_content *html = (html_content *)c;
+ save_text_whitespace before = WHITESPACE_NONE;
+ bool first = true;
+ bool res;
+
+ res = traverse_tree(html->layout,
+ &html->len_ctx,
+ start_idx,
+ end_idx,
+ selstr,
+ &before,
+ &first,
+ false);
+
+ if (res == false) {
+ return NSERROR_NOMEM;
+ }
+ return NSERROR_OK;
+}
+
+
+/**
+ * Label each text box in the given box subtree with its position
+ * in a textual representation of the content.
+ *
+ * \param box The box at root of subtree
+ * \param idx current position within textual representation
+ * \return updated position
+ */
+static unsigned selection_label_subtree(struct box *box, unsigned idx)
+{
+ struct box *child = box->children;
+
+ box->byte_offset = idx;
+
+ if (box->text) {
+ idx += box->length + SPACE_LEN(box);
+ }
+
+ while (child) {
+ if (child->list_marker) {
+ idx = selection_label_subtree(child->list_marker, idx);
+ }
+
+ idx = selection_label_subtree(child, idx);
+ child = child->next;
+ }
+
+ return idx;
+}
+
+/* exported interface documented in html/textselection.h */
+nserror
+html_textselection_get_end(struct content *c, unsigned *end_idx)
+{
+ html_content *html = (html_content *)c;
+ unsigned root_idx;
+
+ root_idx = 0;
+
+ *end_idx = selection_label_subtree(html->layout, root_idx);
+ return NSERROR_OK;
+}
diff --git a/content/handlers/html/box_special.h
b/content/handlers/html/textselection.h
similarity index 55%
copy from content/handlers/html/box_special.h
copy to content/handlers/html/textselection.h
index 973ab97..46db045 100644
--- a/content/handlers/html/box_special.h
+++ b/content/handlers/html/textselection.h
@@ -18,18 +18,26 @@
/**
* \file
- * HTML Box tree construction special element conversion interface.
+ * HTML text selection handling
*/
-#ifndef NETSURF_HTML_BOX_SPECIAL_H
-#define NETSURF_HTML_BOX_SPECIAL_H
+#ifndef NETSURF_HTML_TEXTSELECTION_H
+#define NETSURF_HTML_TEXTSELECTION_H
+struct content;
+struct selection;
+
+nserror html_textselection_redraw(struct content *c, unsigned start_idx,
unsigned end_idx);
+
+nserror html_textselection_copy(struct content *c, unsigned start_idx,
unsigned end_idx, struct selection_string *selstr);
/**
- * call an elements special conversion handler
+ * get maximum index of text section.
*
- * \return true if box construction should continue else false on error.
+ * \param[in] c The content to measure
+ * \param[out] end_idx pointer to value to recive result
+ * \return NSERROR_OK and \a end_idx updated else error code
*/
-bool convert_special_elements(dom_node *node, html_content *content, struct
box *box, bool *convert_children);
+nserror html_textselection_get_end(struct content *c, unsigned *end_idx);
#endif
diff --git a/content/handlers/text/textplain.c
b/content/handlers/text/textplain.c
index 534b91d..8bc05e6 100644
--- a/content/handlers/text/textplain.c
+++ b/content/handlers/text/textplain.c
@@ -42,6 +42,7 @@
#include "content/content_factory.h"
#include "content/hlcache.h"
#include "content/textsearch.h"
+#include "content/handlers/css/utils.h"
#include "desktop/selection.h"
#include "desktop/gui_internal.h"
@@ -168,7 +169,7 @@ textplain_create_internal(textplain_content *c, lwc_string
*encoding)
c->formatted_width = 0;
c->bw = NULL;
- selection_prepare(&c->sel, (struct content *)c, false);
+ selection_prepare(&c->sel, (struct content *)c);
return NSERROR_OK;
@@ -809,21 +810,14 @@ static bool textplain_keypress(struct content *c,
uint32_t key)
return true;
case NS_KEY_ESCAPE:
- if (selection_defined(sel)) {
- selection_clear(sel, true);
- return true;
- }
-
/* if there's no selection, leave Escape for the caller */
- return false;
+ return selection_clear(sel, true);
}
return false;
}
-
-
/**
* Redraw a text string with highlighting
* (for selection/search)
@@ -870,8 +864,7 @@ text_draw(const char *utf8_text,
unsigned end_idx;
/* first try the browser window's current selection */
- if (selection_defined(sel) &&
- selection_highlighted(sel,
+ if (selection_highlighted(sel,
offset,
offset + len,
&start_idx,
@@ -1166,16 +1159,16 @@ textplain_redraw(struct content *c,
struct selection *sel = &text->sel;
bool highlighted = false;
- if (selection_defined(sel)) {
- unsigned start_idx, end_idx;
- if (selection_highlighted(sel,
- tab_ofst,
- tab_ofst + 1,
- &start_idx,
- &end_idx))
- highlighted = true;
+ unsigned start_idx, end_idx;
+ if (selection_highlighted(sel,
+ tab_ofst,
+ tab_ofst + 1,
+ &start_idx,
+ &end_idx)) {
+ highlighted = true;
}
+
if (!highlighted &&
(c->textsearch.context != NULL)) {
unsigned start_idx, end_idx;
@@ -1227,7 +1220,7 @@ textplain_open(struct content *c,
text->bw = bw;
/* text selection */
- selection_init(&text->sel, NULL, NULL);
+ selection_init(&text->sel);
return NSERROR_OK;
}
@@ -1452,6 +1445,105 @@ textplain_textsearch_find(struct content *c,
/**
+ * Given a range of byte offsets within a UTF8 textplain content,
+ * return a box that fully encloses the text
+ *
+ * \param[in] c content of type CONTENT_TEXTPLAIN
+ * \param[in] start byte offset of start of text range
+ * \param[in] end byte offset of end
+ * \param[out] r rectangle to be completed
+ */
+static void
+textplain_coords_from_range(struct content *c,
+ unsigned start,
+ unsigned end,
+ struct rect *r)
+{
+ textplain_content *text = (textplain_content *) c;
+ float line_height = textplain_line_height();
+ char *utf8_data;
+ struct textplain_line *line;
+ unsigned lineno = 0;
+ unsigned nlines;
+
+ assert(c != NULL);
+ assert(start <= end);
+ assert(end <= text->utf8_data_size);
+
+ utf8_data = text->utf8_data;
+ nlines = text->physical_line_count;
+ line = text->physical_line;
+
+ /* find start */
+ lineno = textplain_find_line(c, start);
+
+ r->y0 = (int)(MARGIN + lineno * line_height);
+
+ if (lineno + 1 <= nlines || line[lineno + 1].start >= end) {
+ /* \todo - it may actually be more efficient just to
+ * run forwards most of the time
+ */
+
+ /* find end */
+ lineno = textplain_find_line(c, end);
+
+ r->x0 = 0;
+ r->x1 = text->formatted_width;
+ } else {
+ /* single line */
+ const char *text = utf8_data + line[lineno].start;
+
+ r->x0 = textplain_coord_from_offset(text,
+ start - line[lineno].start,
+ line[lineno].length);
+
+ r->x1 = textplain_coord_from_offset(text,
+ end - line[lineno].start,
+ line[lineno].length);
+ }
+
+ r->y1 = (int)(MARGIN + (lineno + 1) * line_height);
+}
+
+
+/**
+ * Return a pointer to the raw UTF-8 data, as opposed to the reformatted
+ * text to fit the window width. Thus only hard newlines are preserved
+ * in the saved/copied text of a selection.
+ *
+ * \param[in] c content of type CONTENT_TEXTPLAIN
+ * \param[in] start starting byte offset within UTF-8 text
+ * \param[in] end ending byte offset
+ * \param[out] plen receives validated length
+ * \return pointer to text, or NULL if no text
+ */
+static char *
+textplain_get_raw_data(struct content *c,
+ unsigned start,
+ unsigned end,
+ size_t *plen)
+{
+ textplain_content *text = (textplain_content *) c;
+ size_t utf8_size;
+
+ assert(c != NULL);
+
+ utf8_size = text->utf8_data_size;
+
+ /* any text at all? */
+ if (!utf8_size) return NULL;
+
+ /* clamp to valid offset range */
+ if (start >= utf8_size) start = utf8_size;
+ if (end >= utf8_size) end = utf8_size;
+
+ *plen = end - start;
+
+ return text->utf8_data + start;
+}
+
+
+/**
* get bounds of a free text search match
*/
static nserror
@@ -1469,23 +1561,50 @@ textplain_textsearch_bounds(struct content *c,
/**
- * create a selection object suitable for this content
+ * invalidate a region based on offsets into the text cauing a redraw
*/
static nserror
-textplain_create_selection(struct content *c, struct selection **sel_out)
+textplain_textselection_redraw(struct content *c,
+ unsigned start_idx,
+ unsigned end_idx)
{
- struct selection *sel;
- sel = selection_create(c, false);
- if (sel == NULL) {
- return NSERROR_NOMEM;
+ struct rect r;
+
+ if (end_idx <= start_idx) {
+ return NSERROR_BAD_PARAMETER;
}
- selection_init(sel, NULL, NULL);
+ textplain_coords_from_range(c, start_idx, end_idx, &r);
- *sel_out = sel;
+ content__request_redraw(c, r.x0, r.y0, r.x1 - r.x0, r.y1 - r.y0);
+
+ return NSERROR_OK;
+}
+
+static nserror
+textplain_textselection_copy(struct content *c,
+ unsigned start_idx,
+ unsigned end_idx,
+ struct selection_string *selstr)
+{
+ const char *text;
+ size_t length;
+ bool res;
+
+ text = textplain_get_raw_data(c, start_idx, end_idx, &length);
+ res = selection_string_append(text, length, false, NULL, selstr);
+ if (res == false) {
+ return NSERROR_NOMEM;
+ }
return NSERROR_OK;
}
+static nserror
+textplain_textselection_get_end(struct content *c, unsigned *end_idx)
+{
+ *end_idx = textplain_size(c);
+ return NSERROR_OK;
+}
/**
* plain text content handler table
@@ -1508,7 +1627,9 @@ static const content_handler textplain_content_handler = {
.type = textplain_content_type,
.textsearch_find = textplain_textsearch_find,
.textsearch_bounds = textplain_textsearch_bounds,
- .create_selection = textplain_create_selection,
+ .textselection_redraw = textplain_textselection_redraw,
+ .textselection_copy = textplain_textselection_copy,
+ .textselection_get_end = textplain_textselection_get_end,
.no_share = true,
};
@@ -1553,84 +1674,3 @@ size_t textplain_size(struct content *c)
return text->utf8_data_size;
}
-
-
-/* exported interface documented in html/textplain.h */
-void
-textplain_coords_from_range(struct content *c,
- unsigned start,
- unsigned end,
- struct rect *r)
-{
- textplain_content *text = (textplain_content *) c;
- float line_height = textplain_line_height();
- char *utf8_data;
- struct textplain_line *line;
- unsigned lineno = 0;
- unsigned nlines;
-
- assert(c != NULL);
- assert(start <= end);
- assert(end <= text->utf8_data_size);
-
- utf8_data = text->utf8_data;
- nlines = text->physical_line_count;
- line = text->physical_line;
-
- /* find start */
- lineno = textplain_find_line(c, start);
-
- r->y0 = (int)(MARGIN + lineno * line_height);
-
- if (lineno + 1 <= nlines || line[lineno + 1].start >= end) {
- /* \todo - it may actually be more efficient just to
- * run forwards most of the time
- */
-
- /* find end */
- lineno = textplain_find_line(c, end);
-
- r->x0 = 0;
- r->x1 = text->formatted_width;
- } else {
- /* single line */
- const char *text = utf8_data + line[lineno].start;
-
- r->x0 = textplain_coord_from_offset(text,
- start - line[lineno].start,
- line[lineno].length);
-
- r->x1 = textplain_coord_from_offset(text,
- end - line[lineno].start,
- line[lineno].length);
- }
-
- r->y1 = (int)(MARGIN + (lineno + 1) * line_height);
-}
-
-
-/* exported interface documented in html/textplain.h */
-char *
-textplain_get_raw_data(struct content *c,
- unsigned start,
- unsigned end,
- size_t *plen)
-{
- textplain_content *text = (textplain_content *) c;
- size_t utf8_size;
-
- assert(c != NULL);
-
- utf8_size = text->utf8_data_size;
-
- /* any text at all? */
- if (!utf8_size) return NULL;
-
- /* clamp to valid offset range */
- if (start >= utf8_size) start = utf8_size;
- if (end >= utf8_size) end = utf8_size;
-
- *plen = end - start;
-
- return text->utf8_data + start;
-}
diff --git a/content/handlers/text/textplain.h
b/content/handlers/text/textplain.h
index 716397a..b94ee33 100644
--- a/content/handlers/text/textplain.h
+++ b/content/handlers/text/textplain.h
@@ -46,31 +46,4 @@ nserror textplain_init(void);
size_t textplain_size(struct content *c);
-/**
- * Given a range of byte offsets within a UTF8 textplain content,
- * return a box that fully encloses the text
- *
- * \param[in] c content of type CONTENT_TEXTPLAIN
- * \param[in] start byte offset of start of text range
- * \param[in] end byte offset of end
- * \param[out] r rectangle to be completed
- */
-void textplain_coords_from_range(struct content *c,
- unsigned start, unsigned end, struct rect *r);
-
-
-/**
- * Return a pointer to the raw UTF-8 data, as opposed to the reformatted
- * text to fit the window width. Thus only hard newlines are preserved
- * in the saved/copied text of a selection.
- *
- * \param[in] c content of type CONTENT_TEXTPLAIN
- * \param[in] start starting byte offset within UTF-8 text
- * \param[in] end ending byte offset
- * \param[out] plen receives validated length
- * \return pointer to text, or NULL if no text
- */
-char *textplain_get_raw_data(struct content *c, unsigned start, unsigned end,
size_t *plen);
-
-
#endif
diff --git a/content/textsearch.c b/content/textsearch.c
index ae3c8a2..18f9073 100644
--- a/content/textsearch.c
+++ b/content/textsearch.c
@@ -23,6 +23,8 @@
*/
#include <stdbool.h>
+#include <stddef.h>
+#include <stdlib.h>
#include "utils/errors.h"
#include "utils/utils.h"
@@ -163,7 +165,6 @@ static void free_matches(struct textsearch_context
*textsearch)
static void search_show_all(bool all, struct textsearch_context *context)
{
struct list_entry *a;
- nserror res;
for (a = context->found->next; a; a = a->next) {
bool add = true;
@@ -177,9 +178,8 @@ static void search_show_all(bool all, struct
textsearch_context *context)
if (add && !a->sel) {
- res = context->c->handler->create_selection(context->c,
- &a->sel);
- if (res == NSERROR_OK) {
+ a->sel = selection_create(context->c);
+ if (a->sel != NULL) {
selection_set_position(a->sel,
a->start_idx,
a->end_idx);
@@ -424,8 +424,7 @@ content_textsearch_create(struct content *c,
content_type type;
if ((c->handler->textsearch_find == NULL) ||
- (c->handler->textsearch_bounds == NULL) ||
- (c->handler->create_selection == NULL)){
+ (c->handler->textsearch_bounds == NULL)) {
/*
* content has no free text find handler so searching
* is unsupported.
@@ -628,7 +627,6 @@ content_textsearch_ishighlighted(struct textsearch_context
*textsearch,
for (cur = textsearch->found->next; cur != NULL; cur = cur->next) {
if (cur->sel &&
- selection_defined(cur->sel) &&
selection_highlighted(cur->sel,
start_offset,
end_offset,
diff --git a/desktop/selection.c b/desktop/selection.c
index 5955054..06cfdae 100644
--- a/desktop/selection.c
+++ b/desktop/selection.c
@@ -22,45 +22,18 @@
* implementation of text selection within browser windows.
*/
-#include <assert.h>
-#include <stdio.h>
#include <stdlib.h>
-#include <stdbool.h>
-#include <string.h>
-#include <dom/dom.h>
-#include "utils/log.h"
-#include "utils/utf8.h"
-#include "utils/utils.h"
-#include "netsurf/form.h"
-#include "html/box.h"
-#include "html/box_inspect.h"
-#include "html/private.h"
-#include "html/font.h"
-#include "text/textplain.h"
+#include "netsurf/clipboard.h"
#include "netsurf/browser_window.h"
+#include "netsurf/window.h"
+#include "utils/utils.h"
+#include "content/content_protected.h"
-#include "netsurf/mouse.h"
#include "desktop/browser_private.h"
-#include "netsurf/plotters.h"
-#include "desktop/save_text.h"
-#include "desktop/selection.h"
-#include "netsurf/clipboard.h"
-#include "netsurf/window.h"
#include "desktop/gui_internal.h"
+#include "desktop/selection.h"
-/**
- * Text selection works by labelling each node in the box tree with its
- * start index in the textual representation of the tree's content.
- */
-
-#define SPACE_LEN(b) ((b->space == 0) ? 0 : 1)
-
-
-struct rdw_info {
- bool inited;
- struct rect r;
-};
struct selection_string {
char *buffer;
@@ -72,303 +45,6 @@ struct selection_string {
};
-typedef bool (*seln_traverse_handler)(const char *text,
- size_t length,
- struct box *box,
- const nscss_len_ctx *len_ctx,
- void *handle,
- const char *whitespace_text,
- size_t whitespace_length);
-
-
-/**
- * Label each text box in the given box subtree with its position
- * in a textual representation of the content.
- *
- * \param box The box at root of subtree
- * \param idx current position within textual representation
- * \return updated position
- */
-static unsigned selection_label_subtree(struct box *box, unsigned idx)
-{
- struct box *child = box->children;
-
- box->byte_offset = idx;
-
- if (box->text) {
- idx += box->length + SPACE_LEN(box);
- }
-
- while (child) {
- if (child->list_marker) {
- idx = selection_label_subtree(child->list_marker, idx);
- }
-
- idx = selection_label_subtree(child, idx);
- child = child->next;
- }
-
- return idx;
-}
-
-
-/**
- * Tests whether a text box lies partially within the given range of
- * byte offsets, returning the start and end indexes of the bytes
- * that are enclosed.
- *
- * \param box box to be tested
- * \param start_idx byte offset of start of range
- * \param end_idx byte offset of end of range
- * \param start_offset receives the start offset of the selected part
- * \param end_offset receives the end offset of the selected part
- * \return true iff the range encloses at least part of the box
- */
-static bool
-selected_part(struct box *box,
- unsigned start_idx,
- unsigned end_idx,
- unsigned *start_offset,
- unsigned *end_offset)
-{
- size_t box_length = box->length + SPACE_LEN(box);
-
- if (box_length > 0) {
- if ((box->byte_offset >= start_idx) &&
- (box->byte_offset + box_length <= end_idx)) {
-
- /* fully enclosed */
- *start_offset = 0;
- *end_offset = box_length;
- return true;
- } else if ((box->byte_offset + box_length > start_idx) &&
- (box->byte_offset < end_idx)) {
- /* partly enclosed */
- int offset = 0;
- int len;
-
- if (box->byte_offset < start_idx) {
- offset = start_idx - box->byte_offset;
- }
-
- len = box_length - offset;
-
- if (box->byte_offset + box_length > end_idx) {
- len = end_idx - (box->byte_offset + offset);
- }
-
- *start_offset = offset;
- *end_offset = offset + len;
-
- return true;
- }
- }
- return false;
-}
-
-
-/**
- * Traverse the given box subtree, calling the handler function (with
- * its handle) for all boxes that lie (partially) within the given
- * range
- *
- * \param box box subtree
- * \param len_ctx Length conversion context.
- * \param start_idx start of range within textual representation (bytes)
- * \param end_idx end of range
- * \param handler handler function to call
- * \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
- */
-static bool
-traverse_tree(struct box *box,
- const nscss_len_ctx *len_ctx,
- unsigned start_idx,
- unsigned end_idx,
- seln_traverse_handler handler,
- void *handle,
- save_text_whitespace *before,
- bool *first,
- bool do_marker)
-{
- struct box *child;
- const char *whitespace_text = "";
- size_t whitespace_length = 0;
-
- assert(box);
-
- /* If selection starts inside marker */
- if (box->parent &&
- 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,
- len_ctx,
- start_idx,
- end_idx,
- 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;
- }
-
- /* read before calling the handler in case it modifies the tree */
- child = box->children;
-
- /* If nicely formatted output of the selected text is required, work
- * out what whitespace should be placed before the next bit of text */
- if (before) {
- save_text_solve_whitespace(box,
- first,
- before,
- &whitespace_text,
- &whitespace_length);
- } else {
- whitespace_text = NULL;
- }
-
- if ((box->type != BOX_BR) &&
- !((box->type == BOX_FLOAT_LEFT ||
- box->type == BOX_FLOAT_RIGHT) &&
- !box->text)) {
- unsigned start_offset;
- unsigned end_offset;
-
- if (selected_part(box,
- start_idx,
- end_idx,
- &start_offset,
- &end_offset)) {
- if (!handler(box->text + start_offset,
- min(box->length, end_offset) -
start_offset,
- box,
- len_ctx,
- handle,
- whitespace_text,
- whitespace_length)) {
- return false;
- }
- if (before) {
- *first = false;
- *before = WHITESPACE_NONE;
- }
- }
- }
-
- /* find the first child that could lie partially within the selection;
- * this is important at the top-levels of the tree for pruning subtrees
- * that lie entirely before the selection */
-
- if (child) {
- struct box *next = child->next;
-
- while (next && next->byte_offset < start_idx) {
- child = next;
- next = child->next;
- }
-
- while (child) {
- /* read before calling the handler in case it modifies
- * the tree */
- struct box *next = child->next;
-
- if (!traverse_tree(child,
- len_ctx,
- start_idx,
- end_idx,
- handler,
- handle,
- before,
- first,
- false)) {
- return false;
- }
-
- child = next;
- }
- }
-
- return true;
-}
-
-
-/**
- * Selection traversal handler for redrawing the screen when the selection
- * has been altered.
- *
- * \param text pointer to text string
- * \param length length of text to be appended (bytes)
- * \param box pointer to text box being (partially) added
- * \param handle unused handle, we don't need one
- * \param whitespace_text whitespace to place before text for formatting
- * may be NULL
- * \param whitespace_length length of whitespace_text
- * \return true iff successful and traversal should continue
- */
-static bool
-redraw_handler(const char *text,
- size_t length,
- struct box *box,
- const nscss_len_ctx *len_ctx,
- void *handle,
- const char *whitespace_text,
- size_t whitespace_length)
-{
- struct rdw_info *r = (struct rdw_info*)handle;
- int width, height;
- int x, y;
-
- if (!box) {
- return true;
- }
-
- /* \todo - it should be possible to reduce the redrawn area by
- * considering the 'text', 'length' and 'space' parameters */
- box_coords(box, &x, &y);
-
- 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 != 0)) {
- width += box->space;
- }
-
- if (r->inited) {
- if (x < r->r.x0) r->r.x0 = x;
- if (y < r->r.y0) r->r.y0 = y;
- if (x + width > r->r.x1) r->r.x1 = x + width;
- if (y + height > r->r.y1) r->r.y1 = y + height;
- } else {
- r->inited = true;
- r->r.x0 = x;
- r->r.y0 = y;
- r->r.x1 = x + width;
- r->r.y1 = y + height;
- }
-
- return true;
-}
-
-
/**
* Redraws the given range of text.
*
@@ -376,43 +52,20 @@ redraw_handler(const char *text,
* \param start_idx start offset (bytes) within the textual representation
* \param end_idx end offset (bytes) within the textual representation
*/
-static void
+static nserror
selection_redraw(struct selection *s, unsigned start_idx, unsigned end_idx)
{
- struct rdw_info rdw;
-
- assert(end_idx >= start_idx);
- rdw.inited = false;
-
- if (s->root) {
- if (!traverse_tree(s->root,
- &s->len_ctx,
- start_idx,
- end_idx,
- redraw_handler,
- &rdw,
- NULL,
- NULL,
- false))
- return;
+ nserror res;
+
+ if (s->c->handler->textselection_redraw != NULL) {
+ res = s->c->handler->textselection_redraw(s->c,
+ start_idx,
+ end_idx);
} else {
- if ((s->is_html == false) &&
- (end_idx > start_idx)) {
- textplain_coords_from_range(s->c,
- start_idx,
- end_idx,
- &rdw.r);
- rdw.inited = true;
- }
+ res = NSERROR_NOT_IMPLEMENTED;
}
- if (rdw.inited) {
- content__request_redraw(s->c,
- rdw.r.x0,
- rdw.r.y0,
- rdw.r.x1 - rdw.r.x0,
- rdw.r.y1 - rdw.r.y0);
- }
+ return res;
}
@@ -484,35 +137,22 @@ static void selection_set_end(struct selection *s,
unsigned offset)
* \return false iff traversal abandoned part-way through
*/
static bool
-selection_traverse(struct selection *s,
- seln_traverse_handler handler,
- void *handle)
+selection_copy(struct selection *s, struct selection_string *selstr)
{
- save_text_whitespace before = WHITESPACE_NONE;
- bool first = true;
- const char *text;
- size_t length;
-
- if (!s->defined) {
- return true; /* easy case, nothing to do */
- }
+ nserror res;
- if (s->root) {
- /* HTML */
- return traverse_tree(s->root, &s->len_ctx,
- s->start_idx, s->end_idx,
- handler, handle,
- &before, &first, false);
+ if (s->c->handler->textselection_copy != NULL) {
+ res = s->c->handler->textselection_copy(s->c,
+ s->start_idx,
+ s->end_idx,
+ selstr);
+ } else {
+ res = NSERROR_NOT_IMPLEMENTED;
}
- /* Text */
- text = textplain_get_raw_data(s->c, s->start_idx, s->end_idx, &length);
-
- if (text &&
- !handler(text, length, NULL, NULL, handle, NULL, 0)) {
+ if (res != NSERROR_OK) {
return false;
}
-
return true;
}
@@ -527,7 +167,7 @@ selection_traverse(struct selection *s,
* \param sel_string string to append to, may be resized
* \return true iff successful
*/
-static bool
+bool
selection_string_append(const char *text,
size_t length,
bool space,
@@ -589,86 +229,25 @@ selection_string_append(const char *text,
}
-/**
- * Selection traversal routine for appending text to a string
- *
- * \param text pointer to text being added, or NULL for newline
- * \param length length of text to be appended (bytes)
- * \param box pointer to text box, or NULL if from textplain
- * \param len_ctx Length conversion context
- * \param handle selection string to append to
- * \param whitespace_text whitespace to place before text for formatting
- * may be NULL
- * \param whitespace_length length of whitespace_text
- * \return true iff successful and traversal should continue
- */
-static bool
-selection_copy_handler(const char *text,
- size_t length,
- struct box *box,
- const nscss_len_ctx *len_ctx,
- void *handle,
- const char *whitespace_text,
- size_t whitespace_length)
-{
- bool add_space = false;
- plot_font_style_t style;
- plot_font_style_t *pstyle = NULL;
-
- /* add any whitespace which precedes the text from this box */
- if (whitespace_text != NULL &&
- whitespace_length > 0) {
- if (!selection_string_append(whitespace_text,
- whitespace_length,
- false,
- pstyle,
- handle)) {
- return false;
- }
- }
-
- if (box != NULL) {
- /* HTML */
- add_space = (box->space != 0);
-
- if (box->style != NULL) {
- /* Override default font style */
- font_plot_style_from_css(len_ctx, box->style, &style);
- pstyle = &style;
- } else {
- /* If there's no style, there must be no text */
- assert(box->text == NULL);
- }
- }
-
- /* add the text from this box */
- if (!selection_string_append(text, length, add_space, pstyle, handle)) {
- return false;
- }
-
- return true;
-}
-
-
/* exported interface documented in desktop/selection.h */
-struct selection *selection_create(struct content *c, bool is_html)
+struct selection *selection_create(struct content *c)
{
- struct selection *s;
- s = calloc(1, sizeof(struct selection));
- if (s) {
- selection_prepare(s, c, is_html);
+ struct selection *sel;
+ sel = calloc(1, sizeof(struct selection));
+ if (sel) {
+ selection_prepare(sel, c);
+ selection_init(sel);
}
- return s;
+ return sel;
}
/* exported interface documented in desktop/selection.h */
-void selection_prepare(struct selection *s, struct content *c, bool is_html)
+void selection_prepare(struct selection *s, struct content *c)
{
if (s) {
s->c = c;
- s->is_html = is_html;
s->root = NULL;
s->drag_state = DRAG_NONE;
s->max_idx = 0;
@@ -690,23 +269,12 @@ void selection_destroy(struct selection *s)
/* exported interface documented in desktop/selection.h */
-void selection_reinit(struct selection *s, struct box *root)
+void selection_reinit(struct selection *s)
{
- unsigned root_idx;
-
- assert(s);
+ s->max_idx = 0;
- root_idx = 0;
-
- s->root = root;
- if (root) {
- s->max_idx = selection_label_subtree(root, root_idx);
- } else {
- if (s->is_html == false) {
- s->max_idx = textplain_size(s->c);
- } else {
- s->max_idx = 0;
- }
+ if (s->c->handler->textselection_get_end != NULL) {
+ s->c->handler->textselection_get_end(s->c, &s->max_idx);
}
if (s->defined) {
@@ -722,10 +290,7 @@ void selection_reinit(struct selection *s, struct box
*root)
/* exported interface documented in desktop/selection.h */
-void
-selection_init(struct selection *s,
- struct box *root,
- const nscss_len_ctx *len_ctx)
+void selection_init(struct selection *s)
{
if (s->defined) {
selection_clear(s, true);
@@ -735,15 +300,8 @@ selection_init(struct selection *s,
s->start_idx = 0;
s->end_idx = 0;
s->drag_state = DRAG_NONE;
- if (len_ctx != NULL) {
- s->len_ctx = *len_ctx;
- } else {
- s->len_ctx.vw = 0;
- s->len_ctx.vh = 0;
- s->len_ctx.root_style = NULL;
- }
- selection_reinit(s, root);
+ selection_reinit(s);
}
@@ -761,7 +319,7 @@ selection_click(struct selection *s,
top = browser_window_get_root(top);
- if (selection_defined(s)) {
+ if (s->defined) {
if (idx > s->start_idx) {
if (idx <= s->end_idx) {
pos = 0;
@@ -803,7 +361,7 @@ selection_click(struct selection *s,
} else if (mouse & BROWSER_MOUSE_DRAG_2) {
/* adjust selection, but only if there is one */
- if (!selection_defined(s)) {
+ if (!s->defined) {
return false; /* ignore Adjust drags */
}
@@ -823,7 +381,7 @@ selection_click(struct selection *s,
} else if (mouse & BROWSER_MOUSE_CLICK_2) {
/* ignore Adjust clicks when there's no selection */
- if (!selection_defined(s)) {
+ if (!s->defined) {
return false;
}
@@ -901,7 +459,7 @@ char *selection_get_copy(struct selection *s)
if (s == NULL || !s->defined)
return NULL;
- if (!selection_traverse(s, selection_copy_handler, &sel_string)) {
+ if (!selection_copy(s, &sel_string)) {
free(sel_string.buffer);
free(sel_string.styles);
return NULL;
@@ -929,7 +487,7 @@ bool selection_copy_to_clipboard(struct selection *s)
return false;
}
- if (!selection_traverse(s, selection_copy_handler, &sel_string)) {
+ if (!selection_copy(s, &sel_string)) {
free(sel_string.buffer);
free(sel_string.styles);
return false;
@@ -948,7 +506,7 @@ bool selection_copy_to_clipboard(struct selection *s)
/* exported interface documented in desktop/selection.h */
-void selection_clear(struct selection *s, bool redraw)
+bool selection_clear(struct selection *s, bool redraw)
{
int old_start, old_end;
bool was_defined;
@@ -966,6 +524,8 @@ void selection_clear(struct selection *s, bool redraw)
if (redraw && was_defined) {
selection_redraw(s, old_start, old_end);
}
+
+ return was_defined;
}
@@ -996,9 +556,11 @@ selection_highlighted(const struct selection *s,
unsigned *start_idx,
unsigned *end_idx)
{
- /* caller should have checked first for efficiency */
assert(s);
- assert(s->defined);
+
+ if (!s->defined) {
+ return false;
+ }
if ((end <= s->start_idx) ||
(start >= s->end_idx)) {
@@ -1010,3 +572,24 @@ selection_highlighted(const struct selection *s,
return true;
}
+
+/* exported interface documented in desktop/selection.h */
+bool selection_active(struct selection *s)
+{
+ return s->defined;
+}
+
+bool selection_dragging(struct selection *s)
+{
+ return s->drag_state != DRAG_NONE;
+}
+
+bool selection_dragging_start(struct selection *s)
+{
+ return s->drag_state == DRAG_START;
+}
+
+void selection_drag_end(struct selection *s)
+{
+ s->drag_state = DRAG_NONE;
+}
diff --git a/desktop/selection.h b/desktop/selection.h
index cfaf59b..86ff395 100644
--- a/desktop/selection.h
+++ b/desktop/selection.h
@@ -20,15 +20,16 @@
* Text selection within browser windows (interface).
*/
-#ifndef _NETSURF_DESKTOP_SELECTION_H_
-#define _NETSURF_DESKTOP_SELECTION_H_
+#ifndef NETSURF_DESKTOP_SELECTION_H_
+#define NETSURF_DESKTOP_SELECTION_H_
#include <stdbool.h>
#include "netsurf/mouse.h"
-#include "content/handlers/css/utils.h"
struct box;
struct browser_window;
+struct plot_font_style;
+struct selection_string;
typedef enum {
DRAG_NONE,
@@ -36,16 +37,9 @@ typedef enum {
DRAG_END
} seln_drag_state;
-
-/* this structure should be treated as opaque outside selection.c
- (it's defined here to accelerate selection_defined(s) for reduced
- impact on redraw code) */
-
-struct selection
-{
+struct selection {
struct content *c;
struct box *root;
- nscss_len_ctx len_ctx;
unsigned max_idx; /* total bytes in text representation */
@@ -53,24 +47,23 @@ struct selection
unsigned end_idx;
bool defined;
- bool is_html;
seln_drag_state drag_state;
};
+/**
+ * determine if a selecion is active
+ */
+bool selection_active(struct selection *s);
-/* bool selection_defined(struct selection *s); */
-#define selection_defined(s) ((s)->defined)
-
-/* bool selection_dragging(struct selection *s); */
-#define selection_dragging(s) ((s)->drag_state != DRAG_NONE)
+bool selection_dragging(struct selection *s);
-/* bool selection_dragging_start(struct selection *s); */
-#define selection_dragging_start(s) ((s)->drag_state == DRAG_START)
+bool selection_dragging_start(struct selection *s);
-/** Handles completion of a drag operation */
-/* void selection_drag_end(struct selection *s); */
-#define selection_drag_end(s) ((s)->drag_state = DRAG_NONE)
+/**
+ * Handles completion of a drag operation
+ */
+void selection_drag_end(struct selection *s);
/**
* Creates a new selection object associated with a browser window.
@@ -79,7 +72,7 @@ struct selection
*
* \return new selection context
*/
-struct selection *selection_create(struct content *c, bool is_html);
+struct selection *selection_create(struct content *c);
/**
* Prepare a newly created selection object for use.
@@ -88,9 +81,8 @@ struct selection *selection_create(struct content *c, bool
is_html);
*
* \param s selection object
* \param c content
- * \param is_html true if content is html false if content is textplain
*/
-void selection_prepare(struct selection *s, struct content *c, bool is_html);
+void selection_prepare(struct selection *s, struct content *c);
/**
* Destroys a selection object clearing it if nesessary
@@ -108,9 +100,8 @@ void selection_destroy(struct selection *s);
* Used from text and html content handlers
*
* \param s selection object
- * \param root the root box for html document or NULL for text/plain
*/
-void selection_init(struct selection *s, struct box *root, const nscss_len_ctx
*len_ctx);
+void selection_init(struct selection *s);
/**
* Initialise the selection object to use the given box subtree as its root,
@@ -121,9 +112,8 @@ void selection_init(struct selection *s, struct box *root,
const nscss_len_ctx *
* Used from html content handler
*
* \param s selection object
- * \param root the root box for html document or NULL for text/plain
*/
-void selection_reinit(struct selection *s, struct box *root);
+void selection_reinit(struct selection *s);
/**
* Clears the current selection, optionally causing the screen to be updated.
@@ -133,8 +123,9 @@ void selection_reinit(struct selection *s, struct box
*root);
* \param s selection object
* \param redraw true iff the previously selected region of the browser
* window should be redrawn
+ * \return true if selection was cleared false if not
*/
-void selection_clear(struct selection *s, bool redraw);
+bool selection_clear(struct selection *s, bool redraw);
/**
* Selects all the text within the box subtree controlled by
@@ -218,4 +209,11 @@ char *selection_get_copy(struct selection *s);
*/
bool selection_highlighted(const struct selection *s, unsigned start, unsigned
end, unsigned *start_idx, unsigned *end_idx);
+bool
+selection_string_append(const char *text,
+ size_t length,
+ bool space,
+ struct plot_font_style *style,
+ struct selection_string *sel_string);
+
#endif
--
NetSurf Browser
_______________________________________________
netsurf-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]