summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--desktop/browser.c38
-rw-r--r--desktop/selection.c45
-rw-r--r--desktop/selection.h3
-rw-r--r--desktop/textinput.c282
-rw-r--r--desktop/textinput.h31
-rw-r--r--riscos/textselection.c24
6 files changed, 318 insertions, 105 deletions
diff --git a/desktop/browser.c b/desktop/browser.c
index 506d0b449..d20153721 100644
--- a/desktop/browser.c
+++ b/desktop/browser.c
@@ -903,17 +903,12 @@ void browser_window_mouse_action_html(struct browser_window *bw,
case GADGET_TEXTAREA:
status = messages_get("FormTextarea");
pointer = GUI_POINTER_CARET;
- if (mouse & (BROWSER_MOUSE_MOD_1 |
- BROWSER_MOUSE_MOD_2)) {
- if (text_box) {
- selection_click(bw->sel, text_box,
- mouse, x - box_x,
- y - box_y);
- if (selection_dragging(bw->sel))
- bw->drag_type =
- DRAGGING_SELECTION;
- }
- } else if (mouse & BROWSER_MOUSE_CLICK_1) {
+
+ if (mouse & (BROWSER_MOUSE_CLICK_1 | BROWSER_MOUSE_CLICK_2)) {
+
+ if (text_box && selection_root(bw->sel) != gadget_box)
+ selection_init(bw->sel, gadget_box);
+
browser_window_textarea_click(bw,
mouse,
gadget_box,
@@ -921,15 +916,16 @@ void browser_window_mouse_action_html(struct browser_window *bw,
gadget_box_y,
x - gadget_box_x,
y - gadget_box_y);
- } else if (text_box) {
- if (mouse & (BROWSER_MOUSE_DRAG_1 |
- BROWSER_MOUSE_DRAG_2))
- selection_init(bw->sel, gadget_box);
+ }
- selection_click(bw->sel, text_box, mouse,
- x - box_x, y - box_y);
- if (selection_dragging(bw->sel))
+ if (text_box) {
+ selection_click(bw->sel, text_box, mouse, x - box_x, y - box_y);
+
+ if (selection_dragging(bw->sel)) {
bw->drag_type = DRAGGING_SELECTION;
+ status = messages_get("Selecting");
+ } else
+ status = c->status_message;
}
break;
case GADGET_TEXTBOX:
@@ -1021,6 +1017,12 @@ void browser_window_mouse_action_html(struct browser_window *bw,
} else {
+ /* if clicking in the main page, remove the selection from any text areas */
+ if (text_box &&
+ (mouse & (BROWSER_MOUSE_CLICK_1 | BROWSER_MOUSE_CLICK_2)) &&
+ selection_root(bw->sel) != c->data.html.layout)
+ selection_init(bw->sel, c->data.html.layout);
+
if (text_box && selection_click(bw->sel, text_box, mouse,
x - box_x, y - box_y)) {
diff --git a/desktop/selection.c b/desktop/selection.c
index a33a2068a..2bb8cb4e7 100644
--- a/desktop/selection.c
+++ b/desktop/selection.c
@@ -19,13 +19,31 @@
#include "netsurf/desktop/selection.h"
#include "netsurf/render/box.h"
#include "netsurf/render/font.h"
+#include "netsurf/render/form.h"
#include "netsurf/utils/log.h"
#include "netsurf/utils/utf8.h"
#include "netsurf/utils/utils.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.
+ *
+ * Text input fields and text areas have their own number spaces so that
+ * they can be relabelled more efficiently when editing (rather than relabel
+ * the entire box tree) and so that selections are either wholly within
+ * or wholly without the textarea/input box.
+ */
+
#define IS_TEXT(box) ((box)->text && !(box)->object)
+#define IS_INPUT(box) ((box)->gadget && \
+ ((box)->gadget->type == GADGET_TEXTAREA || (box)->gadget->type == GADGET_TEXTBOX))
+
+/** check whether the given text box is in the same number space as the
+ current selection; number spaces are identified by their uppermost nybble */
+
+#define SAME_SPACE(s, offset) (((s)->max_idx & 0xF0000000U) == ((offset) & 0xF0000000U))
struct rdw_info {
@@ -132,13 +150,22 @@ void selection_destroy(struct selection *s)
void selection_reinit(struct selection *s, struct box *root)
{
+ unsigned root_idx;
+
assert(s);
+ if (s->root == root) {
+ /* keep the same number space as before, because we want
+ to keep the selection too */
+ root_idx = (s->max_idx & 0xF0000000U);
+ }
+ else {
+ static int next_idx = 0;
+ root_idx = (next_idx++) << 28;
+ }
+
s->root = root;
if (root) {
- int root_idx = 0;
- if (root->gadget) root_idx = 0x10000000;
-
s->max_idx = selection_label_subtree(s, root, root_idx);
}
else
@@ -195,7 +222,8 @@ unsigned selection_label_subtree(struct selection *s, struct box *node, unsigned
idx += node->length + node->space;
while (child) {
- idx = selection_label_subtree(s, child, idx);
+ if (!IS_INPUT(child))
+ idx = selection_label_subtree(s, child, idx);
child = child->next;
}
@@ -223,7 +251,7 @@ bool selection_click(struct selection *s, struct box *box,
int pos = -1; /* 0 = inside selection, 1 = after it */
int idx;
- if (!s->root)
+ if (!s->root ||!SAME_SPACE(s, box->byte_offset))
return false; /* not our problem */
nsfont_position_in_string(box->style,
@@ -327,6 +355,9 @@ void selection_track(struct selection *s, struct box *box,
int pixel_offset;
int idx;
+ if (!SAME_SPACE(s, box->byte_offset))
+ return;
+
nsfont_position_in_string(box->style,
box->text,
box->length,
@@ -580,6 +611,7 @@ void selection_redraw(struct selection *s, unsigned start_idx, unsigned end_idx)
{
struct rdw_info rdw;
+if (end_idx < start_idx) LOG(("*** asked to redraw from %d to %d", start_idx, end_idx));
assert(end_idx >= start_idx);
rdw.inited = false;
if (traverse_tree(s->root, start_idx, end_idx, redraw_handler, &rdw) &&
@@ -635,6 +667,8 @@ void selection_select_all(struct selection *s)
old_start = s->start_idx;
old_end = s->end_idx;
+LOG(("selection was %d: %u to %u, max %u", was_defined, old_start, old_end, s->max_idx));
+
s->defined = true;
s->start_idx = 0;
s->end_idx = s->max_idx;
@@ -926,3 +960,4 @@ void selection_update(struct selection *s, size_t byte_offset,
s->end_idx += max(change, byte_offset - s->end_idx);
}
}
+
diff --git a/desktop/selection.h b/desktop/selection.h
index c039e1c0f..57097f3d0 100644
--- a/desktop/selection.h
+++ b/desktop/selection.h
@@ -54,6 +54,9 @@ void selection_destroy(struct selection *s);
void selection_init(struct selection *s, struct box *root);
void selection_reinit(struct selection *s, struct box *root);
+/* struct box *selection_root(struct selection *s); */
+#define selection_root(s) ((s)->root)
+
/* bool selection_defined(struct selection *s); */
#define selection_defined(s) ((s)->defined)
diff --git a/desktop/textinput.c b/desktop/textinput.c
index 9b2863351..a941cc86b 100644
--- a/desktop/textinput.c
+++ b/desktop/textinput.c
@@ -31,6 +31,12 @@
#include "netsurf/utils/utf8.h"
#include "netsurf/utils/utils.h"
+
+/** ghost caret used to indicate the insertion point when dragging text
+ into a textarea/input field */
+struct caret ghost_caret;
+
+
static void browser_window_textarea_callback(struct browser_window *bw,
wchar_t key, void *p);
static void browser_window_input_callback(struct browser_window *bw,
@@ -49,11 +55,12 @@ static void input_update_display(struct browser_window *bw, struct box *input,
bool redraw);
static bool textbox_insert(struct browser_window *bw, struct box *text_box,
unsigned char_offset, const char *utf8, unsigned utf8_len);
-static bool textbox_delete(struct box *text_box, unsigned char_offset,
- unsigned utf8_len);
+static bool textbox_delete(struct browser_window *bw, struct box *text_box,
+ unsigned char_offset, unsigned utf8_len);
static struct box *textarea_insert_break(struct browser_window *bw,
struct box *text_box, size_t char_offset);
-static bool delete_handler(struct box *b, int offset, size_t length);
+static bool delete_handler(struct browser_window *bw, struct box *b,
+ int offset, size_t length);
static struct box *line_start(struct box *text_box);
static struct box *line_end(struct box *text_box);
static struct box *line_above(struct box *text_box);
@@ -68,21 +75,75 @@ static bool word_right(const char *text, int len, int *poffset, int *pchars);
/**
- * Handle clicks in a text area by placing the caret.
+ * Remove the given text caret from the window by invalidating it
+ * and causing its former position to be redrawn.
*
- * \param bw browser window where click occurred
- * \param mouse state of mouse buttons and modifier keys
- * \param textarea textarea box
- * \param box_x position of textarea in global document coordinates
- * \param box_y position of textarea in global document coordinates
- * \param x coordinate of click relative to textarea
- * \param y coordinate of click relative to textarea
+ * \param c structure describing text caret
*/
-void browser_window_textarea_click(struct browser_window *bw,
- browser_mouse_state mouse,
- struct box *textarea,
- int box_x, int box_y,
- int x, int y)
+
+void caret_remove(struct caret *c)
+{
+ if (c->defined) {
+ int w = (c->height + 7) / 8;
+ int xc = c->x;
+ c->defined = false;
+ browser_window_redraw_rect(c->bw, xc - w, c->y, 2 * w, c->height);
+ }
+}
+
+
+/**
+ * Set the given text caret's position within the window (text box
+ * and byte/pixel offsets within the UTF-8 content of that text box)
+ * and draw it.
+ *
+ * \param c structure describing text caret
+ * \param bw browser window containing caret
+ * \param box INLINE box containing caret
+ * \param char_offset byte offset within UTF-8 representation
+ * \param pixel_offset from left side of box
+ */
+
+void caret_set_position(struct caret *c, struct browser_window *bw,
+ struct box *text_box, int char_offset, int pixel_offset)
+{
+ struct rect r;
+ int xc;
+ int w;
+
+ box_bounds(text_box, &r);
+
+ c->bw = bw;
+ c->text_box = text_box;
+ c->char_offset = char_offset;
+
+ c->x = xc = r.x0 + pixel_offset;
+ c->y = r.y0;
+ c->height = r.y1 - r.y0;
+ w = (c->height + 7) / 8;
+
+ c->defined = true;
+
+ browser_window_redraw_rect(c->bw, xc - w, c->y, w * 2, c->height);
+}
+
+
+/**
+ * Given the x,y co-ordinates of a point within a textarea, return the
+ * INLINE box pointer, and the character and pixel offsets within that
+ * box at which the caret should be positioned. (eg. for mouse clicks,
+ * drag-and-drop insertions etc)
+ *
+ * \param textarea the textarea being considered
+ * \param x x ordinate of point
+ * \param y y ordinate of point
+ * \param pchar_offset receives the char offset within the INLINE box
+ * \param ppixel_offset receives the pixel offset within the INLINE box
+ * \return pointer to INLINE box
+ */
+
+struct box *textarea_get_position(struct box *textarea, int x, int y,
+ int *pchar_offset, int *ppixel_offset)
{
/* A textarea is an INLINE_BLOCK containing a single
* INLINE_CONTAINER, which contains the text as runs of INLINE
@@ -91,7 +152,6 @@ void browser_window_textarea_click(struct browser_window *bw,
* constraints are satisfied by using a 0-length INLINE for blank
* lines. */
- int char_offset = 0, pixel_offset = 0, new_scroll_y;
struct box *inline_container, *text_box;
inline_container = textarea->children;
@@ -104,8 +164,8 @@ void browser_window_textarea_click(struct browser_window *bw,
/** \todo handle errors */
nsfont_position_in_string(text_box->style, text_box->text,
text_box->length,
- textarea->width,
- &char_offset, &pixel_offset);
+ (unsigned int)(x - text_box->x),
+ pchar_offset, ppixel_offset);
} else {
/* find the relevant text box */
y -= inline_container->y;
@@ -128,7 +188,7 @@ void browser_window_textarea_click(struct browser_window *bw,
text_box->text,
text_box->length,
textarea->width,
- &char_offset, &pixel_offset);
+ pchar_offset, ppixel_offset);
} else {
/* in a text box */
if (text_box->type == BOX_BR)
@@ -147,10 +207,46 @@ void browser_window_textarea_click(struct browser_window *bw,
text_box->text,
text_box->length,
(unsigned int)(x - text_box->x),
- &char_offset, &pixel_offset);
+ pchar_offset, ppixel_offset);
}
}
+ assert(text_box);
+ return text_box;
+}
+
+
+/**
+ * Handle clicks in a text area by placing the caret.
+ *
+ * \param bw browser window where click occurred
+ * \param mouse state of mouse buttons and modifier keys
+ * \param textarea textarea box
+ * \param box_x position of textarea in global document coordinates
+ * \param box_y position of textarea in global document coordinates
+ * \param x coordinate of click relative to textarea
+ * \param y coordinate of click relative to textarea
+ */
+void browser_window_textarea_click(struct browser_window *bw,
+ browser_mouse_state mouse,
+ struct box *textarea,
+ int box_x, int box_y,
+ int x, int y)
+{
+ /* A textarea is an INLINE_BLOCK containing a single
+ * INLINE_CONTAINER, which contains the text as runs of INLINE
+ * separated by BR. There is at least one INLINE. The first and
+ * last boxes are INLINE. Consecutive BR may not be present. These
+ * constraints are satisfied by using a 0-length INLINE for blank
+ * lines. */
+
+ int char_offset = 0, pixel_offset = 0, new_scroll_y;
+ struct box *inline_container = textarea->children;
+ struct box *text_box;
+
+ text_box = textarea_get_position(textarea, x, y,
+ &char_offset, &pixel_offset);
+
/* scroll to place the caret in the centre of the visible region */
new_scroll_y = inline_container->y + text_box->y +
text_box->height / 2 -
@@ -258,11 +354,24 @@ void browser_window_textarea_callback(struct browser_window *bw,
int prev_offset = char_offset;
char_offset = utf8_prev(text_box->text, char_offset);
- textbox_delete(text_box, char_offset, prev_offset - char_offset);
+ textbox_delete(bw, text_box, char_offset,
+ prev_offset - char_offset);
}
reflow = true;
break;
+ case KEY_DELETE_LINE_END: {
+ struct box *end_box = line_end(text_box);
+ if (end_box != text_box ||
+ char_offset < text_box->length + text_box->space) {
+ /* there's something at the end of the line to delete */
+ textarea_cut(bw, text_box, char_offset,
+ end_box, end_box->length + end_box->space);
+ reflow = true;
+ break;
+ }
+ }
+ /* no break */
case KEY_DELETE_RIGHT: /* delete to right */
if (char_offset >= text_box->length) {
/* at the end of a text box */
@@ -296,7 +405,8 @@ void browser_window_textarea_callback(struct browser_window *bw,
/* delete a character */
int next_offset = utf8_next(text_box->text, text_box->length,
char_offset);
- textbox_delete(text_box, char_offset, next_offset - char_offset);
+ textbox_delete(bw, text_box, char_offset,
+ next_offset - char_offset);
}
reflow = true;
break;
@@ -505,16 +615,12 @@ void browser_window_textarea_callback(struct browser_window *bw,
}
break;
- case KEY_DELETE_LINE_START:
- textarea_cut(bw, line_start(text_box), 0, text_box, char_offset);
+ case KEY_DELETE_LINE_START: {
+ struct box *start_box = line_start(text_box);
+ textarea_cut(bw, start_box, 0, text_box, char_offset);
+ text_box = start_box;
char_offset = 0;
reflow = true;
- break;
-
- case KEY_DELETE_LINE_END: {
- struct box *end_box = line_end(text_box);
- textarea_cut(bw, text_box, char_offset, end_box, end_box->length);
- reflow = true;
}
break;
@@ -522,11 +628,11 @@ void browser_window_textarea_callback(struct browser_window *bw,
return;
}
- /* box_dump(textarea, 0); */
- /* for (struct box *t = inline_container->children; t; t = t->next) {
+ /*
+ box_dump(textarea, 0);
+ for (struct box *t = inline_container->children; t; t = t->next) {
assert(t->type == BOX_TEXT);
assert(t->text);
- assert(t->font);
assert(t->parent == inline_container);
if (t->next) assert(t->next->prev == t);
if (t->prev) assert(t->prev->next == t);
@@ -543,13 +649,17 @@ void browser_window_textarea_callback(struct browser_window *bw,
if (reflow)
textarea_reflow(bw, textarea, inline_container);
- if (text_box->length < char_offset) {
- /* the text box has been split and the caret is in the
- * second part */
- char_offset -= (text_box->length + 1); /* +1 for the space */
- text_box = text_box->next;
- assert(text_box);
- assert(char_offset <= text_box->length);
+ if (text_box->length + text_box->space <= char_offset) {
+ if (text_box->next && text_box->next->type == BOX_TEXT) {
+ /* the text box has been split when reflowing and
+ the caret is in the second part */
+ char_offset -= (text_box->length + text_box->space);
+ text_box = text_box->next;
+ assert(text_box);
+ assert(char_offset <= text_box->length);
+ }
+ else
+ char_offset = text_box->length + text_box->space;
}
nsfont_width(text_box->style, text_box->text,
@@ -755,7 +865,7 @@ void browser_window_input_callback(struct browser_window *bw,
/* Go to the previous valid UTF-8 character */
box_offset = utf8_prev(text_box->text, box_offset);
- textbox_delete(text_box, box_offset,
+ textbox_delete(bw, text_box, box_offset,
prev_offset - box_offset);
changed = true;
}
@@ -784,7 +894,7 @@ void browser_window_input_callback(struct browser_window *bw,
next_offset = utf8_next(text_box->text, text_box->length,
box_offset);
- textbox_delete(text_box, box_offset,
+ textbox_delete(bw, text_box, box_offset,
next_offset - box_offset);
changed = true;
}
@@ -915,11 +1025,10 @@ void browser_window_input_callback(struct browser_window *bw,
break;
case KEY_DELETE_LINE_START:
-
if (box_offset <= 0) return;
/* Text box */
- textbox_delete(text_box, 0, box_offset);
+ textbox_delete(bw, text_box, 0, box_offset);
box_offset = 0;
/* Gadget */
@@ -932,12 +1041,11 @@ void browser_window_input_callback(struct browser_window *bw,
break;
case KEY_DELETE_LINE_END:
-
if (box_offset >= text_box->length)
return;
/* Text box */
- textbox_delete(text_box, box_offset, text_box->length - box_offset);
+ textbox_delete(bw, text_box, box_offset, text_box->length - box_offset);
/* Gadget */
input->gadget->length = form_offset;
input->gadget->value[form_offset] = 0;
@@ -1326,7 +1434,14 @@ void input_update_display(struct browser_window *bw, struct box *input,
bool textbox_insert(struct browser_window *bw, struct box *text_box,
unsigned char_offset, const char *utf8, unsigned utf8_len)
{
- char *text = talloc_realloc(bw->current_content, text_box->text,
+ char *text;
+
+ /* code does not support appending after the optional trailing space
+ (this would require inserting a real space and determining whether
+ the resultant string ends in a space) */
+ assert(char_offset <= text_box->length);
+
+ text = talloc_realloc(bw->current_content, text_box->text,
char, text_box->length + utf8_len + 1);
if (!text) {
warn_user("NoMemory", 0);
@@ -1342,6 +1457,9 @@ bool textbox_insert(struct browser_window *bw, struct box *text_box,
/* nothing should assume that the text is terminated, but just in case */
text_box->text[text_box->length] = 0;
+ selection_update(bw->sel, text_box->byte_offset + char_offset,
+ utf8_len, false);
+
text_box->width = UNKNOWN_WIDTH;
return true;
@@ -1351,23 +1469,44 @@ bool textbox_insert(struct browser_window *bw, struct box *text_box,
/**
* Delete a number of chars from a text box
*
+ * \param bw browser window
* \param text_box text box
* \param char_offset offset within text box (bytes) of first char to delete
* \param utf8_len length (bytes) of chars to be deleted
*/
-bool textbox_delete(struct box *text_box, unsigned char_offset, unsigned utf8_len)
+bool textbox_delete(struct browser_window *bw, struct box *text_box,
+ unsigned char_offset, unsigned utf8_len)
{
- unsigned prev_offset = char_offset + utf8_len;
- if (prev_offset <= text_box->length) {
- memmove(text_box->text + char_offset,
- text_box->text + prev_offset,
- text_box->length - prev_offset);
- text_box->length -= (prev_offset - char_offset);
+ unsigned next_offset = char_offset + utf8_len;
+ if (next_offset <= text_box->length + text_box->space) {
+ /* handle removal of trailing space */
+ if (text_box->space && next_offset > text_box->length) {
+ if (char_offset > 0) {
+ /* is the trailing character still a space? */
+ int tmp = utf8_prev(text_box->text, char_offset);
+ if (isspace(text_box->text[tmp]))
+ char_offset = tmp;
+ else
+ text_box->space = false;
+ }
+ else
+ text_box->space = false;
+ text_box->length = char_offset;
+ }
+ else {
+ memmove(text_box->text + char_offset,
+ text_box->text + next_offset,
+ text_box->length - next_offset);
+ text_box->length -= utf8_len;
+ }
/* nothing should assume that the text is terminated, but just in case */
text_box->text[text_box->length] = 0;
+ selection_update(bw->sel, text_box->byte_offset + char_offset,
+ -(int)utf8_len, false);
+
text_box->width = UNKNOWN_WIDTH;
return true;
}
@@ -1378,21 +1517,27 @@ bool textbox_delete(struct box *text_box, unsigned char_offset, unsigned utf8_le
/**
* Delete some text from a box, or delete the box in its entirety
*
+ * \param bw browser window
* \param b box
* \param offset start offset of text to be deleted (in bytes)
* \param length length of text to be deleted
* \return true iff successful
*/
-bool delete_handler(struct box *b, int offset, size_t length)
+bool delete_handler(struct browser_window *bw, struct box *b,
+ int offset, size_t length)
{
- if (offset <= 0 && length >= b->length) {
+ if (offset <= 0 && length >= b->length + b->space) {
+ selection_update(bw->sel, b->byte_offset,
+ -(b->length + b->space), false);
+
/* remove the entire box */
box_unlink_and_free(b);
+
return true;
}
else {
- return textbox_delete(b, offset, length);
+ return textbox_delete(bw, b, offset, length);
}
}
@@ -1521,17 +1666,11 @@ bool textarea_cut(struct browser_window *bw,
{
struct box *box = start_box;
bool success = true;
- bool del = true;
+ bool del = false; /* caller expects start_box to persist */
if (!gui_empty_clipboard())
return false;
- if (!start_idx && (!start_box->prev || start_box->prev->type == BOX_BR)) {
- /* deletion would leave two adjacent BRs, so just collapse
- the start box to an empty TEXT rather than deleting it */
- del = false;
- }
-
while (box && box != end_box) {
/* read before deletion, in case the whole box goes */
struct box *next = box->next;
@@ -1552,14 +1691,15 @@ bool textarea_cut(struct browser_window *bw,
}
if (del) {
- if (!delete_handler(box, start_idx,
- box->length - start_idx)) {
+ if (!delete_handler(bw, box, start_idx,
+ (box->length + box->space) - start_idx)) {
gui_commit_clipboard();
return false;
}
}
else
- textbox_delete(box, start_idx, box->length - start_idx);
+ textbox_delete(bw, box, start_idx,
+ (box->length + box->space) - start_idx);
}
del = true;
@@ -1569,13 +1709,13 @@ bool textarea_cut(struct browser_window *bw,
/* and the last box */
if (box) {
- if (gui_add_to_clipboard(box->text + start_idx, end_idx, box->space)) {
+ if (gui_add_to_clipboard(box->text + start_idx, end_idx - start_idx, box->space)) {
if (del) {
- if (!delete_handler(box, start_idx, end_idx - start_idx))
+ if (!delete_handler(bw, box, start_idx, end_idx - start_idx))
success = false;
}
else
- textbox_delete(box, start_idx, end_idx - start_idx);
+ textbox_delete(bw, box, start_idx, end_idx - start_idx);
}
else
success = false;
diff --git a/desktop/textinput.h b/desktop/textinput.h
index c599ca0e1..14ddb35eb 100644
--- a/desktop/textinput.h
+++ b/desktop/textinput.h
@@ -46,12 +46,41 @@ enum input_key {
};
+struct caret
+{
+ bool defined;
+
+ struct browser_window *bw;
+ struct box *text_box;
+ size_t char_offset;
+
+ /* document co-ordinates of bottom left of caret */
+ int x;
+ int y;
+ int height;
+};
+
+
+/** There's a single ghost caret used to implement
+ * drag-and-drop of text into text areas and input fields.
+ */
+
+extern struct caret ghost_caret;
+
+
+void caret_set_position(struct caret *c, struct browser_window *bw,
+ struct box *text_box, int char_offset, int pixel_offset);
+void caret_remove(struct caret *c);
+
+
+struct box *textarea_get_position(struct box *textarea, int x, int y,
+ int *pchar_offset, int *ppixel_offset);
+
void browser_window_textarea_click(struct browser_window *bw,
browser_mouse_state mouse,
struct box *textarea,
int box_x, int box_y,
int x, int y);
-//bool browser_window_textarea_paste(struct browser_window *bw,
void browser_window_input_click(struct browser_window* bw,
struct box *input,
diff --git a/riscos/textselection.c b/riscos/textselection.c
index afafee0a9..5e2ddf750 100644
--- a/riscos/textselection.c
+++ b/riscos/textselection.c
@@ -120,6 +120,8 @@ void ro_gui_selection_drag_end(struct gui_window *g, wimp_dragged *drag)
os_error *error;
int x, y;
+ LOG(("ending text selection drag"));
+
gui_current_drag_type = GUI_DRAG_NONE;
scroll.w = g->window;
@@ -163,8 +165,8 @@ void ro_gui_selection_drag_end(struct gui_window *g, wimp_dragged *drag)
/**
* Selection traversal routine for appending text to the current contents
* of the clipboard.
-
- * \param box pointer to text box being (partially) added
+ *
+ * \param box pointer to text box being (partially) added (or NULL for newline)
* \param offset start offset of text within box (bytes)
* \param length length of text to be appended (bytes)
* \param handle unused handle, we don't need one
@@ -178,7 +180,7 @@ bool copy_handler(struct box *box, int offset, size_t length, void *handle)
size_t len;
if (box) {
- len = min(length, box->length - offset);
+ len = min(length, box->length - offset);
text = box->text + offset;
if (box->space && length > len) space = true;
}
@@ -260,15 +262,17 @@ bool gui_add_to_clipboard(const char *text, size_t length, bool space)
bool gui_commit_clipboard(void)
{
- utf8_convert_ret res;
- char *new_cb;
+ if (clip_length) {
+ utf8_convert_ret res;
+ char *new_cb;
- res = utf8_to_local_encoding(clipboard, clip_length, &new_cb);
- if (res == UTF8_CONVERT_OK) {
- free(clipboard);
- clipboard = new_cb;
+ res = utf8_to_local_encoding(clipboard, clip_length, &new_cb);
+ if (res == UTF8_CONVERT_OK) {
+ free(clipboard);
+ clipboard = new_cb;
/* \todo utf8_to_local_encoding should return the length! */
- clip_alloc = clip_length = strlen(new_cb);
+ clip_alloc = clip_length = strlen(new_cb);
+ }
}
if (!owns_clipboard) {