[PATCH v2 27/28] keyboard: Fix offsets when deleting text
Jan Arne Petersen
jpetersen at openismus.com
Thu Apr 18 07:47:41 PDT 2013
From: Jan Arne Petersen <jpetersen at openismus.com>
Signed-off-by: Jan Arne Petersen <jpetersen at openismus.com>
---
clients/keyboard.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 85 insertions(+), 5 deletions(-)
diff --git a/clients/keyboard.c b/clients/keyboard.c
index d83ca3c..a2fbded 100644
--- a/clients/keyboard.c
+++ b/clients/keyboard.c
@@ -50,6 +50,7 @@ struct virtual_keyboard {
uint32_t content_purpose;
char *preferred_language;
char *surrounding_text;
+ uint32_t surrounding_cursor;
struct keyboard *keyboard;
};
@@ -380,9 +381,24 @@ resize_handler(struct widget *widget,
/* struct keyboard *keyboard = data; */
}
+static char *
+insert_text(const char *text, uint32_t offset, const char *insert)
+{
+ char *new_text = malloc(strlen(text) + strlen(insert) + 1);
+
+ strncat(new_text, text, offset);
+ new_text[offset] = '\0';
+ strcat(new_text, insert);
+ strcat(new_text, text + offset);
+
+ return new_text;
+}
+
static void
virtual_keyboard_commit_preedit(struct virtual_keyboard *keyboard)
{
+ char *surrounding_text;
+
if (!keyboard->preedit_string ||
strlen(keyboard->preedit_string) == 0)
return;
@@ -392,6 +408,19 @@ virtual_keyboard_commit_preedit(struct virtual_keyboard *keyboard)
wl_input_method_context_commit_string(keyboard->context,
keyboard->serial,
keyboard->preedit_string);
+
+ if (keyboard->surrounding_text) {
+ surrounding_text = insert_text(keyboard->surrounding_text,
+ keyboard->surrounding_cursor,
+ keyboard->preedit_string);
+ free(keyboard->surrounding_text);
+ keyboard->surrounding_text = surrounding_text;
+ keyboard->surrounding_cursor += strlen(keyboard->preedit_string);
+ } else {
+ keyboard->surrounding_text = strdup(keyboard->preedit_string);
+ keyboard->surrounding_cursor = strlen(keyboard->preedit_string);
+ }
+
free(keyboard->preedit_string);
keyboard->preedit_string = strdup("");
}
@@ -417,6 +446,59 @@ virtual_keyboard_send_preedit(struct virtual_keyboard *keyboard,
keyboard->preedit_string);
}
+static const char *
+prev_utf8_char(const char *s, const char *p)
+{
+ for (--p; p >= s; --p) {
+ if ((*p & 0xc0) != 0x80)
+ return p;
+ }
+ return NULL;
+}
+
+static const char *
+next_utf8_char(const char *p)
+{
+ if (*p == '\0')
+ return NULL;
+ for (++p; (*p & 0xc0) == 0x80; ++p)
+ ;
+ return p;
+}
+
+static void
+delete_before_cursor(struct virtual_keyboard *keyboard)
+{
+ const char *start, *end;
+
+ if (!keyboard->surrounding_text) {
+ fprintf(stderr, "delete_before_cursor: No surrounding text available\n");
+ return;
+ }
+
+ start = prev_utf8_char(keyboard->surrounding_text,
+ keyboard->surrounding_text + keyboard->surrounding_cursor);
+ if (!start) {
+ fprintf(stderr, "delete_before_cursor: No previous character to delete\n");
+ return;
+ }
+
+ end = next_utf8_char(start);
+
+ wl_input_method_context_delete_surrounding_text(keyboard->context,
+ (start - keyboard->surrounding_text) - keyboard->surrounding_cursor,
+ end - start);
+ wl_input_method_context_commit_string(keyboard->context,
+ keyboard->serial,
+ "");
+
+ /* Update surrounding text */
+ keyboard->surrounding_cursor = start - keyboard->surrounding_text;
+ keyboard->surrounding_text[keyboard->surrounding_cursor] = '\0';
+ if (*end)
+ memmove(keyboard->surrounding_text + keyboard->surrounding_cursor, end, strlen(end));
+}
+
static void
keyboard_handle_key(struct keyboard *keyboard, uint32_t time, const struct key *key, struct input *input, enum wl_pointer_button_state state)
{
@@ -438,11 +520,7 @@ keyboard_handle_key(struct keyboard *keyboard, uint32_t time, const struct key *
break;
if (strlen(keyboard->keyboard->preedit_string) == 0) {
- wl_input_method_context_delete_surrounding_text(keyboard->keyboard->context,
- -1, 1);
- wl_input_method_context_commit_string(keyboard->keyboard->context,
- keyboard->keyboard->serial,
- "");
+ delete_before_cursor(keyboard->keyboard);
} else {
keyboard->keyboard->preedit_string[strlen(keyboard->keyboard->preedit_string) - 1] = '\0';
virtual_keyboard_send_preedit(keyboard->keyboard, -1);
@@ -567,6 +645,8 @@ handle_surrounding_text(void *data,
free(keyboard->surrounding_text);
keyboard->surrounding_text = strdup(text);
+
+ keyboard->surrounding_cursor = cursor;
}
static void
--
1.8.1.4
More information about the wayland-devel
mailing list