[project @ 2006-02-11 18:33:05 by adrianl]

Textarea/selection improvements and fixes

svn path=/import/netsurf/; revision=2072
This commit is contained in:
Adrian Lees 2006-02-11 18:33:05 +00:00
parent 6b6841f07e
commit edded10c0f
6 changed files with 357 additions and 144 deletions

View File

@ -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)) {

View File

@ -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);
}
}

View File

@ -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)

View File

@ -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);
@ -67,6 +74,148 @@ static bool word_left(const char *text, int *poffset, int *pchars);
static bool word_right(const char *text, int len, int *poffset, int *pchars);
/**
* Remove the given text caret from the window by invalidating it
* and causing its former position to be redrawn.
*
* \param c structure describing text caret
*/
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
* 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. */
struct box *inline_container, *text_box;
inline_container = textarea->children;
if (inline_container->y + inline_container->height < y) {
/* below the bottom of the textarea: place caret at end */
text_box = inline_container->last;
assert(text_box->type == BOX_TEXT);
assert(text_box->text);
/** \todo handle errors */
nsfont_position_in_string(text_box->style, text_box->text,
text_box->length,
(unsigned int)(x - text_box->x),
pchar_offset, ppixel_offset);
} else {
/* find the relevant text box */
y -= inline_container->y;
for (text_box = inline_container->children;
text_box &&
text_box->y + text_box->height < y;
text_box = text_box->next)
;
for (; text_box && text_box->type != BOX_BR &&
text_box->y <= y &&
text_box->x + text_box->width < x;
text_box = text_box->next)
;
if (!text_box) {
/* past last text box */
text_box = inline_container->last;
assert(text_box->type == BOX_TEXT);
assert(text_box->text);
nsfont_position_in_string(text_box->style,
text_box->text,
text_box->length,
textarea->width,
pchar_offset, ppixel_offset);
} else {
/* in a text box */
if (text_box->type == BOX_BR)
text_box = text_box->prev;
else if (y < text_box->y && text_box->prev) {
if (text_box->prev->type == BOX_BR) {
assert(text_box->prev->prev);
text_box = text_box->prev->prev;
}
else
text_box = text_box->prev;
}
assert(text_box->type == BOX_TEXT);
assert(text_box->text);
nsfont_position_in_string(text_box->style,
text_box->text,
text_box->length,
(unsigned int)(x - text_box->x),
pchar_offset, ppixel_offset);
}
}
assert(text_box);
return text_box;
}
/**
* Handle clicks in a text area by placing the caret.
*
@ -92,64 +241,11 @@ void browser_window_textarea_click(struct browser_window *bw,
* lines. */
int char_offset = 0, pixel_offset = 0, new_scroll_y;
struct box *inline_container, *text_box;
struct box *inline_container = textarea->children;
struct box *text_box;
inline_container = textarea->children;
if (inline_container->y + inline_container->height < y) {
/* below the bottom of the textarea: place caret at end */
text_box = inline_container->last;
assert(text_box->type == BOX_TEXT);
assert(text_box->text);
/** \todo handle errors */
nsfont_position_in_string(text_box->style, text_box->text,
text_box->length,
textarea->width,
&char_offset, &pixel_offset);
} else {
/* find the relevant text box */
y -= inline_container->y;
for (text_box = inline_container->children;
text_box &&
text_box->y + text_box->height < y;
text_box = text_box->next)
;
for (; text_box && text_box->type != BOX_BR &&
text_box->y <= y &&
text_box->x + text_box->width < x;
text_box = text_box->next)
;
if (!text_box) {
/* past last text box */
text_box = inline_container->last;
assert(text_box->type == BOX_TEXT);
assert(text_box->text);
nsfont_position_in_string(text_box->style,
text_box->text,
text_box->length,
textarea->width,
&char_offset, &pixel_offset);
} else {
/* in a text box */
if (text_box->type == BOX_BR)
text_box = text_box->prev;
else if (y < text_box->y && text_box->prev) {
if (text_box->prev->type == BOX_BR) {
assert(text_box->prev->prev);
text_box = text_box->prev->prev;
}
else
text_box = text_box->prev;
}
assert(text_box->type == BOX_TEXT);
assert(text_box->text);
nsfont_position_in_string(text_box->style,
text_box->text,
text_box->length,
(unsigned int)(x - text_box->x),
&char_offset, &pixel_offset);
}
}
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 +
@ -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;

View File

@ -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,

View File

@ -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) {