Make get_xy_offset return both char and byte offset. (Byte being needed for selection replacement.)

This commit is contained in:
Michael Drake 2013-01-09 14:26:11 +00:00
parent 4f1553f2e9
commit 31e7b6d983
1 changed files with 35 additions and 19 deletions

View File

@ -79,13 +79,11 @@ struct textarea {
unsigned int text_alloc; /**< Size of allocated text */
unsigned int text_len; /**< Length of text, in bytes */
unsigned int text_utf8_len; /**< Length of text, in characters
* without the trailing NUL
*/
* without the trailing NUL */
struct {
int line; /**< Line caret is on */
int char_off; /**< Character index of caret within the
* specified line
*/
* specified line */
} caret_pos;
int caret_x; /**< cached X coordinate of the caret */
@ -400,14 +398,17 @@ static bool textarea_reflow(struct textarea *ta, unsigned int line)
* \param y Y coordinate
* \return character offset
*/
static unsigned int textarea_get_xy_offset(struct textarea *ta, int x, int y)
static void textarea_get_xy_offset(struct textarea *ta, int x, int y,
size_t *b_off, unsigned int *c_off)
{
size_t b_off, temp;
unsigned int c_off;
size_t bpos, temp; /* Byte positions in utf8 string */
unsigned int cpos; /* Character positions in utf8 string */
int line;
if (!ta->line_count)
return 0;
if (!ta->line_count) {
*b_off = *c_off = 0;
return;
}
x = x - MARGIN_LEFT + ta->scroll_x;
y = y + ta->scroll_y;
@ -422,9 +423,11 @@ static unsigned int textarea_get_xy_offset(struct textarea *ta, int x, int y)
if (ta->line_count - 1 < line)
line = ta->line_count - 1;
/* Get byte position */
nsfont.font_position_in_string(&ta->fstyle,
ta->text + ta->lines[line].b_start,
ta->lines[line].b_length, x, &b_off, &x);
ta->lines[line].b_length, x, &bpos, &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
@ -432,16 +435,19 @@ static unsigned int textarea_get_xy_offset(struct textarea *ta, int x, int y)
* 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 &&
if (bpos == (unsigned)ta->lines[line].b_length &&
ta->text[ta->lines[line].b_start +
ta->lines[line].b_length - 1] == ' ')
b_off--;
bpos--;
for (temp = 0, c_off = 0; temp < b_off + ta->lines[line].b_start;
/* Get character position */
for (temp = 0, cpos = 0; temp < bpos + ta->lines[line].b_start;
temp = utf8_next(ta->text, ta->text_len, temp))
c_off++;
cpos++;
return c_off;
/* Set the return values */
*b_off = bpos;
*c_off = cpos;
}
@ -455,12 +461,14 @@ 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)
{
size_t b_off;
unsigned int c_off;
if (ta->flags & TEXTAREA_READONLY)
return true;
c_off = textarea_get_xy_offset(ta, x, y);
textarea_get_xy_offset(ta, x, y, &b_off, &c_off);
return textarea_set_caret(ta, c_off);
}
@ -1371,12 +1379,16 @@ bool textarea_mouse_action(struct textarea *ta, browser_mouse_state mouse,
int x, int y)
{
int c_start, c_end;
size_t b_off;
unsigned int c_off;
/* mouse button pressed above the text area, move caret */
if (mouse & BROWSER_MOUSE_PRESS_1) {
if (!(ta->flags & TEXTAREA_READONLY)) {
textarea_set_caret_xy(ta, x, y);
ta->drag_start_char = textarea_get_xy_offset(ta, x, y);
textarea_get_xy_offset(ta, x, y, &b_off, &c_off);
ta->drag_start_char = c_off;
}
if (ta->sel_start != -1) {
/* remove selection */
@ -1393,8 +1405,9 @@ bool textarea_mouse_action(struct textarea *ta, browser_mouse_state mouse,
}
} else if (mouse & (BROWSER_MOUSE_DRAG_1 | BROWSER_MOUSE_HOLDING_1)) {
textarea_get_xy_offset(ta, x, y, &b_off, &c_off);
c_start = ta->drag_start_char;
c_end = textarea_get_xy_offset(ta, x, y);
c_end = c_off;
return textarea_select(ta, c_start, c_end);
}
@ -1407,8 +1420,11 @@ bool textarea_drag_end(struct textarea *ta, browser_mouse_state mouse,
int x, int y)
{
int c_end;
size_t b_off;
unsigned int c_off;
c_end = textarea_get_xy_offset(ta, x, y);
textarea_get_xy_offset(ta, x, y, &b_off, &c_off);
c_end = c_off;
return textarea_select(ta, ta->drag_start_char, c_end);
}