From: Jan Arne Petersen <[email protected]>

Signed-off-by: Jan Arne Petersen <[email protected]>
---
 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

_______________________________________________
wayland-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to