keyboard: Fix offsets when deleting text

Signed-off-by: Jan Arne Petersen <jpetersen@openismus.com>
This commit is contained in:
Jan Arne Petersen 2013-04-18 16:47:41 +02:00 committed by Kristian Høgsberg
parent cc75ec11ca
commit d8aa3327b3

View File

@ -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