blob: 890b32cd29b6ffb2aeaefb06bf0928963020acad [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 Petersenc7d2a982013-01-16 21:26:39 +010067 uint32_t serial;
Jan Arne Petersencba9e472012-06-21 21:52:19 +020068};
69
70struct editor {
Jan Arne Petersen51963742012-08-10 16:47:20 +020071 struct text_model_factory *text_model_factory;
Jan Arne Petersencba9e472012-06-21 21:52:19 +020072 struct display *display;
73 struct window *window;
74 struct widget *widget;
75 struct text_entry *entry;
76 struct text_entry *editor;
Rob Bradford9d1d32b2012-11-18 19:06:49 +010077 struct text_entry *active_entry;
Jan Arne Petersencba9e472012-06-21 21:52:19 +020078};
79
Jan Arne Petersen6345faa2012-11-05 03:26:39 +010080static const char *
81utf8_start_char(const char *text, const char *p)
82{
83 for (; p >= text; --p) {
84 if ((*p & 0xc0) != 0x80)
85 return p;
86 }
87 return NULL;
88}
89
90static const char *
91utf8_prev_char(const char *text, const char *p)
92{
93 if (p > text)
94 return utf8_start_char(text, --p);
95 return NULL;
96}
97
98static const char *
99utf8_end_char(const char *p)
100{
101 while ((*p & 0xc0) == 0x80)
102 p++;
103 return p;
104}
105
106static const char *
107utf8_next_char(const char *p)
108{
109 if (*p != 0)
110 return utf8_end_char(++p);
111 return NULL;
112}
113
Jan Arne Petersenb9eb02c2012-09-09 23:08:35 +0200114static struct text_layout *
115text_layout_create(void)
116{
117 struct text_layout *layout;
118 cairo_surface_t *surface;
119 cairo_t *cr;
120
121 layout = malloc(sizeof *layout);
122 if (!layout)
123 return NULL;
124
125 layout->glyphs = NULL;
126 layout->num_glyphs = 0;
127
128 layout->clusters = NULL;
129 layout->num_clusters = 0;
130
131 surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 0, 0);
132 cr = cairo_create(surface);
133 cairo_set_font_size(cr, font_size);
134 cairo_select_font_face(cr, font_name, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
135 layout->font = cairo_get_scaled_font(cr);
136 cairo_scaled_font_reference(layout->font);
137
138 cairo_destroy(cr);
139 cairo_surface_destroy(surface);
140
141 return layout;
142}
143
144static void
145text_layout_destroy(struct text_layout *layout)
146{
147 if (layout->glyphs)
148 cairo_glyph_free(layout->glyphs);
149
150 if (layout->clusters)
151 cairo_text_cluster_free(layout->clusters);
152
153 cairo_scaled_font_destroy(layout->font);
154
155 free(layout);
156}
157
158static void
159text_layout_set_text(struct text_layout *layout,
160 const char *text)
161{
162 if (layout->glyphs)
163 cairo_glyph_free(layout->glyphs);
164
165 if (layout->clusters)
166 cairo_text_cluster_free(layout->clusters);
167
168 layout->glyphs = NULL;
169 layout->num_glyphs = 0;
170 layout->clusters = NULL;
171 layout->num_clusters = 0;
172
173 cairo_scaled_font_text_to_glyphs(layout->font, 0, 0, text, -1,
174 &layout->glyphs, &layout->num_glyphs,
175 &layout->clusters, &layout->num_clusters,
176 &layout->cluster_flags);
177}
178
179static void
180text_layout_draw(struct text_layout *layout, cairo_t *cr)
181{
182 cairo_save(cr);
183 cairo_set_scaled_font(cr, layout->font);
184 cairo_show_glyphs(cr, layout->glyphs, layout->num_glyphs);
185 cairo_restore(cr);
186}
187
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200188static void
189text_layout_extents(struct text_layout *layout, cairo_text_extents_t *extents)
190{
191 cairo_scaled_font_glyph_extents(layout->font,
192 layout->glyphs, layout->num_glyphs,
193 extents);
194}
195
Jan Arne Petersen6345faa2012-11-05 03:26:39 +0100196static uint32_t
197bytes_from_glyphs(struct text_layout *layout, uint32_t index)
198{
199 int i;
200 uint32_t glyphs = 0, bytes = 0;
201
202 for (i = 0; i < layout->num_clusters && glyphs < index; i++) {
203 bytes += layout->clusters[i].num_bytes;
204 glyphs += layout->clusters[i].num_glyphs;
205 }
206
207 return bytes;
208}
209
210static uint32_t
211glyphs_from_bytes(struct text_layout *layout, uint32_t index)
212{
213 int i;
214 uint32_t glyphs = 0, bytes = 0;
215
216 for (i = 0; i < layout->num_clusters && bytes < index; i++) {
217 bytes += layout->clusters[i].num_bytes;
218 glyphs += layout->clusters[i].num_glyphs;
219 }
220
221 return glyphs;
222}
223
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200224static int
225text_layout_xy_to_index(struct text_layout *layout, double x, double y)
226{
227 cairo_text_extents_t extents;
228 int i;
Philipp Brüschweiler70f83672012-10-02 11:06:54 +0200229 double d;
230
231 if (layout->num_glyphs == 0)
232 return 0;
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200233
234 cairo_scaled_font_glyph_extents(layout->font,
235 layout->glyphs, layout->num_glyphs,
236 &extents);
237
Philipp Brüschweiler70f83672012-10-02 11:06:54 +0200238 if (x < 0)
239 return 0;
240
241 for (i = 0; i < layout->num_glyphs - 1; ++i) {
242 d = layout->glyphs[i + 1].x - layout->glyphs[i].x;
243 if (x < layout->glyphs[i].x + d/2)
Jan Arne Petersen6345faa2012-11-05 03:26:39 +0100244 return bytes_from_glyphs(layout, i);
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200245 }
246
Philipp Brüschweiler70f83672012-10-02 11:06:54 +0200247 d = extents.width - layout->glyphs[layout->num_glyphs - 1].x;
248 if (x < layout->glyphs[layout->num_glyphs - 1].x + d/2)
Jan Arne Petersen6345faa2012-11-05 03:26:39 +0100249 return bytes_from_glyphs(layout, layout->num_glyphs - 1);
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200250
Jan Arne Petersen6345faa2012-11-05 03:26:39 +0100251 return bytes_from_glyphs(layout, layout->num_glyphs);
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200252}
253
254static void
255text_layout_index_to_pos(struct text_layout *layout, uint32_t index, cairo_rectangle_t *pos)
256{
257 cairo_text_extents_t extents;
Jan Arne Petersen6345faa2012-11-05 03:26:39 +0100258 int glyph_index = glyphs_from_bytes(layout, index);
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200259
260 if (!pos)
261 return;
262
263 cairo_scaled_font_glyph_extents(layout->font,
264 layout->glyphs, layout->num_glyphs,
265 &extents);
266
Jan Arne Petersen6345faa2012-11-05 03:26:39 +0100267 if (glyph_index >= layout->num_glyphs) {
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200268 pos->x = extents.x_advance;
269 pos->y = layout->num_glyphs ? layout->glyphs[layout->num_glyphs - 1].y : 0;
270 pos->width = 1;
271 pos->height = extents.height;
272 return;
273 }
274
Jan Arne Petersen6345faa2012-11-05 03:26:39 +0100275 pos->x = layout->glyphs[glyph_index].x;
276 pos->y = layout->glyphs[glyph_index].y;
277 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 +0200278 pos->height = extents.height;
279}
280
281static void
282text_layout_get_cursor_pos(struct text_layout *layout, int index, cairo_rectangle_t *pos)
283{
284 text_layout_index_to_pos(layout, index, pos);
285 pos->width = 1;
286}
Jan Arne Petersenb9eb02c2012-09-09 23:08:35 +0200287
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200288static void text_entry_redraw_handler(struct widget *widget, void *data);
289static void text_entry_button_handler(struct widget *widget,
290 struct input *input, uint32_t time,
291 uint32_t button,
292 enum wl_pointer_button_state state, void *data);
Jan Arne Petersen09e7c962012-09-09 23:08:37 +0200293static void text_entry_insert_at_cursor(struct text_entry *entry, const char *text);
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200294static void text_entry_set_preedit(struct text_entry *entry,
295 const char *preedit_text,
296 int preedit_cursor);
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200297static void text_entry_delete_text(struct text_entry *entry,
298 uint32_t index, uint32_t length);
Jan Arne Petersene386dd22012-09-17 15:28:09 +0200299static void text_entry_delete_selected_text(struct text_entry *entry);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200300
301static void
302text_model_commit_string(void *data,
303 struct text_model *text_model,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100304 uint32_t serial,
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200305 const char *text,
306 uint32_t index)
307{
308 struct text_entry *entry = data;
309
John Kåre Alsaker011a1ce2012-10-12 12:25:06 +0200310 if (index > strlen(text))
Jan Arne Petersen09e7c962012-09-09 23:08:37 +0200311 fprintf(stderr, "Invalid cursor index %d\n", index);
Jan Arne Petersen09e7c962012-09-09 23:08:37 +0200312
Jan Arne Petersene386dd22012-09-17 15:28:09 +0200313 text_entry_delete_selected_text(entry);
Jan Arne Petersen09e7c962012-09-09 23:08:37 +0200314 text_entry_insert_at_cursor(entry, text);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200315
316 widget_schedule_redraw(entry->widget);
317}
318
Jan Arne Petersen72f60822012-08-10 16:47:19 +0200319static void
320text_model_preedit_string(void *data,
321 struct text_model *text_model,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100322 uint32_t serial,
Jan Arne Petersen72f60822012-08-10 16:47:19 +0200323 const char *text,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100324 const char *commit)
Jan Arne Petersen72f60822012-08-10 16:47:19 +0200325{
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200326 struct text_entry *entry = data;
327
Jan Arne Petersene386dd22012-09-17 15:28:09 +0200328 text_entry_delete_selected_text(entry);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100329 text_entry_set_preedit(entry, text, entry->preedit_info.cursor);
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200330
331 widget_schedule_redraw(entry->widget);
Jan Arne Petersen72f60822012-08-10 16:47:19 +0200332}
333
334static void
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200335text_model_delete_surrounding_text(void *data,
336 struct text_model *text_model,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100337 uint32_t serial,
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200338 int32_t index,
339 uint32_t length)
340{
341 struct text_entry *entry = data;
342 uint32_t cursor_index = index + entry->cursor;
Jan Arne Petersen6345faa2012-11-05 03:26:39 +0100343 const char *start, *end;
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200344
345 if (cursor_index > strlen(entry->text)) {
346 fprintf(stderr, "Invalid cursor index %d\n", index);
347 return;
348 }
349
350 if (cursor_index + length > strlen(entry->text)) {
351 fprintf(stderr, "Invalid length %d\n", length);
352 return;
353 }
354
355 if (length == 0)
356 return;
357
Jan Arne Petersen6345faa2012-11-05 03:26:39 +0100358 start = utf8_start_char(entry->text, entry->text + cursor_index);
359 end = utf8_end_char(entry->text + cursor_index + length);
360
361 text_entry_delete_text(entry,
362 start - entry->text,
363 end - start);
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200364}
365
366static void
Jan Arne Petersen72f60822012-08-10 16:47:19 +0200367text_model_preedit_styling(void *data,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100368 struct text_model *text_model,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100369 uint32_t serial,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100370 uint32_t index,
371 uint32_t length,
372 uint32_t style)
Jan Arne Petersen72f60822012-08-10 16:47:19 +0200373{
374}
375
376static void
Jan Arne Petersen46535312013-01-16 21:26:38 +0100377text_model_preedit_cursor(void *data,
378 struct text_model *text_model,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100379 uint32_t serial,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100380 int32_t index)
381{
382 struct text_entry *entry = data;
383
384 entry->preedit_info.cursor = index;
385}
386
387static void
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100388text_model_modifiers_map(void *data,
389 struct text_model *text_model,
390 struct wl_array *map)
391{
Jan Arne Petersencd997062012-11-18 19:06:44 +0100392 struct text_entry *entry = data;
393
394 entry->keysym.shift_mask = keysym_modifiers_get_mask(map, "Shift");
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100395}
396
397static void
398text_model_keysym(void *data,
399 struct text_model *text_model,
400 uint32_t serial,
401 uint32_t time,
402 uint32_t key,
403 uint32_t state,
404 uint32_t modifiers)
Jan Arne Petersen72f60822012-08-10 16:47:19 +0200405{
Jan Arne Petersen8aba11d2012-09-17 15:28:07 +0200406 struct text_entry *entry = data;
Jan Arne Petersencd997062012-11-18 19:06:44 +0100407 const char *state_label = "release";
408 const char *key_label = "Unknown";
Jan Arne Petersen6345faa2012-11-05 03:26:39 +0100409 const char *new_char;
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200410
411 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
412 state_label = "pressed";
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200413 }
414
Jan Arne Petersencd997062012-11-18 19:06:44 +0100415 if (key == XKB_KEY_Left ||
416 key == XKB_KEY_Right) {
417 if (state != WL_KEYBOARD_KEY_STATE_RELEASED)
418 return;
419
420 if (key == XKB_KEY_Left)
421 new_char = utf8_prev_char(entry->text, entry->text + entry->cursor);
422 else
423 new_char = utf8_next_char(entry->text + entry->cursor);
424
425 if (new_char != NULL) {
426 entry->cursor = new_char - entry->text;
427 if (!(modifiers & entry->keysym.shift_mask))
428 entry->anchor = entry->cursor;
429 widget_schedule_redraw(entry->widget);
430 }
431
432 return;
433 }
434
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200435 switch (key) {
436 case XKB_KEY_Tab:
437 key_label = "Tab";
438 break;
439 case XKB_KEY_KP_Enter:
Jan Arne Petersencd997062012-11-18 19:06:44 +0100440 case XKB_KEY_Return:
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200441 key_label = "Enter";
442 break;
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200443 }
444
445 fprintf(stderr, "%s key was %s.\n", key_label, state_label);
Jan Arne Petersen72f60822012-08-10 16:47:19 +0200446}
447
448static void
449text_model_selection_replacement(void *data,
450 struct text_model *text_model)
451{
452}
453
454static void
455text_model_direction(void *data,
456 struct text_model *text_model)
457{
458}
459
460static void
461text_model_locale(void *data,
462 struct text_model *text_model)
463{
464}
465
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200466static void
Jan Arne Petersen680275f2012-09-24 14:51:14 +0200467text_model_enter(void *data,
468 struct text_model *text_model,
469 struct wl_surface *surface)
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200470{
471 struct text_entry *entry = data;
472
Jan Arne Petersen680275f2012-09-24 14:51:14 +0200473 if (surface != window_get_wl_surface(entry->window))
474 return;
475
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200476 entry->active = 1;
477
478 widget_schedule_redraw(entry->widget);
479}
480
481static void
Jan Arne Petersen680275f2012-09-24 14:51:14 +0200482text_model_leave(void *data,
483 struct text_model *text_model)
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200484{
485 struct text_entry *entry = data;
486
487 entry->active = 0;
488
489 widget_schedule_redraw(entry->widget);
490}
491
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200492static const struct text_model_listener text_model_listener = {
Jan Arne Petersen72f60822012-08-10 16:47:19 +0200493 text_model_commit_string,
494 text_model_preedit_string,
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200495 text_model_delete_surrounding_text,
Jan Arne Petersen72f60822012-08-10 16:47:19 +0200496 text_model_preedit_styling,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100497 text_model_preedit_cursor,
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100498 text_model_modifiers_map,
499 text_model_keysym,
Jan Arne Petersen72f60822012-08-10 16:47:19 +0200500 text_model_selection_replacement,
501 text_model_direction,
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200502 text_model_locale,
Jan Arne Petersen680275f2012-09-24 14:51:14 +0200503 text_model_enter,
504 text_model_leave
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200505};
506
507static struct text_entry*
508text_entry_create(struct editor *editor, const char *text)
509{
510 struct text_entry *entry;
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200511
Jan Arne Petersencd997062012-11-18 19:06:44 +0100512 entry = calloc(1, sizeof *entry);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200513
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200514 entry->widget = widget_add_widget(editor->widget, entry);
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200515 entry->window = editor->window;
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200516 entry->text = strdup(text);
517 entry->active = 0;
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200518 entry->cursor = strlen(text);
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +0200519 entry->anchor = entry->cursor;
Jan Arne Petersen4c265182012-09-09 23:08:30 +0200520 entry->model = text_model_factory_create_text_model(editor->text_model_factory);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200521 text_model_add_listener(entry->model, &text_model_listener, entry);
522
Jan Arne Petersenb9eb02c2012-09-09 23:08:35 +0200523 entry->layout = text_layout_create();
524 text_layout_set_text(entry->layout, entry->text);
525
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200526 widget_set_redraw_handler(entry->widget, text_entry_redraw_handler);
527 widget_set_button_handler(entry->widget, text_entry_button_handler);
528
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200529 return entry;
530}
531
532static void
533text_entry_destroy(struct text_entry *entry)
534{
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200535 widget_destroy(entry->widget);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200536 text_model_destroy(entry->model);
Jan Arne Petersenb9eb02c2012-09-09 23:08:35 +0200537 text_layout_destroy(entry->layout);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200538 free(entry->text);
539 free(entry);
540}
541
542static void
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200543redraw_handler(struct widget *widget, void *data)
544{
545 struct editor *editor = data;
546 cairo_surface_t *surface;
547 struct rectangle allocation;
548 cairo_t *cr;
549
550 surface = window_get_surface(editor->window);
551 widget_get_allocation(editor->widget, &allocation);
552
553 cr = cairo_create(surface);
554 cairo_rectangle(cr, allocation.x, allocation.y, allocation.width, allocation.height);
555 cairo_clip(cr);
556
557 cairo_translate(cr, allocation.x, allocation.y);
558
559 /* Draw background */
560 cairo_push_group(cr);
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200561 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200562 cairo_set_source_rgba(cr, 1, 1, 1, 1);
563 cairo_rectangle(cr, 0, 0, allocation.width, allocation.height);
564 cairo_fill(cr);
565
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200566 cairo_pop_group_to_source(cr);
567 cairo_paint(cr);
568
569 cairo_destroy(cr);
570 cairo_surface_destroy(surface);
571}
572
573static void
574text_entry_allocate(struct text_entry *entry, int32_t x, int32_t y,
575 int32_t width, int32_t height)
576{
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200577 widget_set_allocation(entry->widget, x, y, width, height);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200578}
579
580static void
581resize_handler(struct widget *widget,
582 int32_t width, int32_t height, void *data)
583{
584 struct editor *editor = data;
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200585 struct rectangle allocation;
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200586
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200587 widget_get_allocation(editor->widget, &allocation);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200588
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200589 text_entry_allocate(editor->entry,
590 allocation.x + 20, allocation.y + 20,
591 width - 40, height / 2 - 40);
592 text_entry_allocate(editor->editor,
593 allocation.x + 20, allocation.y + height / 2 + 20,
594 width - 40, height / 2 - 40);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200595}
596
597static void
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200598text_entry_activate(struct text_entry *entry,
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200599 struct wl_seat *seat)
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200600{
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200601 struct wl_surface *surface = window_get_wl_surface(entry->window);
602
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100603 entry->serial++;
604
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200605 text_model_activate(entry->model,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100606 entry->serial,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200607 seat,
608 surface);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200609}
610
611static void
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200612text_entry_deactivate(struct text_entry *entry,
613 struct wl_seat *seat)
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200614{
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200615 text_model_deactivate(entry->model,
616 seat);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200617}
618
619static void
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200620text_entry_update_layout(struct text_entry *entry)
621{
622 char *text;
623
Philipp Brüschweiler237358b2012-10-02 11:06:51 +0200624 assert(((unsigned int)entry->cursor) <= strlen(entry->text) +
Jan Arne Petersen46535312013-01-16 21:26:38 +0100625 (entry->preedit.text ? strlen(entry->preedit.text) : 0));
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200626
Jan Arne Petersen46535312013-01-16 21:26:38 +0100627 if (!entry->preedit.text) {
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200628 text_layout_set_text(entry->layout, entry->text);
629 return;
630 }
631
Jan Arne Petersen46535312013-01-16 21:26:38 +0100632 text = malloc(strlen(entry->text) + strlen(entry->preedit.text) + 1);
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200633 strncpy(text, entry->text, entry->cursor);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100634 strcpy(text + entry->cursor, entry->preedit.text);
635 strcpy(text + entry->cursor + strlen(entry->preedit.text),
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200636 entry->text + entry->cursor);
637
638 text_layout_set_text(entry->layout, text);
639 free(text);
640
641 widget_schedule_redraw(entry->widget);
Jan Arne Petersencb08f4d2012-09-09 23:08:40 +0200642
643 text_model_set_surrounding_text(entry->model,
644 entry->text,
645 entry->cursor,
646 entry->anchor);
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200647}
648
649static void
Jan Arne Petersen09e7c962012-09-09 23:08:37 +0200650text_entry_insert_at_cursor(struct text_entry *entry, const char *text)
651{
652 char *new_text = malloc(strlen(entry->text) + strlen(text) + 1);
653
654 strncpy(new_text, entry->text, entry->cursor);
655 strcpy(new_text + entry->cursor, text);
656 strcpy(new_text + entry->cursor + strlen(text),
657 entry->text + entry->cursor);
658
659 free(entry->text);
660 entry->text = new_text;
661 entry->cursor += strlen(text);
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +0200662 entry->anchor += strlen(text);
Jan Arne Petersen09e7c962012-09-09 23:08:37 +0200663
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200664 text_entry_update_layout(entry);
665}
666
667static void
668text_entry_set_preedit(struct text_entry *entry,
669 const char *preedit_text,
670 int preedit_cursor)
671{
Jan Arne Petersen46535312013-01-16 21:26:38 +0100672 if (entry->preedit.text) {
673 free(entry->preedit.text);
674 entry->preedit.text = NULL;
675 entry->preedit.cursor = 0;
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200676 }
677
678 if (!preedit_text)
679 return;
680
Jan Arne Petersen46535312013-01-16 21:26:38 +0100681 entry->preedit.text = strdup(preedit_text);
682 entry->preedit.cursor = preedit_cursor;
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200683
684 text_entry_update_layout(entry);
Jan Arne Petersen09e7c962012-09-09 23:08:37 +0200685}
686
687static void
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200688text_entry_set_cursor_position(struct text_entry *entry,
689 int32_t x, int32_t y)
690{
691 entry->cursor = text_layout_xy_to_index(entry->layout, x, y);
692
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100693 entry->serial++;
694
695 text_model_reset(entry->model, entry->serial);
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200696
Jan Arne Petersen46535312013-01-16 21:26:38 +0100697 if (entry->preedit.cursor > 0 &&
698 entry->cursor >= (uint32_t)entry->preedit.cursor) {
699 entry->cursor -= entry->preedit.cursor;
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200700 }
701
702 text_entry_update_layout(entry);
703
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200704 widget_schedule_redraw(entry->widget);
705}
706
707static void
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +0200708text_entry_set_anchor_position(struct text_entry *entry,
709 int32_t x, int32_t y)
710{
711 entry->anchor = text_layout_xy_to_index(entry->layout, x, y);
712
713 widget_schedule_redraw(entry->widget);
714}
715
716static void
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200717text_entry_delete_text(struct text_entry *entry,
718 uint32_t index, uint32_t length)
719{
720 if (entry->cursor > index)
721 entry->cursor -= length;
722
Jan Arne Petersen80ad1a92012-09-17 15:28:10 +0200723 entry->anchor = entry->cursor;
724
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200725 entry->text[index] = '\0';
726 strcat(entry->text, entry->text + index + length);
727
728 text_entry_update_layout(entry);
729
730 widget_schedule_redraw(entry->widget);
731}
732
733static void
Jan Arne Petersene386dd22012-09-17 15:28:09 +0200734text_entry_delete_selected_text(struct text_entry *entry)
735{
736 uint32_t start_index = entry->anchor < entry->cursor ? entry->anchor : entry->cursor;
737 uint32_t end_index = entry->anchor < entry->cursor ? entry->cursor : entry->anchor;
738
739 if (entry->anchor == entry->cursor)
740 return;
741
742 text_entry_delete_text(entry, start_index, end_index - start_index);
743
744 entry->anchor = entry->cursor;
745}
746
747static void
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +0200748text_entry_draw_selection(struct text_entry *entry, cairo_t *cr)
749{
750 cairo_text_extents_t extents;
751 uint32_t start_index = entry->anchor < entry->cursor ? entry->anchor : entry->cursor;
752 uint32_t end_index = entry->anchor < entry->cursor ? entry->cursor : entry->anchor;
753 cairo_rectangle_t start;
754 cairo_rectangle_t end;
755
756 if (entry->anchor == entry->cursor)
757 return;
758
759 text_layout_extents(entry->layout, &extents);
760
761 text_layout_index_to_pos(entry->layout, start_index, &start);
762 text_layout_index_to_pos(entry->layout, end_index, &end);
763
764 cairo_save (cr);
765
Philipp Brüschweilerb8911dc2012-10-02 11:06:52 +0200766 cairo_set_source_rgba(cr, 0.3, 0.3, 1.0, 0.5);
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +0200767 cairo_rectangle(cr,
768 start.x, extents.y_bearing + extents.height + 2,
769 end.x - start.x, -extents.height - 4);
770 cairo_fill(cr);
771
772 cairo_rectangle(cr,
773 start.x, extents.y_bearing + extents.height,
774 end.x - start.x, -extents.height);
775 cairo_clip(cr);
776 cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0);
777 text_layout_draw(entry->layout, cr);
778
779 cairo_restore (cr);
780}
781
782static void
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200783text_entry_draw_cursor(struct text_entry *entry, cairo_t *cr)
784{
785 cairo_text_extents_t extents;
786 cairo_rectangle_t cursor_pos;
787
Jan Arne Petersen46535312013-01-16 21:26:38 +0100788 if (entry->preedit.text && entry->preedit.cursor < 0)
789 return;
790
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200791 text_layout_extents(entry->layout, &extents);
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200792 text_layout_get_cursor_pos(entry->layout,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100793 entry->cursor + entry->preedit.cursor,
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200794 &cursor_pos);
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200795
796 cairo_set_line_width(cr, 1.0);
797 cairo_move_to(cr, cursor_pos.x, extents.y_bearing + extents.height + 2);
798 cairo_line_to(cr, cursor_pos.x, extents.y_bearing - 2);
799 cairo_stroke(cr);
800}
801
802static void
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200803text_entry_draw_preedit(struct text_entry *entry, cairo_t *cr)
804{
805 cairo_text_extents_t extents;
806 cairo_rectangle_t start;
807 cairo_rectangle_t end;
808
Jan Arne Petersen46535312013-01-16 21:26:38 +0100809 if (!entry->preedit.text)
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200810 return;
811
812 text_layout_extents(entry->layout, &extents);
813
814 text_layout_index_to_pos(entry->layout, entry->cursor, &start);
815 text_layout_index_to_pos(entry->layout,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100816 entry->cursor + strlen(entry->preedit.text),
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200817 &end);
818
819 cairo_save (cr);
820
821 cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
822 cairo_rectangle(cr,
823 start.x, 0,
824 end.x - start.x, 1);
825 cairo_fill(cr);
826
827 cairo_restore (cr);
828}
829
Philipp Brüschweiler9f897c72012-10-02 11:06:53 +0200830static const int text_offset_left = 10;
831
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200832static void
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200833text_entry_redraw_handler(struct widget *widget, void *data)
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200834{
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200835 struct text_entry *entry = data;
836 cairo_surface_t *surface;
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200837 struct rectangle allocation;
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200838 cairo_t *cr;
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200839
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200840 surface = window_get_surface(entry->window);
841 widget_get_allocation(entry->widget, &allocation);
842
843 cr = cairo_create(surface);
844 cairo_rectangle(cr, allocation.x, allocation.y, allocation.width, allocation.height);
845 cairo_clip(cr);
846
847 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
848
849 cairo_push_group(cr);
850 cairo_translate(cr, allocation.x, allocation.y);
851
852 cairo_set_source_rgba(cr, 1, 1, 1, 1);
853 cairo_rectangle(cr, 0, 0, allocation.width, allocation.height);
854 cairo_fill(cr);
855
856 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
857
858 if (entry->active) {
859 cairo_rectangle(cr, 0, 0, allocation.width, allocation.height);
860 cairo_set_line_width (cr, 3);
861 cairo_set_source_rgba(cr, 0, 0, 1, 1.0);
862 cairo_stroke(cr);
863 }
864
865 cairo_set_source_rgba(cr, 0, 0, 0, 1);
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200866
Philipp Brüschweiler9f897c72012-10-02 11:06:53 +0200867 cairo_translate(cr, text_offset_left, allocation.height / 2);
Jan Arne Petersenb9eb02c2012-09-09 23:08:35 +0200868 text_layout_draw(entry->layout, cr);
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200869
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +0200870 text_entry_draw_selection(entry, cr);
871
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200872 text_entry_draw_cursor(entry, cr);
873
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200874 text_entry_draw_preedit(entry, cr);
875
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200876 cairo_pop_group_to_source(cr);
877 cairo_paint(cr);
878
879 cairo_destroy(cr);
880 cairo_surface_destroy(surface);
881}
882
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +0200883static int
884text_entry_motion_handler(struct widget *widget,
885 struct input *input, uint32_t time,
886 float x, float y, void *data)
887{
888 struct text_entry *entry = data;
889 struct rectangle allocation;
890
891 widget_get_allocation(entry->widget, &allocation);
892
893 text_entry_set_cursor_position(entry,
Philipp Brüschweiler9f897c72012-10-02 11:06:53 +0200894 x - allocation.x - text_offset_left,
895 y - allocation.y - text_offset_left);
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +0200896
897 return CURSOR_IBEAM;
898}
899
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200900static void
901text_entry_button_handler(struct widget *widget,
902 struct input *input, uint32_t time,
903 uint32_t button,
904 enum wl_pointer_button_state state, void *data)
905{
906 struct text_entry *entry = data;
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200907 struct rectangle allocation;
Rob Bradford9d1d32b2012-11-18 19:06:49 +0100908 struct editor *editor;
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200909 int32_t x, y;
910
911 widget_get_allocation(entry->widget, &allocation);
912 input_get_position(input, &x, &y);
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200913
Rob Bradford9d1d32b2012-11-18 19:06:49 +0100914 editor = window_get_user_data(entry->window);
915
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200916 if (button != BTN_LEFT) {
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200917 return;
918 }
919
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +0200920 text_entry_set_cursor_position(entry,
Philipp Brüschweiler9f897c72012-10-02 11:06:53 +0200921 x - allocation.x - text_offset_left,
922 y - allocation.y - text_offset_left);
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200923
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200924 if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
925 struct wl_seat *seat = input_get_seat(input);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200926
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200927 text_entry_activate(entry, seat);
Rob Bradford9d1d32b2012-11-18 19:06:49 +0100928 editor->active_entry = entry;
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +0200929
930 text_entry_set_anchor_position(entry,
Philipp Brüschweiler9f897c72012-10-02 11:06:53 +0200931 x - allocation.x - text_offset_left,
932 y - allocation.y - text_offset_left);
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +0200933
934 widget_set_motion_handler(entry->widget, text_entry_motion_handler);
935 } else {
936 widget_set_motion_handler(entry->widget, NULL);
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200937 }
938}
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200939
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200940static void
941editor_button_handler(struct widget *widget,
942 struct input *input, uint32_t time,
943 uint32_t button,
944 enum wl_pointer_button_state state, void *data)
945{
946 struct editor *editor = data;
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200947
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200948 if (button != BTN_LEFT) {
949 return;
950 }
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200951
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200952 if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
953 struct wl_seat *seat = input_get_seat(input);
954
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200955 text_entry_deactivate(editor->entry, seat);
956 text_entry_deactivate(editor->editor, seat);
Rob Bradford9d1d32b2012-11-18 19:06:49 +0100957 editor->active_entry = NULL;
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200958 }
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200959}
960
961static void
Rob Bradford9d1d32b2012-11-18 19:06:49 +0100962key_handler(struct window *window,
963 struct input *input, uint32_t time,
964 uint32_t key, uint32_t sym, enum wl_keyboard_key_state state,
965 void *data)
966{
967 struct editor *editor = data;
968 struct text_entry *entry;
969 const char *start, *end, *new_char;
970 char text[16];
971
972 if (!editor->active_entry)
973 return;
974
975 entry = editor->active_entry;
976
977 if (state != WL_KEYBOARD_KEY_STATE_PRESSED)
978 return;
979
980 switch (sym) {
981 case XKB_KEY_BackSpace:
982 start = utf8_prev_char(entry->text, entry->text + entry->cursor);
983
984 if (start == NULL)
985 break;
986
987 end = utf8_end_char(entry->text + entry->cursor);
988 text_entry_delete_text(entry,
989 start - entry->text,
990 end - start);
991 break;
992 case XKB_KEY_Delete:
993 start = utf8_start_char(entry->text, entry->text + entry->cursor);
994
995 if (start == NULL)
996 break;
997
998 end = utf8_next_char(start);
999
1000 if (end == NULL)
1001 break;
1002
1003 text_entry_delete_text(entry,
1004 start - entry->text,
1005 end - start);
1006 break;
1007 case XKB_KEY_Left:
1008 new_char = utf8_prev_char(entry->text, entry->text + entry->cursor);
1009 if (new_char != NULL) {
1010 entry->cursor = new_char - entry->text;
1011 entry->anchor = entry->cursor;
1012 widget_schedule_redraw(entry->widget);
1013 }
1014 break;
1015 case XKB_KEY_Right:
1016 new_char = utf8_next_char(entry->text + entry->cursor);
1017 if (new_char != NULL) {
1018 entry->cursor = new_char - entry->text;
1019 entry->anchor = entry->cursor;
1020 widget_schedule_redraw(entry->widget);
1021 }
1022 break;
1023 default:
1024 if (xkb_keysym_to_utf8(sym, text, sizeof(text)) <= 0)
1025 break;
1026
1027 text_entry_insert_at_cursor(entry, text);
1028 break;
1029 }
1030
1031 widget_schedule_redraw(entry->widget);
1032}
1033
1034static void
Kristian Høgsbergfa80e112012-10-10 21:34:26 -04001035global_handler(struct display *display, uint32_t name,
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001036 const char *interface, uint32_t version, void *data)
1037{
1038 struct editor *editor = data;
1039
Jan Arne Petersen51963742012-08-10 16:47:20 +02001040 if (!strcmp(interface, "text_model_factory")) {
Kristian Høgsbergfa80e112012-10-10 21:34:26 -04001041 editor->text_model_factory =
1042 display_bind(display, name,
1043 &text_model_factory_interface, 1);
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001044 }
1045}
1046
1047int
1048main(int argc, char *argv[])
1049{
1050 struct editor editor;
1051
Jan Arne Petersen25f6db52012-11-05 03:26:40 +01001052 memset(&editor, 0, sizeof editor);
1053
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001054 editor.display = display_create(argc, argv);
1055 if (editor.display == NULL) {
1056 fprintf(stderr, "failed to create display: %m\n");
1057 return -1;
1058 }
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001059
Kristian Høgsbergfa80e112012-10-10 21:34:26 -04001060 display_set_user_data(editor.display, &editor);
1061 display_set_global_handler(editor.display, global_handler);
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001062
1063 editor.window = window_create(editor.display);
1064 editor.widget = frame_create(editor.window, &editor);
1065
1066 editor.entry = text_entry_create(&editor, "Entry");
1067 editor.editor = text_entry_create(&editor, "Editor");
1068
1069 window_set_title(editor.window, "Text Editor");
Rob Bradford9d1d32b2012-11-18 19:06:49 +01001070 window_set_key_handler(editor.window, key_handler);
1071 window_set_user_data(editor.window, &editor);
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001072
1073 widget_set_redraw_handler(editor.widget, redraw_handler);
1074 widget_set_resize_handler(editor.widget, resize_handler);
Jan Arne Petersenf80bc062012-09-09 23:08:34 +02001075 widget_set_button_handler(editor.widget, editor_button_handler);
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001076
1077 window_schedule_resize(editor.window, 500, 400);
1078
1079 display_run(editor.display);
1080
1081 text_entry_destroy(editor.entry);
1082 text_entry_destroy(editor.editor);
1083
1084 return 0;
1085}