editor: Fix some offsets for multi-byte characters

Signed-off-by: Jan Arne Petersen <jpetersen@openismus.com>
Jan Arne Petersen 12 years ago committed by Kristian Høgsberg
parent d8aa3327b3
commit 685168661a
  1. 100
      clients/editor.c

@ -82,31 +82,23 @@ struct editor {
}; };
static const char * static const char *
utf8_start_char(const char *text, const char *p) utf8_end_char(const char *p)
{ {
for (; p >= text; --p) { while ((*p & 0xc0) == 0x80)
if ((*p & 0xc0) != 0x80) p++;
return p; return p;
}
return NULL;
} }
static const char * static const char *
utf8_prev_char(const char *text, const char *p) utf8_prev_char(const char *s, const char *p)
{ {
if (p > text) for (--p; p >= s; --p) {
return utf8_start_char(text, --p); if ((*p & 0xc0) != 0x80)
return p;
}
return NULL; return NULL;
} }
static const char *
utf8_end_char(const char *p)
{
while ((*p & 0xc0) == 0x80)
p++;
return p;
}
static const char * static const char *
utf8_next_char(const char *p) utf8_next_char(const char *p)
{ {
@ -211,7 +203,7 @@ text_input_delete_surrounding_text(void *data,
entry->pending_commit.delete_index = entry->cursor + index; entry->pending_commit.delete_index = entry->cursor + index;
entry->pending_commit.delete_length = length; entry->pending_commit.delete_length = length;
text_length = utf8_characters(entry->text); text_length = strlen(entry->text);
if (entry->pending_commit.delete_index > text_length) { if (entry->pending_commit.delete_index > text_length) {
fprintf(stderr, "Invalid cursor index %d\n", index); fprintf(stderr, "Invalid cursor index %d\n", index);
@ -339,11 +331,12 @@ text_input_keysym(void *data,
if (new_char != NULL) { if (new_char != NULL) {
entry->cursor = new_char - entry->text; entry->cursor = new_char - entry->text;
if (!(modifiers & entry->keysym.shift_mask))
entry->anchor = entry->cursor;
widget_schedule_redraw(entry->widget);
} }
if (!(modifiers & entry->keysym.shift_mask))
entry->anchor = entry->cursor;
widget_schedule_redraw(entry->widget);
return; return;
} }
@ -356,11 +349,11 @@ text_input_keysym(void *data,
text_entry_commit_and_reset(entry); text_entry_commit_and_reset(entry);
start = utf8_prev_char(entry->text, entry->text + entry->cursor); start = utf8_prev_char(entry->text, entry->text + entry->cursor);
end = utf8_next_char(start);
if (start == NULL) if (start == NULL)
return; return;
end = utf8_end_char(entry->text + entry->cursor);
text_entry_delete_text(entry, text_entry_delete_text(entry,
start - entry->text, start - entry->text,
end - start); end - start);
@ -593,8 +586,8 @@ text_entry_update_layout(struct text_entry *entry)
char *text; char *text;
PangoAttrList *attr_list; PangoAttrList *attr_list;
assert((entry->cursor) <= strlen(entry->text) + assert(entry->cursor <= (strlen(entry->text) +
(entry->preedit.text ? strlen(entry->preedit.text) : 0)); (entry->preedit.text ? strlen(entry->preedit.text) : 0)));
if (entry->preedit.text) { if (entry->preedit.text) {
text = malloc(strlen(entry->text) + strlen(entry->preedit.text) + 1); text = malloc(strlen(entry->text) + strlen(entry->preedit.text) + 1);
@ -692,6 +685,7 @@ text_entry_insert_at_cursor(struct text_entry *entry, const char *text,
entry->anchor = entry->cursor + strlen(text) + anchor; entry->anchor = entry->cursor + strlen(text) + anchor;
else else
entry->anchor = entry->cursor + 1 + anchor; entry->anchor = entry->cursor + 1 + anchor;
if (cursor >= 0) if (cursor >= 0)
entry->cursor += strlen(text) + cursor; entry->cursor += strlen(text) + cursor;
else else
@ -764,6 +758,7 @@ text_entry_try_invoke_preedit_action(struct text_entry *entry,
{ {
int index, trailing; int index, trailing;
uint32_t cursor; uint32_t cursor;
const char *text;
if (!entry->preedit.text) if (!entry->preedit.text)
return 0; return 0;
@ -771,7 +766,9 @@ text_entry_try_invoke_preedit_action(struct text_entry *entry,
pango_layout_xy_to_index(entry->layout, pango_layout_xy_to_index(entry->layout,
x * PANGO_SCALE, y * PANGO_SCALE, x * PANGO_SCALE, y * PANGO_SCALE,
&index, &trailing); &index, &trailing);
cursor = index + trailing;
text = pango_layout_get_text(entry->layout);
cursor = g_utf8_offset_to_pointer(text + index, trailing) - text;
if (cursor < entry->cursor || if (cursor < entry->cursor ||
cursor > entry->cursor + strlen(entry->preedit.text)) { cursor > entry->cursor + strlen(entry->preedit.text)) {
@ -791,13 +788,16 @@ text_entry_set_cursor_position(struct text_entry *entry,
int32_t x, int32_t y) int32_t x, int32_t y)
{ {
int index, trailing; int index, trailing;
const char *text;
text_entry_commit_and_reset(entry); text_entry_commit_and_reset(entry);
pango_layout_xy_to_index(entry->layout, pango_layout_xy_to_index(entry->layout,
x * PANGO_SCALE, y * PANGO_SCALE, x * PANGO_SCALE, y * PANGO_SCALE,
&index, &trailing); &index, &trailing);
entry->cursor = index + trailing;
text = pango_layout_get_text(entry->layout);
entry->cursor = g_utf8_offset_to_pointer(text + index, trailing) - text;
text_entry_update_layout(entry); text_entry_update_layout(entry);
@ -811,11 +811,14 @@ text_entry_set_anchor_position(struct text_entry *entry,
int32_t x, int32_t y) int32_t x, int32_t y)
{ {
int index, trailing; int index, trailing;
const char *text;
pango_layout_xy_to_index(entry->layout, pango_layout_xy_to_index(entry->layout,
x * PANGO_SCALE, y * PANGO_SCALE, x * PANGO_SCALE, y * PANGO_SCALE,
&index, &trailing); &index, &trailing);
entry->anchor = index + trailing;
text = pango_layout_get_text(entry->layout);
entry->anchor = g_utf8_offset_to_pointer(text + index, trailing) - text;
text_entry_update_layout(entry); text_entry_update_layout(entry);
@ -828,13 +831,17 @@ static void
text_entry_delete_text(struct text_entry *entry, text_entry_delete_text(struct text_entry *entry,
uint32_t index, uint32_t length) uint32_t index, uint32_t length)
{ {
uint32_t l;
if (entry->cursor > index) if (entry->cursor > index)
entry->cursor -= length; entry->cursor -= length;
entry->anchor = entry->cursor; entry->anchor = entry->cursor;
entry->text[index] = '\0'; l = strlen(entry->text + index + length);
strcat(entry->text, entry->text + index + length); memmove(entry->text + index,
entry->text + index + length,
l + 1);
text_entry_update_layout(entry); text_entry_update_layout(entry);
@ -874,6 +881,7 @@ text_entry_get_cursor_rectangle(struct text_entry *entry, struct rectangle *rect
return; return;
} }
pango_layout_get_extents(entry->layout, &extents, NULL); pango_layout_get_extents(entry->layout, &extents, NULL);
pango_layout_get_cursor_pos(entry->layout, pango_layout_get_cursor_pos(entry->layout,
entry->cursor + entry->preedit.cursor, entry->cursor + entry->preedit.cursor,
@ -1053,7 +1061,7 @@ key_handler(struct window *window,
{ {
struct editor *editor = data; struct editor *editor = data;
struct text_entry *entry; struct text_entry *entry;
const char *start, *end, *new_char; const char *new_char;
char text[16]; char text[16];
if (!editor->active_entry) if (!editor->active_entry)
@ -1068,32 +1076,20 @@ key_handler(struct window *window,
case XKB_KEY_BackSpace: case XKB_KEY_BackSpace:
text_entry_commit_and_reset(entry); text_entry_commit_and_reset(entry);
start = utf8_prev_char(entry->text, entry->text + entry->cursor); new_char = utf8_prev_char(entry->text, entry->text + entry->cursor);
if (new_char != NULL)
if (start == NULL) text_entry_delete_text(entry,
break; new_char - entry->text,
(entry->text + entry->cursor) - new_char);
end = utf8_end_char(entry->text + entry->cursor);
text_entry_delete_text(entry,
start - entry->text,
end - start);
break; break;
case XKB_KEY_Delete: case XKB_KEY_Delete:
text_entry_commit_and_reset(entry); text_entry_commit_and_reset(entry);
start = utf8_start_char(entry->text, entry->text + entry->cursor); new_char = utf8_next_char(entry->text + entry->cursor);
if (new_char != NULL)
if (start == NULL) text_entry_delete_text(entry,
break; entry->cursor,
new_char - (entry->text + entry->cursor));
end = utf8_next_char(start);
if (end == NULL)
break;
text_entry_delete_text(entry,
start - entry->text,
end - start);
break; break;
case XKB_KEY_Left: case XKB_KEY_Left:
text_entry_commit_and_reset(entry); text_entry_commit_and_reset(entry);

Loading…
Cancel
Save