3 #include "e_kbd_dict.h"
5 static E_Kbd_Buf_Layout *
10 kbl = E_NEW(E_Kbd_Buf_Layout, 1);
16 _e_kbd_buf_layout_ref(E_Kbd_Buf_Layout *kbl)
22 _e_kbd_buf_layout_unref(E_Kbd_Buf_Layout *kbl)
25 if (kbl->ref > 0) return;
31 if (ky->key) eina_stringshare_del(ky->key);
32 if (ky->key_shift) eina_stringshare_del(ky->key_shift);
33 if (ky->key_capslock) eina_stringshare_del(ky->key_capslock);
35 kbl->keys = eina_list_remove_list(kbl->keys, kbl->keys);
41 _e_kbd_buf_string_matches_clear(E_Kbd_Buf *kb)
43 while (kb->string_matches)
45 if (kb->string_matches->data)
46 eina_stringshare_del(kb->string_matches->data);
47 kb->string_matches = eina_list_remove_list(kb->string_matches, kb->string_matches);
52 _e_kbd_buf_actual_string_clear(E_Kbd_Buf *kb)
54 if (kb->actual_string) eina_stringshare_del(kb->actual_string);
55 kb->actual_string = NULL;
58 static E_Kbd_Buf_Key *
59 _e_kbd_buf_at_coord_get(E_Kbd_Buf *kb __UNUSED__, E_Kbd_Buf_Layout *kbl, int x, int y)
63 for (l = kbl->keys; l; l = l->next)
70 if ((x >= ky->x) && (y >= ky->y) &&
71 (x < (ky->x + ky->w)) && (y < (ky->y + ky->h)))
78 static E_Kbd_Buf_Key *
79 _e_kbd_buf_closest_get(E_Kbd_Buf *kb __UNUSED__, E_Kbd_Buf_Layout *kbl, int x, int y)
82 E_Kbd_Buf_Key *ky_closest = NULL;
83 int dist_closest = 0x7fffffff;
85 for (l = kbl->keys; l; l = l->next)
93 dx = x - (ky->x + (ky->w / 2));
94 dy = y - (ky->y + (ky->h / 2));
95 dist = (dx * dx) + (dy * dy);
96 if (dist < dist_closest)
107 _e_kbd_buf_keystroke_key_string_get(E_Kbd_Buf *kb __UNUSED__, E_Kbd_Buf_Keystroke *ks, E_Kbd_Buf_Key *ky)
109 const char *str = NULL;
111 if ((ky) && (ky->key))
115 if (ky->key_shift) str = ky->key_shift;
118 else if (ks->capslock)
120 if (ky->key_capslock) str = ky->key_capslock;
129 _e_kbd_buf_keystroke_string_get(E_Kbd_Buf *kb, E_Kbd_Buf_Keystroke *ks)
131 const char *str = NULL;
133 if (ks->key) str = ks->key;
138 ky = _e_kbd_buf_at_coord_get(kb, ks->layout, ks->x, ks->y);
139 if (!ky) ky = _e_kbd_buf_closest_get(kb, ks->layout, ks->x, ks->y);
140 str = _e_kbd_buf_keystroke_key_string_get(kb, ks, ky);
146 _e_kbd_buf_actual_string_update(E_Kbd_Buf *kb)
151 unsigned int actual_size = 0;
152 E_Kbd_Buf_Keystroke *ks;
154 _e_kbd_buf_actual_string_clear(kb);
155 EINA_LIST_FOREACH(kb->keystrokes, l, ks)
159 str = _e_kbd_buf_keystroke_string_get(kb, ks);
161 if (!actual) actual_size += 64, actual = malloc(actual_size);
162 else if ((actual_len + strlen(str) + 1) > actual_size)
165 actual = realloc(actual, actual_size);
167 strcpy(actual + actual_len, str);
168 actual_len += strlen(str);
170 kb->actual_string = eina_stringshare_add(actual);
175 _e_kbd_buf_matches_find(Eina_List *matches, const char *s)
179 for (l = matches; l; l = l->next)
181 if (!strcmp(l->data, s)) return s;
187 _e_kbd_buf_matches_update(E_Kbd_Buf *kb)
191 E_Kbd_Dict *dicts[3];
193 _e_kbd_buf_string_matches_clear(kb);
194 dicts[0] = kb->dict.personal;
195 dicts[1] = kb->dict.sys;
196 dicts[2] = kb->dict.data;
197 for (i = 0; i < 3; i++)
199 if (!dicts[i]) continue;
200 e_kbd_dict_matches_lookup(dicts[i]);
201 e_kbd_dict_matches_first(dicts[i]);
204 word = e_kbd_dict_matches_match_get(dicts[i], &pri);
206 if (!_e_kbd_buf_matches_find(kb->string_matches, word))
207 kb->string_matches = eina_list_append(kb->string_matches,
208 eina_stringshare_add(word));
209 e_kbd_dict_matches_next(dicts[i]);
215 _e_kbd_buf_cb_data_dict_reload(void *data)
221 kb->dict.data_reload_delay = NULL;
223 if (kb->dict.data) e_kbd_dict_free(kb->dict.data);
224 e_user_dir_concat_static(buf, "dicts-dynamic/data.dic");
225 kb->dict.data = e_kbd_dict_new(buf);
226 return ECORE_CALLBACK_CANCEL;
230 _e_kbd_buf_cb_data_dict_change(void *data, Ecore_File_Monitor *em __UNUSED__, Ecore_File_Event event __UNUSED__, const char *path __UNUSED__)
235 if (kb->dict.data_reload_delay) ecore_timer_del(kb->dict.data_reload_delay);
236 kb->dict.data_reload_delay = ecore_timer_add(2.0, _e_kbd_buf_cb_data_dict_reload, kb);
240 e_kbd_buf_new(const char *sysdicts, const char *dict)
245 kb = E_NEW(E_Kbd_Buf, 1);
246 if (!kb) return NULL;
247 kb->sysdicts = eina_stringshare_add(sysdicts);
249 e_user_dir_concat_static(buf, "dicts");
250 if (!ecore_file_exists(buf)) ecore_file_mkpath(buf);
252 e_user_dir_snprintf(buf, sizeof(buf), "dicts/%s", dict);
253 kb->dict.sys = e_kbd_dict_new(buf);
256 snprintf(buf, sizeof(buf), "%s/dicts/%s", kb->sysdicts, dict);
257 kb->dict.sys = e_kbd_dict_new(buf);
260 e_user_dir_concat_static(buf, "dicts-dynamic");
261 if (!ecore_file_exists(buf)) ecore_file_mkpath(buf);
263 e_user_dir_concat_static(buf, "dicts-dynamic/personal.dic");
264 kb->dict.personal = e_kbd_dict_new(buf);
265 if (!kb->dict.personal)
275 kb->dict.personal = e_kbd_dict_new(buf);
277 e_user_dir_concat_static(buf, "dicts-dynamic/data.dic");
278 kb->dict.data = e_kbd_dict_new(buf);
279 kb->dict.data_monitor =
280 ecore_file_monitor_add(buf, _e_kbd_buf_cb_data_dict_change, kb);
285 e_kbd_buf_free(E_Kbd_Buf *kb)
288 e_kbd_buf_layout_clear(kb);
289 e_kbd_buf_lookup_cancel(kb);
290 eina_stringshare_del(kb->sysdicts);
291 if (kb->dict.sys) e_kbd_dict_free(kb->dict.sys);
292 if (kb->dict.personal) e_kbd_dict_free(kb->dict.personal);
293 if (kb->dict.data) e_kbd_dict_free(kb->dict.data);
294 if (kb->dict.data_monitor) ecore_file_monitor_del(kb->dict.data_monitor);
295 if (kb->dict.data_reload_delay) ecore_timer_del(kb->dict.data_reload_delay);
300 e_kbd_buf_dict_set(E_Kbd_Buf *kb, const char *dict)
306 if (kb->dict.sys) e_kbd_dict_free(kb->dict.sys);
308 e_user_dir_concat_static(buf, "dicts");
309 if (!ecore_file_exists(buf)) ecore_file_mkpath(buf);
311 e_user_dir_snprintf(buf, sizeof(buf), "dicts/%s", dict);
312 kb->dict.sys = e_kbd_dict_new(buf);
315 snprintf(buf, sizeof(buf), "%s/dicts/%s", kb->sysdicts, dict);
316 kb->dict.sys = e_kbd_dict_new(buf);
321 e_kbd_buf_clear(E_Kbd_Buf *kb)
323 e_kbd_buf_lookup_cancel(kb);
324 while (kb->keystrokes)
326 E_Kbd_Buf_Keystroke *ks;
328 ks = kb->keystrokes->data;
329 if (ks->key) eina_stringshare_del(ks->key);
330 _e_kbd_buf_layout_unref(ks->layout);
332 kb->keystrokes = eina_list_remove_list(kb->keystrokes, kb->keystrokes);
334 _e_kbd_buf_string_matches_clear(kb);
335 if (kb->dict.sys) e_kbd_dict_word_letter_clear(kb->dict.sys);
336 if (kb->dict.personal) e_kbd_dict_word_letter_clear(kb->dict.personal);
337 if (kb->dict.data) e_kbd_dict_word_letter_clear(kb->dict.data);
338 _e_kbd_buf_actual_string_clear(kb);
342 e_kbd_buf_layout_clear(E_Kbd_Buf *kb)
346 _e_kbd_buf_layout_unref(kb->layout);
352 e_kbd_buf_layout_size_set(E_Kbd_Buf *kb, int w, int h)
354 if (!kb->layout) kb->layout = _e_kbd_buf_new();
355 if (!kb->layout) return;
361 e_kbd_buf_layout_fuzz_set(E_Kbd_Buf *kb, int fuzz)
363 if (!kb->layout) kb->layout = _e_kbd_buf_new();
364 if (!kb->layout) return;
365 kb->layout->fuzz = fuzz;
369 e_kbd_buf_layout_key_add(E_Kbd_Buf *kb, const char *key, const char *key_shift, const char *key_capslock, int x, int y, int w, int h)
374 if (!kb->layout) kb->layout = _e_kbd_buf_new();
375 if (!kb->layout) return;
376 ky = E_NEW(E_Kbd_Buf_Key, 1);
378 ky->key = eina_stringshare_add(key);
379 if (key_shift) ky->key_shift = eina_stringshare_add(key_shift);
380 if (key_capslock) ky->key_capslock = eina_stringshare_add(key_capslock);
385 kb->layout->keys = eina_list_append(kb->layout->keys, ky);
389 _e_kbd_buf_keystroke_add(E_Kbd_Buf *kb, E_Kbd_Buf_Keystroke *ks)
393 str = _e_kbd_buf_keystroke_string_get(kb, ks);
396 if (kb->dict.sys) e_kbd_dict_word_letter_add(kb->dict.sys, str, 0);
397 if (kb->dict.personal) e_kbd_dict_word_letter_add(kb->dict.personal, str, 0);
398 if (kb->dict.data) e_kbd_dict_word_letter_add(kb->dict.data, str, 0);
403 e_kbd_buf_pressed_key_add(E_Kbd_Buf *kb, const char *key, int shift, int capslock)
405 E_Kbd_Buf_Keystroke *ks;
407 e_kbd_buf_lookup_cancel(kb);
409 if (!kb->layout) kb->layout = _e_kbd_buf_new();
410 if (!kb->layout) return;
411 ks = E_NEW(E_Kbd_Buf_Keystroke, 1);
413 ks->key = eina_stringshare_add(key);
414 if (shift) ks->shift = 1;
415 if (capslock) ks->capslock = 1;
416 ks->layout = kb->layout;
417 _e_kbd_buf_layout_ref(ks->layout);
418 kb->keystrokes = eina_list_append(kb->keystrokes, ks);
420 if (kb->dict.sys) e_kbd_dict_word_letter_advance(kb->dict.sys);
421 if (kb->dict.personal) e_kbd_dict_word_letter_advance(kb->dict.personal);
422 if (kb->dict.data) e_kbd_dict_word_letter_advance(kb->dict.data);
423 _e_kbd_buf_keystroke_add(kb, ks);
425 _e_kbd_buf_actual_string_update(kb);
426 _e_kbd_buf_matches_update(kb);
430 _e_kbd_buf_keystroke_point_add(E_Kbd_Buf *kb, E_Kbd_Buf_Keystroke *ks)
434 for (l = ks->layout->keys; l; l = l->next)
438 int px, py, dx, dy, d;
441 px = ky->x + (ky->w / 2);
442 py = ky->y + (ky->h / 2);
445 d = sqrt((dx * dx) + (dy * dy));
446 if (d <= ks->layout->fuzz)
448 str = _e_kbd_buf_keystroke_key_string_get(kb, ks, ky);
451 if (kb->dict.sys) e_kbd_dict_word_letter_add(kb->dict.sys, str, d);
452 if (kb->dict.personal) e_kbd_dict_word_letter_add(kb->dict.personal, str, d);
453 if (kb->dict.data) e_kbd_dict_word_letter_add(kb->dict.data, str, d);
460 e_kbd_buf_pressed_point_add(E_Kbd_Buf *kb, int x, int y, int shift, int capslock)
462 E_Kbd_Buf_Keystroke *ks;
464 e_kbd_buf_lookup_cancel(kb);
465 if (!kb->layout) kb->layout = _e_kbd_buf_new();
466 if (!kb->layout) return;
467 ks = E_NEW(E_Kbd_Buf_Keystroke, 1);
471 if (shift) ks->shift = 1;
472 if (capslock) ks->capslock = 1;
473 ks->layout = kb->layout;
474 _e_kbd_buf_layout_ref(ks->layout);
475 kb->keystrokes = eina_list_append(kb->keystrokes, ks);
477 if (kb->dict.sys) e_kbd_dict_word_letter_advance(kb->dict.sys);
478 if (kb->dict.personal) e_kbd_dict_word_letter_advance(kb->dict.personal);
479 if (kb->dict.data) e_kbd_dict_word_letter_advance(kb->dict.data);
481 _e_kbd_buf_keystroke_point_add(kb, ks);
483 _e_kbd_buf_actual_string_update(kb);
484 _e_kbd_buf_matches_update(kb);
488 e_kbd_buf_actual_string_get(E_Kbd_Buf *kb)
490 return kb->actual_string;
493 EAPI const Eina_List *
494 e_kbd_buf_string_matches_get(E_Kbd_Buf *kb)
496 return kb->string_matches;
500 e_kbd_buf_backspace(E_Kbd_Buf *kb)
504 l = eina_list_last(kb->keystrokes);
507 E_Kbd_Buf_Keystroke *ks;
510 if (ks->key) eina_stringshare_del(ks->key);
511 _e_kbd_buf_layout_unref(ks->layout);
513 kb->keystrokes = eina_list_remove_list(kb->keystrokes, l);
514 if (kb->dict.sys) e_kbd_dict_word_letter_delete(kb->dict.sys);
515 if (kb->dict.personal) e_kbd_dict_word_letter_delete(kb->dict.personal);
516 if (kb->dict.data) e_kbd_dict_word_letter_delete(kb->dict.data);
517 _e_kbd_buf_actual_string_update(kb);
518 _e_kbd_buf_matches_update(kb);
523 e_kbd_buf_word_use(E_Kbd_Buf *kb, const char *word)
525 if (kb->dict.personal)
526 e_kbd_dict_word_usage_adjust(kb->dict.personal, word, 1);
529 // FIXME: just faking delayed lookup with timer
531 _e_kbd_buf_cb_faket(void *data)
536 kb->lookup.faket = NULL;
537 kb->lookup.func((void *)kb->lookup.data);
538 kb->lookup.func = NULL;
539 kb->lookup.data = NULL;
540 return ECORE_CALLBACK_CANCEL;
544 e_kbd_buf_lookup(E_Kbd_Buf *kb, void (*func) (void *data), const void *data)
546 e_kbd_buf_lookup_cancel(kb);
548 kb->lookup.func = func;
549 kb->lookup.data = data;
551 // FIXME: just faking delayed lookup with timer
552 kb->lookup.faket = ecore_timer_add(0.1, _e_kbd_buf_cb_faket, kb);
556 e_kbd_buf_lookup_cancel(E_Kbd_Buf *kb)
558 // FIXME: just faking delayed lookup with timer
559 if (!kb->lookup.faket) return;
560 ecore_timer_del(kb->lookup.faket);
561 kb->lookup.faket = NULL;
563 kb->lookup.func = NULL;
564 kb->lookup.data = NULL;