diff options
author | Michael Drake <tlsa@netsurf-browser.org> | 2013-01-05 15:27:53 +0000 |
---|---|---|
committer | Michael Drake <tlsa@netsurf-browser.org> | 2013-01-05 15:27:53 +0000 |
commit | 1ac2e00134f6174708ce2cec21a96a0ae08f9ad6 (patch) | |
tree | 85e01244cbbcb38d98b7e1a0e2c86609af822794 /desktop/textarea.c | |
parent | 912d3f7690525e4c2124f03c5f8d129d17c33001 (diff) | |
download | netsurf-1ac2e00134f6174708ce2cec21a96a0ae08f9ad6.tar.gz netsurf-1ac2e00134f6174708ce2cec21a96a0ae08f9ad6.tar.bz2 |
Remove forward declaration.
Diffstat (limited to 'desktop/textarea.c')
-rw-r--r-- | desktop/textarea.c | 889 |
1 files changed, 441 insertions, 448 deletions
diff --git a/desktop/textarea.c b/desktop/textarea.c index 92fb02c9e..5c2e26947 100644 --- a/desktop/textarea.c +++ b/desktop/textarea.c @@ -112,130 +112,366 @@ struct textarea { }; -static bool textarea_insert_text(struct textarea *ta, unsigned int index, - const char *text); -static bool textarea_replace_text(struct textarea *ta, unsigned int start, - unsigned int end, const char *text); -static bool textarea_reflow(struct textarea *ta, unsigned int line); -static unsigned int textarea_get_xy_offset(struct textarea *ta, int x, int y); -static bool textarea_set_caret_xy(struct textarea *ta, int x, int y); -static bool textarea_scroll_visible(struct textarea *ta); -static bool textarea_select(struct textarea *ta, int c_start, int c_end); -static bool textarea_select_fragment(struct textarea *ta); + +/** + * Normalises any line endings within the text, replacing CRLF or CR with + * LF as necessary. If the textarea is single line, then all linebreaks are + * converted into spaces. + * + * \param ta Text area + * \param b_start Byte offset to start at + * \param b_len Byte length to check + */ static void textarea_normalise_text(struct textarea *ta, - unsigned int b_start, unsigned int b_len); + unsigned int b_start, unsigned int b_len) +{ + bool multi = (ta->flags & TEXTAREA_MULTILINE) ? true:false; + unsigned int index; + + /* Remove CR characters. If it's a CRLF pair delete it ot replace it + * with LF otherwise. + */ + for (index = 0; index < b_len; index++) { + if (ta->text[b_start + index] == '\r') { + if (b_start + index + 1 <= ta->text_len && + ta->text[b_start + index + 1] == '\n') { + ta->text_len--; + ta->text_utf8_len--; + memmove(ta->text + b_start + index, + ta->text + b_start + index + 1, + ta->text_len - b_start - index); + } + else + ta->text[b_start + index] = '\n'; + } + /* Replace newlines with spaces if this is a single line + * textarea. + */ + if (!multi && (ta->text[b_start + index] == '\n')) + ta->text[b_start + index] = ' '; + } +} -/* exported interface, documented in textarea.h */ -struct textarea *textarea_create(int width, int height, - textarea_flags flags, const plot_font_style_t *style, - textarea_redraw_request_callback redraw_request, void *data) + +/** + * Selects a character range in the textarea and redraws it + * + * \param ta Text area + * \param c_start First character (inclusive) + * \param c_end Last character (exclusive) + * \return true on success false otherwise + */ +static bool textarea_select(struct textarea *ta, int c_start, int c_end) { - struct textarea *ret; + int swap = -1; - if (redraw_request == NULL) { - LOG(("no callback provided")); - return NULL; + /* if start is after end they get swapped, start won't and end will + be selected this way */ + if (c_start > c_end) { + swap = c_start; + c_start = c_end; + c_end = swap; } - ret = malloc(sizeof(struct textarea)); - if (ret == NULL) { - LOG(("malloc failed")); - return NULL; + ta->selection_start = c_start; + ta->selection_end = c_end; + + if (!(ta->flags & TEXTAREA_READONLY)) { + if (swap == -1) + return textarea_set_caret(ta, c_end); + else + return textarea_set_caret(ta, c_start); } - ret->redraw_request = redraw_request; - ret->data = data; - ret->vis_width = width; - ret->vis_height = height; - ret->scroll_x = 0; - ret->scroll_y = 0; - ret->drag_start_char = 0; + ta->redraw_request(ta->data, 0, 0, ta->vis_width, ta->vis_height); + return true; +} - ret->flags = flags; - ret->text = malloc(64); - if (ret->text == NULL) { - LOG(("malloc failed")); - free(ret); - return NULL; - } - ret->text[0] = '\0'; - ret->text_alloc = 64; - ret->text_len = 1; - ret->text_utf8_len = 0; - ret->fstyle = *style; +/** + * Selects a text fragment, relative to current caret position. + * + * \param ta Text area + * \return True on success, false otherwise + */ +static bool textarea_select_fragment(struct textarea * ta) +{ + int caret_pos, sel_start = 0, sel_end = 0, index; + size_t b_start, b_end; - ret->line_height = FIXTOINT(FDIV((FMUL(FLTTOFIX(1.2), FMUL(nscss_screen_dpi, INTTOFIX((style->size / FONT_SIZE_SCALE))))), F_72)); + /* Fragment separators must be suitable for URLs and ordinary text */ + static const char *sep = " /:.\r\n"; - ret->caret_pos.line = ret->caret_pos.char_off = 0; - ret->caret_x = MARGIN_LEFT; - ret->caret_y = 0; - ret->selection_start = -1; - ret->selection_end = -1; + caret_pos = textarea_get_caret(ta); + if (caret_pos < 0) { + return false; + } - ret->line_count = 0; - ret->lines = NULL; + /* Compute byte offset of caret position */ + for (b_start = 0, index = 0; index < caret_pos; + b_start = utf8_next(ta->text, ta->text_len, + b_start), + index++) { + /* Cache the character offset of the last separator */ + if (strchr(sep, ta->text[b_start]) != NULL) { + /* Add one to start to skip over separator */ + sel_start = index + 1; + } + } - return ret; -} + /* Search for next separator, if any */ + for (b_end = b_start; b_end < ta->text_len; + b_end = utf8_next(ta->text, ta->text_len, + b_end), + index++) { + if (strchr(sep, ta->text[b_end]) != NULL) { + sel_end = index; + break; + } + } + if (sel_start < sel_end) { + textarea_select(ta, sel_start, sel_end); + return true; + } + return false; +} -/* exported interface, documented in textarea.h */ -void textarea_destroy(struct textarea *ta) + +/** + * Scrolls a textarea to make the caret visible (doesn't perform a redraw) + * + * \param ta The text area to be scrolled + * \return true if textarea was scrolled false otherwise + */ +static bool textarea_scroll_visible(struct textarea *ta) { - free(ta->text); - free(ta->lines); - free(ta); + int x0, x1, y0, y1, x, y; + int index, b_off; + bool scrolled = false; + + if (ta->caret_pos.char_off == -1) + return false; + + x0 = MARGIN_LEFT; + x1 = ta->vis_width - MARGIN_RIGHT; + y0 = 0; + y1 = ta->vis_height; + + index = textarea_get_caret(ta); + + /* find byte offset of caret position */ + for (b_off = 0; index-- > 0; + b_off = utf8_next(ta->text, ta->text_len, b_off)) + ; /* do nothing */ + + nsfont.font_width(&ta->fstyle, + ta->text + ta->lines[ta->caret_pos.line].b_start, + b_off - ta->lines[ta->caret_pos.line].b_start, + &x); + + /* top-left of caret */ + x += MARGIN_LEFT - ta->scroll_x; + y = ta->line_height * ta->caret_pos.line - ta->scroll_y; + + /* check and change vertical scroll */ + if (y < y0) { + ta->scroll_y -= y0 - y; + scrolled = true; + } else if (y + ta->line_height > y1) { + ta->scroll_y += y + ta->line_height - y1; + scrolled = true; + } + + + /* check and change horizontal scroll */ + if (x < x0) { + ta->scroll_x -= x0 - x ; + scrolled = true; + } else if (x > x1 - 1) { + ta->scroll_x += x - (x1 - 1); + scrolled = true; + } + + return scrolled; } -/* exported interface, documented in textarea.h */ -bool textarea_set_text(struct textarea *ta, const char *text) +/** + * Reflow a text area from the given line onwards + * + * \param ta Text area to reflow + * \param line Line number to begin reflow on + * \return true on success false otherwise + */ +static bool textarea_reflow(struct textarea *ta, unsigned int line) { - unsigned int len = strlen(text) + 1; + char *text; + unsigned int len; + size_t b_off; + int x; + char *space; + unsigned int line_count = 0; - if (len >= ta->text_alloc) { - char *temp = realloc(ta->text, len + 64); - if (temp == NULL) { - LOG(("realloc failed")); + /** \todo pay attention to line parameter */ + /** \todo create horizontal scrollbar if needed */ + + ta->line_count = 0; + + if (ta->lines == NULL) { + ta->lines = + malloc(LINE_CHUNK_SIZE * sizeof(struct line_info)); + if (ta->lines == NULL) { + LOG(("malloc failed")); return false; } - ta->text = temp; - ta->text_alloc = len + 64; } - memcpy(ta->text, text, len); - ta->text_len = len; - ta->text_utf8_len = utf8_length(ta->text); + if (!(ta->flags & TEXTAREA_MULTILINE)) { + /* Single line */ + ta->lines[line_count].b_start = 0; + ta->lines[line_count++].b_length = ta->text_len - 1; - textarea_normalise_text(ta, 0, len); + ta->line_count = line_count; - return textarea_reflow(ta, 0); + return true; + } + + for (len = ta->text_len - 1, text = ta->text; len > 0; + len -= b_off, text += b_off) { + + nsfont.font_split(&ta->fstyle, text, len, + ta->vis_width - MARGIN_LEFT - MARGIN_RIGHT, + &b_off, &x); + + if (line_count > 0 && line_count % LINE_CHUNK_SIZE == 0) { + struct line_info *temp = realloc(ta->lines, + (line_count + LINE_CHUNK_SIZE) * + sizeof(struct line_info)); + if (temp == NULL) { + LOG(("realloc failed")); + return false; + } + + ta->lines = temp; + } + + /* handle LF */ + for (space = text; space <= text + b_off; space++) { + if (*space == '\n') + break; + } + + if (space <= text + b_off) { + /* Found newline; use it */ + ta->lines[line_count].b_start = text - ta->text; + ta->lines[line_count++].b_length = space - text; + + b_off = space + 1 - text; + + if (len - b_off == 0) { + /* reached end of input => add last line */ + ta->lines[line_count].b_start = + text + b_off - ta->text; + ta->lines[line_count++].b_length = 0; + } + + continue; + } + + if (len - b_off > 0) { + /* find last space (if any) */ + for (space = text + b_off; space > text; space--) + if (*space == ' ') + break; + + if (space != text) + b_off = space + 1 - text; + } + + ta->lines[line_count].b_start = text - ta->text; + ta->lines[line_count++].b_length = b_off; + } + + ta->line_count = line_count; + + return true; } -/* exported interface, documented in textarea.h */ -int textarea_get_text(struct textarea *ta, char *buf, unsigned int len) +/** + * get character offset from the beginning of the text for some coordinates + * + * \param ta Text area + * \param x X coordinate + * \param y Y coordinate + * \return character offset + */ +static unsigned int textarea_get_xy_offset(struct textarea *ta, int x, int y) { - if (buf == NULL && len == 0) { - /* want length */ - return ta->text_len; - } else if (buf == NULL) { - /* Can't write to NULL */ - return -1; - } + size_t b_off, temp; + unsigned int c_off; + int line; - if (len < ta->text_len) { - LOG(("buffer too small")); - return -1; - } + if (!ta->line_count) + return 0; - memcpy(buf, ta->text, ta->text_len); + x = x - MARGIN_LEFT + ta->scroll_x; + y = y + ta->scroll_y; - return ta->text_len; + if (x < 0) + x = 0; + + line = y / ta->line_height; + + if (line < 0) + line = 0; + if (ta->line_count - 1 < line) + line = ta->line_count - 1; + + nsfont.font_position_in_string(&ta->fstyle, + ta->text + ta->lines[line].b_start, + ta->lines[line].b_length, x, &b_off, &x); + + /* If the calculated byte offset corresponds with the number of bytes + * in the line, and the line has been soft-wrapped, then ensure the + * caret offset is before the trailing space character, rather than + * after it. Otherwise, the caret will be placed at the start of the + * following line, which is undesirable. + */ + if (b_off == (unsigned)ta->lines[line].b_length && + ta->text[ta->lines[line].b_start + + ta->lines[line].b_length - 1] == ' ') + b_off--; + + for (temp = 0, c_off = 0; temp < b_off + ta->lines[line].b_start; + temp = utf8_next(ta->text, ta->text_len, temp)) + c_off++; + + return c_off; +} + + +/** + * Set the caret's position + * + * \param ta Text area + * \param x X position of caret in a window relative to text area top left + * \param y Y position of caret in a window relative to text area top left + * \return true on success false otherwise + */ +static bool textarea_set_caret_xy(struct textarea *ta, int x, int y) +{ + unsigned int c_off; + + if (ta->flags & TEXTAREA_READONLY) + return true; + + c_off = textarea_get_xy_offset(ta, x, y); + return textarea_set_caret(ta, c_off); } @@ -247,7 +483,7 @@ int textarea_get_text(struct textarea *ta, char *buf, unsigned int len) * \param text UTF-8 text to insert * \return false on memory exhaustion, true otherwise */ -bool textarea_insert_text(struct textarea *ta, unsigned int index, +static bool textarea_insert_text(struct textarea *ta, unsigned int index, const char *text) { unsigned int b_len = strlen(text); @@ -301,7 +537,7 @@ bool textarea_insert_text(struct textarea *ta, unsigned int index, * \param text UTF-8 text to insert * \return false on memory exhaustion, true otherwise */ -bool textarea_replace_text(struct textarea *ta, unsigned int start, +static bool textarea_replace_text(struct textarea *ta, unsigned int start, unsigned int end, const char *text) { unsigned int b_len = strlen(text); @@ -362,6 +598,122 @@ bool textarea_replace_text(struct textarea *ta, unsigned int start, } + + +/* exported interface, documented in textarea.h */ +struct textarea *textarea_create(int width, int height, + textarea_flags flags, const plot_font_style_t *style, + textarea_redraw_request_callback redraw_request, void *data) +{ + struct textarea *ret; + + if (redraw_request == NULL) { + LOG(("no callback provided")); + return NULL; + } + + ret = malloc(sizeof(struct textarea)); + if (ret == NULL) { + LOG(("malloc failed")); + return NULL; + } + + ret->redraw_request = redraw_request; + ret->data = data; + ret->vis_width = width; + ret->vis_height = height; + ret->scroll_x = 0; + ret->scroll_y = 0; + ret->drag_start_char = 0; + + + ret->flags = flags; + ret->text = malloc(64); + if (ret->text == NULL) { + LOG(("malloc failed")); + free(ret); + return NULL; + } + ret->text[0] = '\0'; + ret->text_alloc = 64; + ret->text_len = 1; + ret->text_utf8_len = 0; + + ret->fstyle = *style; + + ret->line_height = FIXTOINT(FDIV((FMUL(FLTTOFIX(1.2), + FMUL(nscss_screen_dpi, + INTTOFIX((style->size / FONT_SIZE_SCALE))))), F_72)); + + ret->caret_pos.line = ret->caret_pos.char_off = 0; + ret->caret_x = MARGIN_LEFT; + ret->caret_y = 0; + ret->selection_start = -1; + ret->selection_end = -1; + + ret->line_count = 0; + ret->lines = NULL; + + return ret; +} + + +/* exported interface, documented in textarea.h */ +void textarea_destroy(struct textarea *ta) +{ + free(ta->text); + free(ta->lines); + free(ta); +} + + +/* exported interface, documented in textarea.h */ +bool textarea_set_text(struct textarea *ta, const char *text) +{ + unsigned int len = strlen(text) + 1; + + if (len >= ta->text_alloc) { + char *temp = realloc(ta->text, len + 64); + if (temp == NULL) { + LOG(("realloc failed")); + return false; + } + ta->text = temp; + ta->text_alloc = len + 64; + } + + memcpy(ta->text, text, len); + ta->text_len = len; + ta->text_utf8_len = utf8_length(ta->text); + + textarea_normalise_text(ta, 0, len); + + return textarea_reflow(ta, 0); +} + + +/* exported interface, documented in textarea.h */ +int textarea_get_text(struct textarea *ta, char *buf, unsigned int len) +{ + if (buf == NULL && len == 0) { + /* want length */ + return ta->text_len; + } else if (buf == NULL) { + /* Can't write to NULL */ + return -1; + } + + if (len < ta->text_len) { + LOG(("buffer too small")); + return -1; + } + + memcpy(buf, ta->text, ta->text_len); + + return ta->text_len; +} + + /* exported interface, documented in textarea.h */ bool textarea_set_caret(struct textarea *ta, int caret) { @@ -464,7 +816,7 @@ bool textarea_set_caret(struct textarea *ta, int caret) ta->text + ta->lines[ta->caret_pos.line].b_start, b_off - ta->lines[ta->caret_pos.line].b_start, - &x); + &x); x += MARGIN_LEFT - ta->scroll_x; ta->caret_x = x; @@ -496,79 +848,6 @@ bool textarea_set_caret(struct textarea *ta, int caret) } -/** - * get character offset from the beginning of the text for some coordinates - * - * \param ta Text area - * \param x X coordinate - * \param y Y coordinate - * \return character offset - */ -unsigned int textarea_get_xy_offset(struct textarea *ta, int x, int y) -{ - size_t b_off, temp; - unsigned int c_off; - int line; - - if (!ta->line_count) - return 0; - - x = x - MARGIN_LEFT + ta->scroll_x; - y = y + ta->scroll_y; - - if (x < 0) - x = 0; - - line = y / ta->line_height; - - if (line < 0) - line = 0; - if (ta->line_count - 1 < line) - line = ta->line_count - 1; - - nsfont.font_position_in_string(&ta->fstyle, - ta->text + ta->lines[line].b_start, - ta->lines[line].b_length, x, &b_off, &x); - - /* If the calculated byte offset corresponds with the number of bytes - * in the line, and the line has been soft-wrapped, then ensure the - * caret offset is before the trailing space character, rather than - * after it. Otherwise, the caret will be placed at the start of the - * following line, which is undesirable. - */ - if (b_off == (unsigned)ta->lines[line].b_length && - ta->text[ta->lines[line].b_start + - ta->lines[line].b_length - 1] == ' ') - b_off--; - - for (temp = 0, c_off = 0; temp < b_off + ta->lines[line].b_start; - temp = utf8_next(ta->text, ta->text_len, temp)) - c_off++; - - return c_off; -} - - -/** - * Set the caret's position - * - * \param ta Text area - * \param x X position of caret in a window relative to text area top left - * \param y Y position of caret in a window relative to text area top left - * \return true on success false otherwise - */ -bool textarea_set_caret_xy(struct textarea *ta, int x, int y) -{ - unsigned int c_off; - - if (ta->flags & TEXTAREA_READONLY) - return true; - - c_off = textarea_get_xy_offset(ta, x, y); - return textarea_set_caret(ta, c_off); -} - - /* exported interface, documented in textarea.h */ int textarea_get_caret(struct textarea *ta) { @@ -587,107 +866,6 @@ int textarea_get_caret(struct textarea *ta) return c_off + ta->caret_pos.char_off; } -/** - * Reflow a text area from the given line onwards - * - * \param ta Text area to reflow - * \param line Line number to begin reflow on - * \return true on success false otherwise - */ -bool textarea_reflow(struct textarea *ta, unsigned int line) -{ - char *text; - unsigned int len; - size_t b_off; - int x; - char *space; - unsigned int line_count = 0; - - /** \todo pay attention to line parameter */ - /** \todo create horizontal scrollbar if needed */ - - ta->line_count = 0; - - if (ta->lines == NULL) { - ta->lines = - malloc(LINE_CHUNK_SIZE * sizeof(struct line_info)); - if (ta->lines == NULL) { - LOG(("malloc failed")); - return false; - } - } - - if (!(ta->flags & TEXTAREA_MULTILINE)) { - /* Single line */ - ta->lines[line_count].b_start = 0; - ta->lines[line_count++].b_length = ta->text_len - 1; - - ta->line_count = line_count; - - return true; - } - - for (len = ta->text_len - 1, text = ta->text; len > 0; - len -= b_off, text += b_off) { - - nsfont.font_split(&ta->fstyle, text, len, - ta->vis_width - MARGIN_LEFT - MARGIN_RIGHT, - &b_off, &x); - - if (line_count > 0 && line_count % LINE_CHUNK_SIZE == 0) { - struct line_info *temp = realloc(ta->lines, - (line_count + LINE_CHUNK_SIZE) * - sizeof(struct line_info)); - if (temp == NULL) { - LOG(("realloc failed")); - return false; - } - - ta->lines = temp; - } - - /* handle LF */ - for (space = text; space <= text + b_off; space++) { - if (*space == '\n') - break; - } - - if (space <= text + b_off) { - /* Found newline; use it */ - ta->lines[line_count].b_start = text - ta->text; - ta->lines[line_count++].b_length = space - text; - - b_off = space + 1 - text; - - if (len - b_off == 0) { - /* reached end of input => add last line */ - ta->lines[line_count].b_start = - text + b_off - ta->text; - ta->lines[line_count++].b_length = 0; - } - - continue; - } - - if (len - b_off > 0) { - /* find last space (if any) */ - for (space = text + b_off; space > text; space--) - if (*space == ' ') - break; - - if (space != text) - b_off = space + 1 - text; - } - - ta->lines[line_count].b_start = text - ta->text; - ta->lines[line_count++].b_length = b_off; - } - - ta->line_count = line_count; - - return true; -} - /* exported interface, documented in textarea.h */ void textarea_redraw(struct textarea *ta, int x, int y, @@ -1197,64 +1375,6 @@ bool textarea_keypress(struct textarea *ta, uint32_t key) return true; } -/** - * Scrolls a textarea to make the caret visible (doesn't perform a redraw) - * - * \param ta The text area to be scrolled - * \return true if textarea was scrolled false otherwise - */ -bool textarea_scroll_visible(struct textarea *ta) -{ - int x0, x1, y0, y1, x, y; - int index, b_off; - bool scrolled = false; - - if (ta->caret_pos.char_off == -1) - return false; - - x0 = MARGIN_LEFT; - x1 = ta->vis_width - MARGIN_RIGHT; - y0 = 0; - y1 = ta->vis_height; - - index = textarea_get_caret(ta); - - /* find byte offset of caret position */ - for (b_off = 0; index-- > 0; - b_off = utf8_next(ta->text, ta->text_len, b_off)) - ; /* do nothing */ - - nsfont.font_width(&ta->fstyle, - ta->text + ta->lines[ta->caret_pos.line].b_start, - b_off - ta->lines[ta->caret_pos.line].b_start, - &x); - - /* top-left of caret */ - x += MARGIN_LEFT - ta->scroll_x; - y = ta->line_height * ta->caret_pos.line - ta->scroll_y; - - /* check and change vertical scroll */ - if (y < y0) { - ta->scroll_y -= y0 - y; - scrolled = true; - } else if (y + ta->line_height > y1) { - ta->scroll_y += y + ta->line_height - y1; - scrolled = true; - } - - - /* check and change horizontal scroll */ - if (x < x0) { - ta->scroll_x -= x0 - x ; - scrolled = true; - } else if (x > x1 - 1) { - ta->scroll_x += x - (x1 - 1); - scrolled = true; - } - - return scrolled; -} - /* exported interface, documented in textarea.h */ bool textarea_mouse_action(struct textarea *ta, browser_mouse_state mouse, @@ -1305,133 +1425,6 @@ bool textarea_drag_end(struct textarea *ta, browser_mouse_state mouse, return textarea_select(ta, ta->drag_start_char, c_end); } -/** - * Selects a character range in the textarea and redraws it - * - * \param ta Text area - * \param c_start First character (inclusive) - * \param c_end Last character (exclusive) - * \return true on success false otherwise - */ -bool textarea_select(struct textarea *ta, int c_start, int c_end) -{ - int swap = -1; - - /* if start is after end they get swapped, start won't and end will - be selected this way */ - if (c_start > c_end) { - swap = c_start; - c_start = c_end; - c_end = swap; - } - - ta->selection_start = c_start; - ta->selection_end = c_end; - - if (!(ta->flags & TEXTAREA_READONLY)) { - if (swap == -1) - return textarea_set_caret(ta, c_end); - else - return textarea_set_caret(ta, c_start); - } - - ta->redraw_request(ta->data, 0, 0, ta->vis_width, ta->vis_height); - - return true; -} - - -/** - * Selects a text fragment, relative to current caret position. - * - * \param ta Text area - * \return True on success, false otherwise - */ -static bool textarea_select_fragment(struct textarea * ta) -{ - int caret_pos, sel_start = 0, sel_end = 0, index; - size_t b_start, b_end; - - /* Fragment separators must be suitable for URLs and ordinary text */ - static const char *sep = " /:.\r\n"; - - caret_pos = textarea_get_caret(ta); - if (caret_pos < 0) { - return false; - } - - /* Compute byte offset of caret position */ - for (b_start = 0, index = 0; index < caret_pos; - b_start = utf8_next(ta->text, ta->text_len, - b_start), - index++) { - /* Cache the character offset of the last separator */ - if (strchr(sep, ta->text[b_start]) != NULL) { - /* Add one to start to skip over separator */ - sel_start = index + 1; - } - } - - /* Search for next separator, if any */ - for (b_end = b_start; b_end < ta->text_len; - b_end = utf8_next(ta->text, ta->text_len, - b_end), - index++) { - if (strchr(sep, ta->text[b_end]) != NULL) { - sel_end = index; - break; - } - } - - if (sel_start < sel_end) { - textarea_select(ta, sel_start, sel_end); - return true; - } - - return false; -} - - -/** - * Normalises any line endings within the text, replacing CRLF or CR with - * LF as necessary. If the textarea is single line, then all linebreaks are - * converted into spaces. - * - * \param ta Text area - * \param b_start Byte offset to start at - * \param b_len Byte length to check - */ -void textarea_normalise_text(struct textarea *ta, - unsigned int b_start, unsigned int b_len) -{ - bool multi = (ta->flags & TEXTAREA_MULTILINE) ? true:false; - unsigned int index; - - /* Remove CR characters. If it's a CRLF pair delete it ot replace it - * with LF otherwise. - */ - for (index = 0; index < b_len; index++) { - if (ta->text[b_start + index] == '\r') { - if (b_start + index + 1 <= ta->text_len && - ta->text[b_start + index + 1] == '\n') { - ta->text_len--; - ta->text_utf8_len--; - memmove(ta->text + b_start + index, - ta->text + b_start + index + 1, - ta->text_len - b_start - index); - } - else - ta->text[b_start + index] = '\n'; - } - /* Replace newlines with spaces if this is a single line - * textarea. - */ - if (!multi && (ta->text[b_start + index] == '\n')) - ta->text[b_start + index] = ' '; - } - -} - /* exported interface, documented in textarea.h */ void textarea_get_dimensions(struct textarea *ta, int *width, int *height) |