[PATCH v2 28/28] editor: Fix some offsets for multi-byte characters
Jan Arne Petersen
jpetersen at openismus.com
Thu Apr 18 07:47:42 PDT 2013
From: Jan Arne Petersen <jpetersen at openismus.com>
Signed-off-by: Jan Arne Petersen <jpetersen at openismus.com>
---
clients/editor.c | 100 ++++++++++++++++++++++++++-----------------------------
1 file changed, 48 insertions(+), 52 deletions(-)
diff --git a/clients/editor.c b/clients/editor.c
index f6e6084..7c90ed9 100644
--- a/clients/editor.c
+++ b/clients/editor.c
@@ -82,32 +82,24 @@ struct editor {
};
static const char *
-utf8_start_char(const char *text, const char *p)
+utf8_end_char(const char *p)
{
- for (; p >= text; --p) {
- if ((*p & 0xc0) != 0x80)
- return p;
- }
- return NULL;
+ while ((*p & 0xc0) == 0x80)
+ p++;
+ return p;
}
static const char *
-utf8_prev_char(const char *text, const char *p)
+utf8_prev_char(const char *s, const char *p)
{
- if (p > text)
- return utf8_start_char(text, --p);
+ for (--p; p >= s; --p) {
+ if ((*p & 0xc0) != 0x80)
+ return p;
+ }
return NULL;
}
static const char *
-utf8_end_char(const char *p)
-{
- while ((*p & 0xc0) == 0x80)
- p++;
- return p;
-}
-
-static const char *
utf8_next_char(const char *p)
{
if (*p != 0)
@@ -200,7 +192,7 @@ text_input_delete_surrounding_text(void *data,
entry->pending_commit.delete_index = entry->cursor + index;
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) {
fprintf(stderr, "Invalid cursor index %d\n", index);
@@ -328,11 +320,12 @@ text_input_keysym(void *data,
if (new_char != NULL) {
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;
}
@@ -345,11 +338,11 @@ text_input_keysym(void *data,
text_entry_commit_and_reset(entry);
start = utf8_prev_char(entry->text, entry->text + entry->cursor);
+ end = utf8_next_char(start);
if (start == NULL)
return;
- end = utf8_end_char(entry->text + entry->cursor);
text_entry_delete_text(entry,
start - entry->text,
end - start);
@@ -582,8 +575,8 @@ text_entry_update_layout(struct text_entry *entry)
char *text;
PangoAttrList *attr_list;
- assert((entry->cursor) <= strlen(entry->text) +
- (entry->preedit.text ? strlen(entry->preedit.text) : 0));
+ assert(entry->cursor <= (strlen(entry->text) +
+ (entry->preedit.text ? strlen(entry->preedit.text) : 0)));
if (entry->preedit.text) {
text = malloc(strlen(entry->text) + strlen(entry->preedit.text) + 1);
@@ -681,6 +674,7 @@ text_entry_insert_at_cursor(struct text_entry *entry, const char *text,
entry->anchor = entry->cursor + strlen(text) + anchor;
else
entry->anchor = entry->cursor + 1 + anchor;
+
if (cursor >= 0)
entry->cursor += strlen(text) + cursor;
else
@@ -753,6 +747,7 @@ text_entry_try_invoke_preedit_action(struct text_entry *entry,
{
int index, trailing;
uint32_t cursor;
+ const char *text;
if (!entry->preedit.text)
return 0;
@@ -760,7 +755,9 @@ text_entry_try_invoke_preedit_action(struct text_entry *entry,
pango_layout_xy_to_index(entry->layout,
x * PANGO_SCALE, y * PANGO_SCALE,
&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 ||
cursor > entry->cursor + strlen(entry->preedit.text)) {
@@ -780,13 +777,16 @@ text_entry_set_cursor_position(struct text_entry *entry,
int32_t x, int32_t y)
{
int index, trailing;
+ const char *text;
text_entry_commit_and_reset(entry);
pango_layout_xy_to_index(entry->layout,
x * PANGO_SCALE, y * PANGO_SCALE,
&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);
@@ -800,11 +800,14 @@ text_entry_set_anchor_position(struct text_entry *entry,
int32_t x, int32_t y)
{
int index, trailing;
+ const char *text;
pango_layout_xy_to_index(entry->layout,
x * PANGO_SCALE, y * PANGO_SCALE,
&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);
@@ -817,13 +820,17 @@ static void
text_entry_delete_text(struct text_entry *entry,
uint32_t index, uint32_t length)
{
+ uint32_t l;
+
if (entry->cursor > index)
entry->cursor -= length;
entry->anchor = entry->cursor;
- entry->text[index] = '\0';
- strcat(entry->text, entry->text + index + length);
+ l = strlen(entry->text + index + length);
+ memmove(entry->text + index,
+ entry->text + index + length,
+ l + 1);
text_entry_update_layout(entry);
@@ -863,6 +870,7 @@ text_entry_get_cursor_rectangle(struct text_entry *entry, struct rectangle *rect
return;
}
+
pango_layout_get_extents(entry->layout, &extents, NULL);
pango_layout_get_cursor_pos(entry->layout,
entry->cursor + entry->preedit.cursor,
@@ -1042,7 +1050,7 @@ key_handler(struct window *window,
{
struct editor *editor = data;
struct text_entry *entry;
- const char *start, *end, *new_char;
+ const char *new_char;
char text[16];
if (!editor->active_entry)
@@ -1057,32 +1065,20 @@ key_handler(struct window *window,
case XKB_KEY_BackSpace:
text_entry_commit_and_reset(entry);
- start = utf8_prev_char(entry->text, entry->text + entry->cursor);
-
- if (start == NULL)
- break;
-
- end = utf8_end_char(entry->text + entry->cursor);
- text_entry_delete_text(entry,
- start - entry->text,
- end - start);
+ new_char = utf8_prev_char(entry->text, entry->text + entry->cursor);
+ if (new_char != NULL)
+ text_entry_delete_text(entry,
+ new_char - entry->text,
+ (entry->text + entry->cursor) - new_char);
break;
case XKB_KEY_Delete:
text_entry_commit_and_reset(entry);
- start = utf8_start_char(entry->text, entry->text + entry->cursor);
-
- if (start == NULL)
- break;
-
- end = utf8_next_char(start);
-
- if (end == NULL)
- break;
-
- text_entry_delete_text(entry,
- start - entry->text,
- end - start);
+ new_char = utf8_next_char(entry->text + entry->cursor);
+ if (new_char != NULL)
+ text_entry_delete_text(entry,
+ entry->cursor,
+ new_char - (entry->text + entry->cursor));
break;
case XKB_KEY_Left:
text_entry_commit_and_reset(entry);
--
1.8.1.4
More information about the wayland-devel
mailing list