From c1fbcb7c38f026cca8b14c1316a311c59a8d73e9 Mon Sep 17 00:00:00 2001 From: Jan Arne Petersen Date: Sun, 9 Sep 2012 23:08:39 +0200 Subject: [PATCH] editor: Add support for setting a preedit Add support for setting a preedit text to the editor example. Signed-off-by: Jan Arne Petersen --- clients/editor.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 89 insertions(+), 2 deletions(-) diff --git a/clients/editor.c b/clients/editor.c index 3056bdc..86d9a12 100644 --- a/clients/editor.c +++ b/clients/editor.c @@ -51,6 +51,8 @@ struct text_entry { int active; uint32_t cursor; uint32_t anchor; + char *preedit_text; + uint32_t preedit_cursor; struct text_model *model; struct text_layout *layout; }; @@ -311,6 +313,8 @@ text_entry_create(struct editor *editor, const char *text) entry->active = 0; entry->cursor = strlen(text); entry->anchor = entry->cursor; + entry->preedit_text = NULL; + entry->preedit_cursor = 0; entry->model = text_model_factory_create_text_model(editor->text_model_factory); text_model_add_listener(entry->model, &text_model_listener, entry); @@ -408,6 +412,30 @@ text_entry_deactivate(struct text_entry *entry, } static void +text_entry_update_layout(struct text_entry *entry) +{ + char *text; + + assert(((unsigned int)entry->cursor) <= strlen(entry->text)); + + if (!entry->preedit_text) { + text_layout_set_text(entry->layout, entry->text); + return; + } + + text = malloc(strlen(entry->text) + strlen(entry->preedit_text) + 1); + strncpy(text, entry->text, entry->cursor); + strcpy(text + entry->cursor, entry->preedit_text); + strcpy(text + entry->cursor + strlen(entry->preedit_text), + entry->text + entry->cursor); + + text_layout_set_text(entry->layout, text); + free(text); + + widget_schedule_redraw(entry->widget); +} + +static void text_entry_insert_at_cursor(struct text_entry *entry, const char *text) { char *new_text = malloc(strlen(entry->text) + strlen(text) + 1); @@ -422,7 +450,27 @@ text_entry_insert_at_cursor(struct text_entry *entry, const char *text) entry->cursor += strlen(text); entry->anchor += strlen(text); - text_layout_set_text(entry->layout, entry->text); + text_entry_update_layout(entry); +} + +static void +text_entry_set_preedit(struct text_entry *entry, + const char *preedit_text, + int preedit_cursor) +{ + if (entry->preedit_text) { + free(entry->preedit_text); + entry->preedit_text = NULL; + entry->preedit_cursor = 0; + } + + if (!preedit_text) + return; + + entry->preedit_text = strdup(preedit_text); + entry->preedit_cursor = preedit_cursor; + + text_entry_update_layout(entry); } static void @@ -431,6 +479,12 @@ text_entry_set_cursor_position(struct text_entry *entry, { entry->cursor = text_layout_xy_to_index(entry->layout, x, y); + if (entry->cursor >= entry->preedit_cursor) { + entry->cursor -= entry->preedit_cursor; + } + + text_entry_update_layout(entry); + widget_schedule_redraw(entry->widget); } @@ -485,7 +539,9 @@ text_entry_draw_cursor(struct text_entry *entry, cairo_t *cr) cairo_rectangle_t cursor_pos; text_layout_extents(entry->layout, &extents); - text_layout_get_cursor_pos(entry->layout, entry->cursor, &cursor_pos); + text_layout_get_cursor_pos(entry->layout, + entry->cursor + entry->preedit_cursor, + &cursor_pos); cairo_set_line_width(cr, 1.0); cairo_move_to(cr, cursor_pos.x, extents.y_bearing + extents.height + 2); @@ -494,6 +550,34 @@ text_entry_draw_cursor(struct text_entry *entry, cairo_t *cr) } static void +text_entry_draw_preedit(struct text_entry *entry, cairo_t *cr) +{ + cairo_text_extents_t extents; + cairo_rectangle_t start; + cairo_rectangle_t end; + + if (!entry->preedit_text) + return; + + text_layout_extents(entry->layout, &extents); + + text_layout_index_to_pos(entry->layout, entry->cursor, &start); + text_layout_index_to_pos(entry->layout, + entry->cursor + strlen(entry->preedit_text), + &end); + + cairo_save (cr); + + cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0); + cairo_rectangle(cr, + start.x, 0, + end.x - start.x, 1); + cairo_fill(cr); + + cairo_restore (cr); +} + +static void text_entry_redraw_handler(struct widget *widget, void *data) { struct text_entry *entry = data; @@ -535,6 +619,8 @@ text_entry_redraw_handler(struct widget *widget, void *data) text_entry_draw_cursor(entry, cr); + text_entry_draw_preedit(entry, cr); + cairo_pop_group_to_source(cr); cairo_paint(cr); @@ -646,6 +732,7 @@ main(int argc, char *argv[]) editor.entry = text_entry_create(&editor, "Entry"); editor.editor = text_entry_create(&editor, "Editor"); + text_entry_set_preedit(editor.editor, "preedit", strlen("preedit")); window_set_title(editor.window, "Text Editor"); -- 2.7.4