blob: 2198813a1938831685b69903238a6d9a0d396dba [file] [log] [blame]
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001/*
2 * Copyright © 2012 Openismus GmbH
Jan Arne Petersen4c265182012-09-09 23:08:30 +02003 * Copyright © 2012 Intel Corporation
Jan Arne Petersencba9e472012-06-21 21:52:19 +02004 *
5 * Permission to use, copy, modify, distribute, and sell this software and
6 * its documentation for any purpose is hereby granted without fee, provided
7 * that the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the name of the copyright holders not be used in
10 * advertising or publicity pertaining to distribution of the software
11 * without specific, written prior permission. The copyright holders make
12 * no representations about the suitability of this software for any
13 * purpose. It is provided "as is" without express or implied warranty.
14 *
15 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
16 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
18 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
19 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
20 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 */
23
Philipp Brüschweiler591cfca2012-07-11 22:25:29 +020024#include <assert.h>
Jan Arne Petersencba9e472012-06-21 21:52:19 +020025#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28
29#include <linux/input.h>
30#include <cairo.h>
31
32#include "window.h"
33#include "text-client-protocol.h"
34
Jan Arne Petersenb9eb02c2012-09-09 23:08:35 +020035static const char *font_name = "sans-serif";
36static int font_size = 14;
37
38struct text_layout {
39 cairo_glyph_t *glyphs;
40 int num_glyphs;
41 cairo_text_cluster_t *clusters;
42 int num_clusters;
43 cairo_text_cluster_flags_t cluster_flags;
44 cairo_scaled_font_t *font;
45};
46
Jan Arne Petersencba9e472012-06-21 21:52:19 +020047struct text_entry {
48 struct widget *widget;
Jan Arne Petersene829adc2012-08-10 16:47:22 +020049 struct window *window;
Jan Arne Petersencba9e472012-06-21 21:52:19 +020050 char *text;
51 int active;
Jan Arne Petersen7e634a02012-09-09 23:08:36 +020052 uint32_t cursor;
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +020053 uint32_t anchor;
Jan Arne Petersen46535312013-01-16 21:26:38 +010054 struct {
55 char *text;
56 int32_t cursor;
57 char *commit;
58 } preedit;
59 struct {
60 int32_t cursor;
61 } preedit_info;
Jan Arne Petersencba9e472012-06-21 21:52:19 +020062 struct text_model *model;
Jan Arne Petersenb9eb02c2012-09-09 23:08:35 +020063 struct text_layout *layout;
Jan Arne Petersencd997062012-11-18 19:06:44 +010064 struct {
65 xkb_mod_mask_t shift_mask;
66 } keysym;
Jan Arne Petersencba9e472012-06-21 21:52:19 +020067};
68
69struct editor {
Jan Arne Petersen51963742012-08-10 16:47:20 +020070 struct text_model_factory *text_model_factory;
Jan Arne Petersencba9e472012-06-21 21:52:19 +020071 struct display *display;
72 struct window *window;
73 struct widget *widget;
74 struct text_entry *entry;
75 struct text_entry *editor;
Rob Bradford9d1d32b2012-11-18 19:06:49 +010076 struct text_entry *active_entry;
Jan Arne Petersencba9e472012-06-21 21:52:19 +020077};
78
Jan Arne Petersen6345faa2012-11-05 03:26:39 +010079static const char *
80utf8_start_char(const char *text, const char *p)
81{
82 for (; p >= text; --p) {
83 if ((*p & 0xc0) != 0x80)
84 return p;
85 }
86 return NULL;
87}
88
89static const char *
90utf8_prev_char(const char *text, const char *p)
91{
92 if (p > text)
93 return utf8_start_char(text, --p);
94 return NULL;
95}
96
97static const char *
98utf8_end_char(const char *p)
99{
100 while ((*p & 0xc0) == 0x80)
101 p++;
102 return p;
103}
104
105static const char *
106utf8_next_char(const char *p)
107{
108 if (*p != 0)
109 return utf8_end_char(++p);
110 return NULL;
111}
112
Jan Arne Petersenb9eb02c2012-09-09 23:08:35 +0200113static struct text_layout *
114text_layout_create(void)
115{
116 struct text_layout *layout;
117 cairo_surface_t *surface;
118 cairo_t *cr;
119
120 layout = malloc(sizeof *layout);
121 if (!layout)
122 return NULL;
123
124 layout->glyphs = NULL;
125 layout->num_glyphs = 0;
126
127 layout->clusters = NULL;
128 layout->num_clusters = 0;
129
130 surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 0, 0);
131 cr = cairo_create(surface);
132 cairo_set_font_size(cr, font_size);
133 cairo_select_font_face(cr, font_name, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
134 layout->font = cairo_get_scaled_font(cr);
135 cairo_scaled_font_reference(layout->font);
136
137 cairo_destroy(cr);
138 cairo_surface_destroy(surface);
139
140 return layout;
141}
142
143static void
144text_layout_destroy(struct text_layout *layout)
145{
146 if (layout->glyphs)
147 cairo_glyph_free(layout->glyphs);
148
149 if (layout->clusters)
150 cairo_text_cluster_free(layout->clusters);
151
152 cairo_scaled_font_destroy(layout->font);
153
154 free(layout);
155}
156
157static void
158text_layout_set_text(struct text_layout *layout,
159 const char *text)
160{
161 if (layout->glyphs)
162 cairo_glyph_free(layout->glyphs);
163
164 if (layout->clusters)
165 cairo_text_cluster_free(layout->clusters);
166
167 layout->glyphs = NULL;
168 layout->num_glyphs = 0;
169 layout->clusters = NULL;
170 layout->num_clusters = 0;
171
172 cairo_scaled_font_text_to_glyphs(layout->font, 0, 0, text, -1,
173 &layout->glyphs, &layout->num_glyphs,
174 &layout->clusters, &layout->num_clusters,
175 &layout->cluster_flags);
176}
177
178static void
179text_layout_draw(struct text_layout *layout, cairo_t *cr)
180{
181 cairo_save(cr);
182 cairo_set_scaled_font(cr, layout->font);
183 cairo_show_glyphs(cr, layout->glyphs, layout->num_glyphs);
184 cairo_restore(cr);
185}
186
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200187static void
188text_layout_extents(struct text_layout *layout, cairo_text_extents_t *extents)
189{
190 cairo_scaled_font_glyph_extents(layout->font,
191 layout->glyphs, layout->num_glyphs,
192 extents);
193}
194
Jan Arne Petersen6345faa2012-11-05 03:26:39 +0100195static uint32_t
196bytes_from_glyphs(struct text_layout *layout, uint32_t index)
197{
198 int i;
199 uint32_t glyphs = 0, bytes = 0;
200
201 for (i = 0; i < layout->num_clusters && glyphs < index; i++) {
202 bytes += layout->clusters[i].num_bytes;
203 glyphs += layout->clusters[i].num_glyphs;
204 }
205
206 return bytes;
207}
208
209static uint32_t
210glyphs_from_bytes(struct text_layout *layout, uint32_t index)
211{
212 int i;
213 uint32_t glyphs = 0, bytes = 0;
214
215 for (i = 0; i < layout->num_clusters && bytes < index; i++) {
216 bytes += layout->clusters[i].num_bytes;
217 glyphs += layout->clusters[i].num_glyphs;
218 }
219
220 return glyphs;
221}
222
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200223static int
224text_layout_xy_to_index(struct text_layout *layout, double x, double y)
225{
226 cairo_text_extents_t extents;
227 int i;
Philipp Brüschweiler70f83672012-10-02 11:06:54 +0200228 double d;
229
230 if (layout->num_glyphs == 0)
231 return 0;
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200232
233 cairo_scaled_font_glyph_extents(layout->font,
234 layout->glyphs, layout->num_glyphs,
235 &extents);
236
Philipp Brüschweiler70f83672012-10-02 11:06:54 +0200237 if (x < 0)
238 return 0;
239
240 for (i = 0; i < layout->num_glyphs - 1; ++i) {
241 d = layout->glyphs[i + 1].x - layout->glyphs[i].x;
242 if (x < layout->glyphs[i].x + d/2)
Jan Arne Petersen6345faa2012-11-05 03:26:39 +0100243 return bytes_from_glyphs(layout, i);
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200244 }
245
Philipp Brüschweiler70f83672012-10-02 11:06:54 +0200246 d = extents.width - layout->glyphs[layout->num_glyphs - 1].x;
247 if (x < layout->glyphs[layout->num_glyphs - 1].x + d/2)
Jan Arne Petersen6345faa2012-11-05 03:26:39 +0100248 return bytes_from_glyphs(layout, layout->num_glyphs - 1);
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200249
Jan Arne Petersen6345faa2012-11-05 03:26:39 +0100250 return bytes_from_glyphs(layout, layout->num_glyphs);
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200251}
252
253static void
254text_layout_index_to_pos(struct text_layout *layout, uint32_t index, cairo_rectangle_t *pos)
255{
256 cairo_text_extents_t extents;
Jan Arne Petersen6345faa2012-11-05 03:26:39 +0100257 int glyph_index = glyphs_from_bytes(layout, index);
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200258
259 if (!pos)
260 return;
261
262 cairo_scaled_font_glyph_extents(layout->font,
263 layout->glyphs, layout->num_glyphs,
264 &extents);
265
Jan Arne Petersen6345faa2012-11-05 03:26:39 +0100266 if (glyph_index >= layout->num_glyphs) {
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200267 pos->x = extents.x_advance;
268 pos->y = layout->num_glyphs ? layout->glyphs[layout->num_glyphs - 1].y : 0;
269 pos->width = 1;
270 pos->height = extents.height;
271 return;
272 }
273
Jan Arne Petersen6345faa2012-11-05 03:26:39 +0100274 pos->x = layout->glyphs[glyph_index].x;
275 pos->y = layout->glyphs[glyph_index].y;
276 pos->width = glyph_index < layout->num_glyphs - 1 ? layout->glyphs[glyph_index + 1].x : extents.x_advance - pos->x;
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200277 pos->height = extents.height;
278}
279
280static void
281text_layout_get_cursor_pos(struct text_layout *layout, int index, cairo_rectangle_t *pos)
282{
283 text_layout_index_to_pos(layout, index, pos);
284 pos->width = 1;
285}
Jan Arne Petersenb9eb02c2012-09-09 23:08:35 +0200286
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200287static void text_entry_redraw_handler(struct widget *widget, void *data);
288static void text_entry_button_handler(struct widget *widget,
289 struct input *input, uint32_t time,
290 uint32_t button,
291 enum wl_pointer_button_state state, void *data);
Jan Arne Petersen09e7c962012-09-09 23:08:37 +0200292static void text_entry_insert_at_cursor(struct text_entry *entry, const char *text);
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200293static void text_entry_set_preedit(struct text_entry *entry,
294 const char *preedit_text,
295 int preedit_cursor);
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200296static void text_entry_delete_text(struct text_entry *entry,
297 uint32_t index, uint32_t length);
Jan Arne Petersene386dd22012-09-17 15:28:09 +0200298static void text_entry_delete_selected_text(struct text_entry *entry);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200299
300static void
301text_model_commit_string(void *data,
302 struct text_model *text_model,
303 const char *text,
304 uint32_t index)
305{
306 struct text_entry *entry = data;
307
John Kåre Alsaker011a1ce2012-10-12 12:25:06 +0200308 if (index > strlen(text))
Jan Arne Petersen09e7c962012-09-09 23:08:37 +0200309 fprintf(stderr, "Invalid cursor index %d\n", index);
Jan Arne Petersen09e7c962012-09-09 23:08:37 +0200310
Jan Arne Petersene386dd22012-09-17 15:28:09 +0200311 text_entry_delete_selected_text(entry);
Jan Arne Petersen09e7c962012-09-09 23:08:37 +0200312 text_entry_insert_at_cursor(entry, text);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200313
314 widget_schedule_redraw(entry->widget);
315}
316
Jan Arne Petersen72f60822012-08-10 16:47:19 +0200317static void
318text_model_preedit_string(void *data,
319 struct text_model *text_model,
320 const char *text,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100321 const char *commit)
Jan Arne Petersen72f60822012-08-10 16:47:19 +0200322{
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200323 struct text_entry *entry = data;
324
Jan Arne Petersene386dd22012-09-17 15:28:09 +0200325 text_entry_delete_selected_text(entry);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100326 text_entry_set_preedit(entry, text, entry->preedit_info.cursor);
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200327
328 widget_schedule_redraw(entry->widget);
Jan Arne Petersen72f60822012-08-10 16:47:19 +0200329}
330
331static void
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200332text_model_delete_surrounding_text(void *data,
333 struct text_model *text_model,
334 int32_t index,
335 uint32_t length)
336{
337 struct text_entry *entry = data;
338 uint32_t cursor_index = index + entry->cursor;
Jan Arne Petersen6345faa2012-11-05 03:26:39 +0100339 const char *start, *end;
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200340
341 if (cursor_index > strlen(entry->text)) {
342 fprintf(stderr, "Invalid cursor index %d\n", index);
343 return;
344 }
345
346 if (cursor_index + length > strlen(entry->text)) {
347 fprintf(stderr, "Invalid length %d\n", length);
348 return;
349 }
350
351 if (length == 0)
352 return;
353
Jan Arne Petersen6345faa2012-11-05 03:26:39 +0100354 start = utf8_start_char(entry->text, entry->text + cursor_index);
355 end = utf8_end_char(entry->text + cursor_index + length);
356
357 text_entry_delete_text(entry,
358 start - entry->text,
359 end - start);
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200360}
361
362static void
Jan Arne Petersen72f60822012-08-10 16:47:19 +0200363text_model_preedit_styling(void *data,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100364 struct text_model *text_model,
365 uint32_t index,
366 uint32_t length,
367 uint32_t style)
Jan Arne Petersen72f60822012-08-10 16:47:19 +0200368{
369}
370
371static void
Jan Arne Petersen46535312013-01-16 21:26:38 +0100372text_model_preedit_cursor(void *data,
373 struct text_model *text_model,
374 int32_t index)
375{
376 struct text_entry *entry = data;
377
378 entry->preedit_info.cursor = index;
379}
380
381static void
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100382text_model_modifiers_map(void *data,
383 struct text_model *text_model,
384 struct wl_array *map)
385{
Jan Arne Petersencd997062012-11-18 19:06:44 +0100386 struct text_entry *entry = data;
387
388 entry->keysym.shift_mask = keysym_modifiers_get_mask(map, "Shift");
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100389}
390
391static void
392text_model_keysym(void *data,
393 struct text_model *text_model,
394 uint32_t serial,
395 uint32_t time,
396 uint32_t key,
397 uint32_t state,
398 uint32_t modifiers)
Jan Arne Petersen72f60822012-08-10 16:47:19 +0200399{
Jan Arne Petersen8aba11d2012-09-17 15:28:07 +0200400 struct text_entry *entry = data;
Jan Arne Petersencd997062012-11-18 19:06:44 +0100401 const char *state_label = "release";
402 const char *key_label = "Unknown";
Jan Arne Petersen6345faa2012-11-05 03:26:39 +0100403 const char *new_char;
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200404
405 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
406 state_label = "pressed";
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200407 }
408
Jan Arne Petersencd997062012-11-18 19:06:44 +0100409 if (key == XKB_KEY_Left ||
410 key == XKB_KEY_Right) {
411 if (state != WL_KEYBOARD_KEY_STATE_RELEASED)
412 return;
413
414 if (key == XKB_KEY_Left)
415 new_char = utf8_prev_char(entry->text, entry->text + entry->cursor);
416 else
417 new_char = utf8_next_char(entry->text + entry->cursor);
418
419 if (new_char != NULL) {
420 entry->cursor = new_char - entry->text;
421 if (!(modifiers & entry->keysym.shift_mask))
422 entry->anchor = entry->cursor;
423 widget_schedule_redraw(entry->widget);
424 }
425
426 return;
427 }
428
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200429 switch (key) {
430 case XKB_KEY_Tab:
431 key_label = "Tab";
432 break;
433 case XKB_KEY_KP_Enter:
Jan Arne Petersencd997062012-11-18 19:06:44 +0100434 case XKB_KEY_Return:
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200435 key_label = "Enter";
436 break;
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200437 }
438
439 fprintf(stderr, "%s key was %s.\n", key_label, state_label);
Jan Arne Petersen72f60822012-08-10 16:47:19 +0200440}
441
442static void
443text_model_selection_replacement(void *data,
444 struct text_model *text_model)
445{
446}
447
448static void
449text_model_direction(void *data,
450 struct text_model *text_model)
451{
452}
453
454static void
455text_model_locale(void *data,
456 struct text_model *text_model)
457{
458}
459
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200460static void
Jan Arne Petersen680275f2012-09-24 14:51:14 +0200461text_model_enter(void *data,
462 struct text_model *text_model,
463 struct wl_surface *surface)
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200464{
465 struct text_entry *entry = data;
466
Jan Arne Petersen680275f2012-09-24 14:51:14 +0200467 if (surface != window_get_wl_surface(entry->window))
468 return;
469
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200470 entry->active = 1;
471
472 widget_schedule_redraw(entry->widget);
473}
474
475static void
Jan Arne Petersen680275f2012-09-24 14:51:14 +0200476text_model_leave(void *data,
477 struct text_model *text_model)
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200478{
479 struct text_entry *entry = data;
480
481 entry->active = 0;
482
483 widget_schedule_redraw(entry->widget);
484}
485
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200486static const struct text_model_listener text_model_listener = {
Jan Arne Petersen72f60822012-08-10 16:47:19 +0200487 text_model_commit_string,
488 text_model_preedit_string,
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200489 text_model_delete_surrounding_text,
Jan Arne Petersen72f60822012-08-10 16:47:19 +0200490 text_model_preedit_styling,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100491 text_model_preedit_cursor,
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100492 text_model_modifiers_map,
493 text_model_keysym,
Jan Arne Petersen72f60822012-08-10 16:47:19 +0200494 text_model_selection_replacement,
495 text_model_direction,
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200496 text_model_locale,
Jan Arne Petersen680275f2012-09-24 14:51:14 +0200497 text_model_enter,
498 text_model_leave
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200499};
500
501static struct text_entry*
502text_entry_create(struct editor *editor, const char *text)
503{
504 struct text_entry *entry;
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200505
Jan Arne Petersencd997062012-11-18 19:06:44 +0100506 entry = calloc(1, sizeof *entry);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200507
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200508 entry->widget = widget_add_widget(editor->widget, entry);
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200509 entry->window = editor->window;
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200510 entry->text = strdup(text);
511 entry->active = 0;
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200512 entry->cursor = strlen(text);
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +0200513 entry->anchor = entry->cursor;
Jan Arne Petersen4c265182012-09-09 23:08:30 +0200514 entry->model = text_model_factory_create_text_model(editor->text_model_factory);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200515 text_model_add_listener(entry->model, &text_model_listener, entry);
516
Jan Arne Petersenb9eb02c2012-09-09 23:08:35 +0200517 entry->layout = text_layout_create();
518 text_layout_set_text(entry->layout, entry->text);
519
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200520 widget_set_redraw_handler(entry->widget, text_entry_redraw_handler);
521 widget_set_button_handler(entry->widget, text_entry_button_handler);
522
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200523 return entry;
524}
525
526static void
527text_entry_destroy(struct text_entry *entry)
528{
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200529 widget_destroy(entry->widget);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200530 text_model_destroy(entry->model);
Jan Arne Petersenb9eb02c2012-09-09 23:08:35 +0200531 text_layout_destroy(entry->layout);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200532 free(entry->text);
533 free(entry);
534}
535
536static void
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200537redraw_handler(struct widget *widget, void *data)
538{
539 struct editor *editor = data;
540 cairo_surface_t *surface;
541 struct rectangle allocation;
542 cairo_t *cr;
543
544 surface = window_get_surface(editor->window);
545 widget_get_allocation(editor->widget, &allocation);
546
547 cr = cairo_create(surface);
548 cairo_rectangle(cr, allocation.x, allocation.y, allocation.width, allocation.height);
549 cairo_clip(cr);
550
551 cairo_translate(cr, allocation.x, allocation.y);
552
553 /* Draw background */
554 cairo_push_group(cr);
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200555 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200556 cairo_set_source_rgba(cr, 1, 1, 1, 1);
557 cairo_rectangle(cr, 0, 0, allocation.width, allocation.height);
558 cairo_fill(cr);
559
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200560 cairo_pop_group_to_source(cr);
561 cairo_paint(cr);
562
563 cairo_destroy(cr);
564 cairo_surface_destroy(surface);
565}
566
567static void
568text_entry_allocate(struct text_entry *entry, int32_t x, int32_t y,
569 int32_t width, int32_t height)
570{
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200571 widget_set_allocation(entry->widget, x, y, width, height);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200572}
573
574static void
575resize_handler(struct widget *widget,
576 int32_t width, int32_t height, void *data)
577{
578 struct editor *editor = data;
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200579 struct rectangle allocation;
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200580
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200581 widget_get_allocation(editor->widget, &allocation);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200582
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200583 text_entry_allocate(editor->entry,
584 allocation.x + 20, allocation.y + 20,
585 width - 40, height / 2 - 40);
586 text_entry_allocate(editor->editor,
587 allocation.x + 20, allocation.y + height / 2 + 20,
588 width - 40, height / 2 - 40);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200589}
590
591static void
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200592text_entry_activate(struct text_entry *entry,
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200593 struct wl_seat *seat)
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200594{
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200595 struct wl_surface *surface = window_get_wl_surface(entry->window);
596
597 text_model_activate(entry->model,
598 seat,
599 surface);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200600}
601
602static void
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200603text_entry_deactivate(struct text_entry *entry,
604 struct wl_seat *seat)
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200605{
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200606 text_model_deactivate(entry->model,
607 seat);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200608}
609
610static void
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200611text_entry_update_layout(struct text_entry *entry)
612{
613 char *text;
614
Philipp Brüschweiler237358b2012-10-02 11:06:51 +0200615 assert(((unsigned int)entry->cursor) <= strlen(entry->text) +
Jan Arne Petersen46535312013-01-16 21:26:38 +0100616 (entry->preedit.text ? strlen(entry->preedit.text) : 0));
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200617
Jan Arne Petersen46535312013-01-16 21:26:38 +0100618 if (!entry->preedit.text) {
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200619 text_layout_set_text(entry->layout, entry->text);
620 return;
621 }
622
Jan Arne Petersen46535312013-01-16 21:26:38 +0100623 text = malloc(strlen(entry->text) + strlen(entry->preedit.text) + 1);
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200624 strncpy(text, entry->text, entry->cursor);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100625 strcpy(text + entry->cursor, entry->preedit.text);
626 strcpy(text + entry->cursor + strlen(entry->preedit.text),
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200627 entry->text + entry->cursor);
628
629 text_layout_set_text(entry->layout, text);
630 free(text);
631
632 widget_schedule_redraw(entry->widget);
Jan Arne Petersencb08f4d2012-09-09 23:08:40 +0200633
634 text_model_set_surrounding_text(entry->model,
635 entry->text,
636 entry->cursor,
637 entry->anchor);
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200638}
639
640static void
Jan Arne Petersen09e7c962012-09-09 23:08:37 +0200641text_entry_insert_at_cursor(struct text_entry *entry, const char *text)
642{
643 char *new_text = malloc(strlen(entry->text) + strlen(text) + 1);
644
645 strncpy(new_text, entry->text, entry->cursor);
646 strcpy(new_text + entry->cursor, text);
647 strcpy(new_text + entry->cursor + strlen(text),
648 entry->text + entry->cursor);
649
650 free(entry->text);
651 entry->text = new_text;
652 entry->cursor += strlen(text);
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +0200653 entry->anchor += strlen(text);
Jan Arne Petersen09e7c962012-09-09 23:08:37 +0200654
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200655 text_entry_update_layout(entry);
656}
657
658static void
659text_entry_set_preedit(struct text_entry *entry,
660 const char *preedit_text,
661 int preedit_cursor)
662{
Jan Arne Petersen46535312013-01-16 21:26:38 +0100663 if (entry->preedit.text) {
664 free(entry->preedit.text);
665 entry->preedit.text = NULL;
666 entry->preedit.cursor = 0;
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200667 }
668
669 if (!preedit_text)
670 return;
671
Jan Arne Petersen46535312013-01-16 21:26:38 +0100672 entry->preedit.text = strdup(preedit_text);
673 entry->preedit.cursor = preedit_cursor;
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200674
675 text_entry_update_layout(entry);
Jan Arne Petersen09e7c962012-09-09 23:08:37 +0200676}
677
678static void
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200679text_entry_set_cursor_position(struct text_entry *entry,
680 int32_t x, int32_t y)
681{
682 entry->cursor = text_layout_xy_to_index(entry->layout, x, y);
683
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200684 text_model_reset(entry->model);
685
Jan Arne Petersen46535312013-01-16 21:26:38 +0100686 if (entry->preedit.cursor > 0 &&
687 entry->cursor >= (uint32_t)entry->preedit.cursor) {
688 entry->cursor -= entry->preedit.cursor;
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200689 }
690
691 text_entry_update_layout(entry);
692
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200693 widget_schedule_redraw(entry->widget);
694}
695
696static void
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +0200697text_entry_set_anchor_position(struct text_entry *entry,
698 int32_t x, int32_t y)
699{
700 entry->anchor = text_layout_xy_to_index(entry->layout, x, y);
701
702 widget_schedule_redraw(entry->widget);
703}
704
705static void
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200706text_entry_delete_text(struct text_entry *entry,
707 uint32_t index, uint32_t length)
708{
709 if (entry->cursor > index)
710 entry->cursor -= length;
711
Jan Arne Petersen80ad1a92012-09-17 15:28:10 +0200712 entry->anchor = entry->cursor;
713
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200714 entry->text[index] = '\0';
715 strcat(entry->text, entry->text + index + length);
716
717 text_entry_update_layout(entry);
718
719 widget_schedule_redraw(entry->widget);
720}
721
722static void
Jan Arne Petersene386dd22012-09-17 15:28:09 +0200723text_entry_delete_selected_text(struct text_entry *entry)
724{
725 uint32_t start_index = entry->anchor < entry->cursor ? entry->anchor : entry->cursor;
726 uint32_t end_index = entry->anchor < entry->cursor ? entry->cursor : entry->anchor;
727
728 if (entry->anchor == entry->cursor)
729 return;
730
731 text_entry_delete_text(entry, start_index, end_index - start_index);
732
733 entry->anchor = entry->cursor;
734}
735
736static void
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +0200737text_entry_draw_selection(struct text_entry *entry, cairo_t *cr)
738{
739 cairo_text_extents_t extents;
740 uint32_t start_index = entry->anchor < entry->cursor ? entry->anchor : entry->cursor;
741 uint32_t end_index = entry->anchor < entry->cursor ? entry->cursor : entry->anchor;
742 cairo_rectangle_t start;
743 cairo_rectangle_t end;
744
745 if (entry->anchor == entry->cursor)
746 return;
747
748 text_layout_extents(entry->layout, &extents);
749
750 text_layout_index_to_pos(entry->layout, start_index, &start);
751 text_layout_index_to_pos(entry->layout, end_index, &end);
752
753 cairo_save (cr);
754
Philipp Brüschweilerb8911dc2012-10-02 11:06:52 +0200755 cairo_set_source_rgba(cr, 0.3, 0.3, 1.0, 0.5);
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +0200756 cairo_rectangle(cr,
757 start.x, extents.y_bearing + extents.height + 2,
758 end.x - start.x, -extents.height - 4);
759 cairo_fill(cr);
760
761 cairo_rectangle(cr,
762 start.x, extents.y_bearing + extents.height,
763 end.x - start.x, -extents.height);
764 cairo_clip(cr);
765 cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0);
766 text_layout_draw(entry->layout, cr);
767
768 cairo_restore (cr);
769}
770
771static void
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200772text_entry_draw_cursor(struct text_entry *entry, cairo_t *cr)
773{
774 cairo_text_extents_t extents;
775 cairo_rectangle_t cursor_pos;
776
Jan Arne Petersen46535312013-01-16 21:26:38 +0100777 if (entry->preedit.text && entry->preedit.cursor < 0)
778 return;
779
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200780 text_layout_extents(entry->layout, &extents);
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200781 text_layout_get_cursor_pos(entry->layout,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100782 entry->cursor + entry->preedit.cursor,
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200783 &cursor_pos);
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200784
785 cairo_set_line_width(cr, 1.0);
786 cairo_move_to(cr, cursor_pos.x, extents.y_bearing + extents.height + 2);
787 cairo_line_to(cr, cursor_pos.x, extents.y_bearing - 2);
788 cairo_stroke(cr);
789}
790
791static void
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200792text_entry_draw_preedit(struct text_entry *entry, cairo_t *cr)
793{
794 cairo_text_extents_t extents;
795 cairo_rectangle_t start;
796 cairo_rectangle_t end;
797
Jan Arne Petersen46535312013-01-16 21:26:38 +0100798 if (!entry->preedit.text)
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200799 return;
800
801 text_layout_extents(entry->layout, &extents);
802
803 text_layout_index_to_pos(entry->layout, entry->cursor, &start);
804 text_layout_index_to_pos(entry->layout,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100805 entry->cursor + strlen(entry->preedit.text),
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200806 &end);
807
808 cairo_save (cr);
809
810 cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
811 cairo_rectangle(cr,
812 start.x, 0,
813 end.x - start.x, 1);
814 cairo_fill(cr);
815
816 cairo_restore (cr);
817}
818
Philipp Brüschweiler9f897c72012-10-02 11:06:53 +0200819static const int text_offset_left = 10;
820
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200821static void
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200822text_entry_redraw_handler(struct widget *widget, void *data)
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200823{
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200824 struct text_entry *entry = data;
825 cairo_surface_t *surface;
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200826 struct rectangle allocation;
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200827 cairo_t *cr;
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200828
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200829 surface = window_get_surface(entry->window);
830 widget_get_allocation(entry->widget, &allocation);
831
832 cr = cairo_create(surface);
833 cairo_rectangle(cr, allocation.x, allocation.y, allocation.width, allocation.height);
834 cairo_clip(cr);
835
836 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
837
838 cairo_push_group(cr);
839 cairo_translate(cr, allocation.x, allocation.y);
840
841 cairo_set_source_rgba(cr, 1, 1, 1, 1);
842 cairo_rectangle(cr, 0, 0, allocation.width, allocation.height);
843 cairo_fill(cr);
844
845 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
846
847 if (entry->active) {
848 cairo_rectangle(cr, 0, 0, allocation.width, allocation.height);
849 cairo_set_line_width (cr, 3);
850 cairo_set_source_rgba(cr, 0, 0, 1, 1.0);
851 cairo_stroke(cr);
852 }
853
854 cairo_set_source_rgba(cr, 0, 0, 0, 1);
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200855
Philipp Brüschweiler9f897c72012-10-02 11:06:53 +0200856 cairo_translate(cr, text_offset_left, allocation.height / 2);
Jan Arne Petersenb9eb02c2012-09-09 23:08:35 +0200857 text_layout_draw(entry->layout, cr);
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200858
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +0200859 text_entry_draw_selection(entry, cr);
860
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200861 text_entry_draw_cursor(entry, cr);
862
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200863 text_entry_draw_preedit(entry, cr);
864
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200865 cairo_pop_group_to_source(cr);
866 cairo_paint(cr);
867
868 cairo_destroy(cr);
869 cairo_surface_destroy(surface);
870}
871
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +0200872static int
873text_entry_motion_handler(struct widget *widget,
874 struct input *input, uint32_t time,
875 float x, float y, void *data)
876{
877 struct text_entry *entry = data;
878 struct rectangle allocation;
879
880 widget_get_allocation(entry->widget, &allocation);
881
882 text_entry_set_cursor_position(entry,
Philipp Brüschweiler9f897c72012-10-02 11:06:53 +0200883 x - allocation.x - text_offset_left,
884 y - allocation.y - text_offset_left);
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +0200885
886 return CURSOR_IBEAM;
887}
888
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200889static void
890text_entry_button_handler(struct widget *widget,
891 struct input *input, uint32_t time,
892 uint32_t button,
893 enum wl_pointer_button_state state, void *data)
894{
895 struct text_entry *entry = data;
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200896 struct rectangle allocation;
Rob Bradford9d1d32b2012-11-18 19:06:49 +0100897 struct editor *editor;
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200898 int32_t x, y;
899
900 widget_get_allocation(entry->widget, &allocation);
901 input_get_position(input, &x, &y);
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200902
Rob Bradford9d1d32b2012-11-18 19:06:49 +0100903 editor = window_get_user_data(entry->window);
904
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200905 if (button != BTN_LEFT) {
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200906 return;
907 }
908
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +0200909 text_entry_set_cursor_position(entry,
Philipp Brüschweiler9f897c72012-10-02 11:06:53 +0200910 x - allocation.x - text_offset_left,
911 y - allocation.y - text_offset_left);
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200912
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200913 if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
914 struct wl_seat *seat = input_get_seat(input);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200915
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200916 text_entry_activate(entry, seat);
Rob Bradford9d1d32b2012-11-18 19:06:49 +0100917 editor->active_entry = entry;
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +0200918
919 text_entry_set_anchor_position(entry,
Philipp Brüschweiler9f897c72012-10-02 11:06:53 +0200920 x - allocation.x - text_offset_left,
921 y - allocation.y - text_offset_left);
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +0200922
923 widget_set_motion_handler(entry->widget, text_entry_motion_handler);
924 } else {
925 widget_set_motion_handler(entry->widget, NULL);
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200926 }
927}
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200928
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200929static void
930editor_button_handler(struct widget *widget,
931 struct input *input, uint32_t time,
932 uint32_t button,
933 enum wl_pointer_button_state state, void *data)
934{
935 struct editor *editor = data;
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200936
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200937 if (button != BTN_LEFT) {
938 return;
939 }
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200940
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200941 if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
942 struct wl_seat *seat = input_get_seat(input);
943
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200944 text_entry_deactivate(editor->entry, seat);
945 text_entry_deactivate(editor->editor, seat);
Rob Bradford9d1d32b2012-11-18 19:06:49 +0100946 editor->active_entry = NULL;
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200947 }
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200948}
949
950static void
Rob Bradford9d1d32b2012-11-18 19:06:49 +0100951key_handler(struct window *window,
952 struct input *input, uint32_t time,
953 uint32_t key, uint32_t sym, enum wl_keyboard_key_state state,
954 void *data)
955{
956 struct editor *editor = data;
957 struct text_entry *entry;
958 const char *start, *end, *new_char;
959 char text[16];
960
961 if (!editor->active_entry)
962 return;
963
964 entry = editor->active_entry;
965
966 if (state != WL_KEYBOARD_KEY_STATE_PRESSED)
967 return;
968
969 switch (sym) {
970 case XKB_KEY_BackSpace:
971 start = utf8_prev_char(entry->text, entry->text + entry->cursor);
972
973 if (start == NULL)
974 break;
975
976 end = utf8_end_char(entry->text + entry->cursor);
977 text_entry_delete_text(entry,
978 start - entry->text,
979 end - start);
980 break;
981 case XKB_KEY_Delete:
982 start = utf8_start_char(entry->text, entry->text + entry->cursor);
983
984 if (start == NULL)
985 break;
986
987 end = utf8_next_char(start);
988
989 if (end == NULL)
990 break;
991
992 text_entry_delete_text(entry,
993 start - entry->text,
994 end - start);
995 break;
996 case XKB_KEY_Left:
997 new_char = utf8_prev_char(entry->text, entry->text + entry->cursor);
998 if (new_char != NULL) {
999 entry->cursor = new_char - entry->text;
1000 entry->anchor = entry->cursor;
1001 widget_schedule_redraw(entry->widget);
1002 }
1003 break;
1004 case XKB_KEY_Right:
1005 new_char = utf8_next_char(entry->text + entry->cursor);
1006 if (new_char != NULL) {
1007 entry->cursor = new_char - entry->text;
1008 entry->anchor = entry->cursor;
1009 widget_schedule_redraw(entry->widget);
1010 }
1011 break;
1012 default:
1013 if (xkb_keysym_to_utf8(sym, text, sizeof(text)) <= 0)
1014 break;
1015
1016 text_entry_insert_at_cursor(entry, text);
1017 break;
1018 }
1019
1020 widget_schedule_redraw(entry->widget);
1021}
1022
1023static void
Kristian Høgsbergfa80e112012-10-10 21:34:26 -04001024global_handler(struct display *display, uint32_t name,
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001025 const char *interface, uint32_t version, void *data)
1026{
1027 struct editor *editor = data;
1028
Jan Arne Petersen51963742012-08-10 16:47:20 +02001029 if (!strcmp(interface, "text_model_factory")) {
Kristian Høgsbergfa80e112012-10-10 21:34:26 -04001030 editor->text_model_factory =
1031 display_bind(display, name,
1032 &text_model_factory_interface, 1);
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001033 }
1034}
1035
1036int
1037main(int argc, char *argv[])
1038{
1039 struct editor editor;
1040
Jan Arne Petersen25f6db52012-11-05 03:26:40 +01001041 memset(&editor, 0, sizeof editor);
1042
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001043 editor.display = display_create(argc, argv);
1044 if (editor.display == NULL) {
1045 fprintf(stderr, "failed to create display: %m\n");
1046 return -1;
1047 }
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001048
Kristian Høgsbergfa80e112012-10-10 21:34:26 -04001049 display_set_user_data(editor.display, &editor);
1050 display_set_global_handler(editor.display, global_handler);
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001051
1052 editor.window = window_create(editor.display);
1053 editor.widget = frame_create(editor.window, &editor);
1054
1055 editor.entry = text_entry_create(&editor, "Entry");
1056 editor.editor = text_entry_create(&editor, "Editor");
1057
1058 window_set_title(editor.window, "Text Editor");
Rob Bradford9d1d32b2012-11-18 19:06:49 +01001059 window_set_key_handler(editor.window, key_handler);
1060 window_set_user_data(editor.window, &editor);
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001061
1062 widget_set_redraw_handler(editor.widget, redraw_handler);
1063 widget_set_resize_handler(editor.widget, resize_handler);
Jan Arne Petersenf80bc062012-09-09 23:08:34 +02001064 widget_set_button_handler(editor.widget, editor_button_handler);
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001065
1066 window_schedule_resize(editor.window, 500, 400);
1067
1068 display_run(editor.display);
1069
1070 text_entry_destroy(editor.entry);
1071 text_entry_destroy(editor.editor);
1072
1073 return 0;
1074}