summaryrefslogtreecommitdiff
path: root/desktop
diff options
context:
space:
mode:
Diffstat (limited to 'desktop')
-rw-r--r--desktop/textarea.c889
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)