bool ThaiInstance::process_key_event (const KeyEvent& key) { if (key.is_key_release() || key.code == 0 || __is_context_intact_key (key.code)) { return false; } if (key.mask & (SCIM_KEY_AllMasks & ~(SCIM_KEY_ShiftMask | SCIM_KEY_CapsLockMask)) || __is_context_lost_key (key.code)) { _forget_previous_chars (); return false; } KeyEvent thai_key = m_keymap.map_key (key); ucs4_t thai_uni = thai_key.get_unicode_code (); if (!th_wcistis (thai_uni)) return false; thchar_t thai_tis = th_uni2tis (thai_uni); thcell_t context_cell = _get_previous_cell (); thinpconv_t conv; if (th_validate (context_cell, thai_tis, &conv)) { if (conv.offset < 0) if (!delete_surrounding_text (conv.offset, -conv.offset)) return false; _forget_previous_chars (); _remember_previous_char (thai_tis); WideString str; for (int i = 0; conv.conv [i]; i++) str.push_back (th_tis2uni (conv.conv [i])); commit_string (str); } else { beep (); } return true; }
static int brk_recover_try (const thchar_t *s, int len, const char *brkpos_hints, int pos[], size_t n) { BrkPool *pool; BrkPool *node; int ret; pool = brk_root_pool (n); ret = 0; while (NULL != (node = brk_pool_get_node (pool))) { BrkShot *shot = &node->shot; BrkPool *match; int is_keep_node, is_terminal; /* walk dictionary character-wise till a word is matched */ is_keep_node = 1; do { if (!trie_state_walk (shot->dict_state, th_tis2uni (s[shot->str_pos++]))) { is_terminal = 0; is_keep_node = 0; break; } is_terminal = trie_state_is_terminal (shot->dict_state); if (shot->str_pos >= len) { if (!is_terminal) { is_keep_node = 0; } break; } } while (!(is_terminal && brkpos_hints[shot->str_pos])); if (!is_keep_node) { pool = brk_pool_delete (pool, node); continue; } /* if node still kept, mark break position and rewind dictionary */ if (is_terminal) { if (shot->str_pos < len && !trie_state_is_single (shot->dict_state)) { /* add node to mark break position instead of current */ node = brk_pool_node_new (shot); pool = brk_pool_add (pool, node); shot = &node->shot; } trie_state_rewind (shot->dict_state); shot->brk_pos [shot->cur_brk_pos++] = shot->str_pos; } if (shot->str_pos == len || shot->cur_brk_pos == n) { /* path is done; get result & remove it */ if (shot->cur_brk_pos > ret) { ret = shot->cur_brk_pos; memcpy (pos, shot->brk_pos, ret * sizeof (pos[0])); } pool = brk_pool_delete (pool, node); /* stop as soon as first solution is found */ if (ret == n) break; } else { /* find matched nodes, contest and keep the best one */ while (NULL != (match = brk_pool_match (pool, node))) { pool = brk_pool_delete (pool, match); } } } brk_pool_free (pool); return ret; }
static int brk_maximal_do_impl (const thchar_t *s, int len, const char *brkpos_hints, int pos[], size_t n) { BrkPool *pool; BrkPool *node; BestBrk *best_brk; RecovHist recov_hist; int ret; pool = brk_root_pool (n); best_brk = best_brk_new (n); if (!best_brk) return 0; recov_hist.pos = recov_hist.recov = -1; while (NULL != (node = brk_pool_get_node (pool))) { BrkShot *shot = &node->shot; BrkPool *match; int is_keep_node, is_terminal, is_recovered; int str_pos; /* walk dictionary character-wise till a word is matched */ is_keep_node = 1; is_recovered = 0; str_pos = shot->str_pos; do { if (!trie_state_walk (shot->dict_state, th_tis2uni (s[str_pos++]))) { int recovered; is_terminal = 0; /* try to recover from error */ recovered = brk_recover (s, len, shot->str_pos + 1, brkpos_hints, &recov_hist); if (-1 != recovered) { /* add penalty by recovered - recent break pos */ shot->penalty += recovered; if (shot->cur_brk_pos > 0) shot->penalty -= shot->brk_pos[shot->cur_brk_pos - 1]; str_pos = recovered; is_recovered = 1; } else { /* add penalty with string len - recent break pos */ shot->penalty += len; if (shot->cur_brk_pos > 0) shot->penalty -= shot->brk_pos[shot->cur_brk_pos - 1]; shot->brk_pos [shot->cur_brk_pos++] = str_pos = len; is_keep_node = 0; } break; } is_terminal = trie_state_is_terminal (shot->dict_state); if (str_pos >= len) { if (!is_terminal) { /* add penalty with string len - recent break pos */ shot->penalty += len; if (shot->cur_brk_pos > 0) shot->penalty -= shot->brk_pos[shot->cur_brk_pos - 1]; shot->brk_pos [shot->cur_brk_pos++] = len; is_keep_node = 0; } break; } } while (!(is_terminal && brkpos_hints[str_pos])); shot->str_pos = str_pos; /* if node still kept, mark break position and rewind dictionary */ if (is_keep_node && (is_terminal || is_recovered)) { if (shot->str_pos < len && is_terminal && !trie_state_is_single (shot->dict_state)) { /* add node to mark break position instead of current */ node = brk_pool_node_new (shot); pool = brk_pool_add (pool, node); shot = &node->shot; } trie_state_rewind (shot->dict_state); shot->brk_pos [shot->cur_brk_pos++] = shot->str_pos; } if (!is_keep_node || shot->str_pos == len || shot->cur_brk_pos >= n) { /* path is done; contest and remove */ best_brk_contest (best_brk, shot); pool = brk_pool_delete (pool, node); } else { /* find matched nodes, contest and keep the best one */ while (NULL != (match = brk_pool_match (pool, node))) { BrkPool *del_node; if (match->shot.penalty < node->shot.penalty || (match->shot.penalty == node->shot.penalty && match->shot.cur_brk_pos < node->shot.cur_brk_pos)) { del_node = node; node = match; } else { del_node = match; } pool = brk_pool_delete (pool, del_node); } } } ret = best_brk->cur_brk_pos; memcpy (pos, best_brk->brk_pos, ret * sizeof (pos[0])); brk_pool_free (pool); best_brk_free (best_brk); return ret; }