From edded10c0fab01984b43de8d857cce7b6027b242 Mon Sep 17 00:00:00 2001 From: Adrian Lees Date: Sat, 11 Feb 2006 18:33:05 +0000 Subject: [project @ 2006-02-11 18:33:05 by adrianl] Textarea/selection improvements and fixes svn path=/import/netsurf/; revision=2072 --- desktop/browser.c | 38 +++---- desktop/selection.c | 45 +++++++- desktop/selection.h | 3 + desktop/textinput.c | 282 ++++++++++++++++++++++++++++++++++++------------- desktop/textinput.h | 31 +++++- riscos/textselection.c | 24 +++-- 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) { -- cgit v1.2.3