HRESULT CTextService::_HandleCharReturn(TfEditCookie ec, ITfContext *pContext, BOOL back) { _EndCompletionList(ec, pContext); //terminate composition cursoridx = kana.size(); _Update(ec, pContext, TRUE, back); _TerminateComposition(ec, pContext); _ResetStatus(); return S_OK; }
HRESULT CTextService::_HandleCharShift(TfEditCookie ec, ITfContext *pContext) { if(showentry || (!inputkey && !kana.empty() && roman.empty())) { _EndCompletionList(ec, pContext); //leave composition cursoridx = kana.size(); _Update(ec, pContext, TRUE); if(pContext != NULL) { ITfRange *pRange; if(_IsComposing() && _pComposition->GetRange(&pRange) == S_OK) { pRange->Collapse(ec, TF_ANCHOR_END); _pComposition->ShiftStart(ec, pRange); SafeRelease(&pRange); } } _ResetStatus(); } return S_OK; }
void CTextService::_StartConv(TfEditCookie ec, ITfContext *pContext) { CANDIDATES candidates_sel; CANDIDATES candidates_hint; std::wstring keyhint, key, hint; std::wstring candidate, str; size_t okuriidx_bak; _EndCompletionList(ec, pContext); size_t hintchidx = kana.find_first_of(CHAR_SKK_HINT); if(!hintmode || hintchidx == std::wstring::npos) { _StartSubConv(REQ_SEARCH); } else { keyhint = kana; key = keyhint.substr(0, hintchidx); if(okuriidx > key.size()) { keyhint = keyhint.substr(0, okuriidx + 1); okuriidx = 0; } okuriidx_bak = okuriidx; okuriidx = 0; hint = keyhint.substr(hintchidx + 1); //ヒント検索 kana = hint; _StartSubConv(REQ_SEARCH); candidates_hint = candidates; //通常検索 okuriidx = okuriidx_bak; kana = key; cursoridx = kana.size(); _StartSubConv(REQ_SEARCH); //ヒント候補の文字を含む通常候補をヒント候補順で抽出 FORWARD_ITERATION_I(candidates_hint_itr, candidates_hint) { candidate = candidates_hint_itr->first.first; for(size_t i = 0; i < candidate.size(); i++) { str.clear(); if((i + 1) != candidate.size() && IS_SURROGATE_PAIR(candidate[i], candidate[i + 1])) { str.push_back(candidate[i]); str.push_back(candidate[i + 1]); i++; } else { str.push_back(candidate[i]); } FORWARD_ITERATION(candidates_itr, candidates) { if(candidates_itr->first.first.find(str) != std::wstring::npos) { candidates_sel.push_back(*candidates_itr); candidates_itr = candidates.erase(candidates_itr); } else { ++candidates_itr; } } } } candidates = candidates_sel; }
HRESULT CTextService::_HandleControl(TfEditCookie ec, ITfContext *pContext, BYTE sf, WCHAR ch) { switch(sf) { case SKK_KANA: if(abbrevmode && !showentry) { break; } switch(inputmode) { case im_hiragana: case im_katakana: _ConvRoman(); if(inputkey && !showentry) { if(okuriidx != 0) { kana.erase(okuriidx, 1); okuriidx = 0; } //ひらがな/カタカナに変換 _ConvKanaToKana(kana, inputmode, kana, (inputmode == im_hiragana ? im_katakana : im_hiragana)); _HandleCharReturn(ec, pContext); } else { _HandleCharReturn(ec, pContext); //ひらがな/カタカナモードへ inputmode = (inputmode == im_hiragana ? im_katakana : im_hiragana); _UpdateLanguageBar(); } return S_OK; break; case im_katakana_ank: _ConvRoman(); _HandleCharReturn(ec, pContext); //ひらがなモードへ inputmode = im_hiragana; _UpdateLanguageBar(); return S_OK; break; default: break; } break; case SKK_CONV_CHAR: if(abbrevmode && !showentry) { //全英に変換 ASCII_JLATIN_CONV ajc; ajc.ascii[1] = L'\0'; roman = kana; kana.clear(); cursoridx = 0; for(size_t i = 0; i < roman.size(); i++) { ajc.ascii[0] = roman[i]; if(_ConvAsciiJLatin(&ajc) == S_OK) { kana.append(ajc.jlatin); } } _HandleCharReturn(ec, pContext); return S_OK; break; } switch(inputmode) { case im_hiragana: case im_katakana: _ConvRoman(); if(inputkey && !showentry) { if(okuriidx != 0) { kana.erase(okuriidx, 1); okuriidx = 0; } //半角カタカナに変換 _ConvKanaToKana(kana, inputmode, kana, im_katakana_ank); _HandleCharReturn(ec, pContext); } else { _HandleCharReturn(ec, pContext); //半角カタカナモードへ inputmode = im_katakana_ank; _UpdateLanguageBar(); } return S_OK; break; case im_katakana_ank: _ConvRoman(); _HandleCharReturn(ec, pContext); //ひらがなモードへ inputmode = im_hiragana; _UpdateLanguageBar(); return S_OK; break; default: break; } break; case SKK_JLATIN: case SKK_ASCII: if(abbrevmode && !showentry) { break; } switch(inputmode) { case im_hiragana: case im_katakana: case im_katakana_ank: _ConvRoman(); _HandleCharReturn(ec, pContext); //アスキー/全英モードへ inputmode = (sf == SKK_ASCII ? im_ascii : im_jlatin); _UpdateLanguageBar(); return S_OK; break; default: break; } break; case SKK_JMODE: switch(inputmode) { case im_jlatin: case im_ascii: //ひらがなモードへ inputmode = im_hiragana; _UpdateLanguageBar(); return S_OK; break; default: break; } break; case SKK_ABBREV: if(abbrevmode && !showentry) { break; } switch(inputmode) { case im_hiragana: case im_katakana: _ConvRoman(); if(!inputkey || showentry) { _HandleCharShift(ec, pContext); //見出し入力開始(abbrev) inputkey = TRUE; abbrevmode = TRUE; } _Update(ec, pContext); return S_OK; break; default: break; } break; case SKK_AFFIX: if(!inputkey || (abbrevmode && !showentry)) { break; } if(showentry || (inputkey && kana.empty() && roman.empty())) { if(showentry) { _HandleCharShift(ec, pContext); } //見出し入力開始(接尾辞) inputkey = TRUE; ch = L'>'; kana.push_back(ch); cursoridx++; _Update(ec, pContext); return S_OK; } switch(inputmode) { case im_hiragana: case im_katakana: _ConvRoman(); if(!kana.empty() && okuriidx == 0) { ch = L'>'; roman.clear(); kana.push_back(ch); cursoridx = kana.size(); if(cx_begincvokuri && !hintmode) { //辞書検索開始(接頭辞) showentry = TRUE; _StartConv(ec, pContext); } } _Update(ec, pContext); return S_OK; break; default: break; } break; case SKK_NEXT_CAND: if(showentry) { _NextConv(); _Update(ec, pContext); return S_OK; } else if(inputkey) { _ConvRoman(); if(okuriidx != 0 && okuriidx < kana.size()) { if(kana[okuriidx] == CHAR_SKK_OKURI) { kana.erase(okuriidx, 1); if(okuriidx < cursoridx) { cursoridx--; } okuriidx = 0; } } if(!kana.empty()) { //候補表示開始 cursoridx = kana.size(); showentry = TRUE; _StartConv(ec, pContext); } _Update(ec, pContext); return S_OK; } break; case SKK_PREV_CAND: if(showentry) { _PrevConv(); if(!showentry && (cx_dynamiccomp || cx_dyncompmulti)) { _DynamicComp(ec, pContext); } else { _Update(ec, pContext); } return S_OK; } break; case SKK_PURGE_DIC: if(showentry) { if(purgedicmode) { purgedicmode = FALSE; _DelUserDic((okuriidx == 0 ? REQ_USER_DEL_1 : REQ_USER_DEL_0), ((candorgcnt <= candidx) ? searchkey : searchkeyorg), candidates[candidx].second.first); showentry = FALSE; candidx = 0; kana.clear(); okuriidx = 0; cursoridx = 0; _HandleCharReturn(ec, pContext); } else { purgedicmode = TRUE; _Update(ec, pContext); } return S_OK; } break; case SKK_NEXT_COMP: if(inputkey && !showentry) { _ConvRoman(); if(!complement) { _Update(ec, pContext); } _NextComp(); BOOL vertical = _GetVertical(ec, pContext); if(complement && cx_compuserdic) { if(candidx == 0) { _UserDicComp(); } if((!cx_stacompmulti && !cx_dyncompmulti) || !vertical || pContext == NULL) { okuriidx = kana.size(); if(candidx < candidates.size() && !candidates[candidx].first.second.empty()) { kana += markSP + candidates[candidx].first.second; } kana.insert(okuriidx, 1, CHAR_SKK_OKURI); _Update(ec, pContext); kana.erase(okuriidx); okuriidx = 0; } } else if(!complement && (cx_dynamiccomp || cx_dyncompmulti)) { _DynamicComp(ec, pContext, TRUE); } else { if(!complement && cx_stacompmulti) { _EndCompletionList(ec, pContext); } if((!cx_stacompmulti && !cx_dyncompmulti) || !vertical || pContext == NULL) { _Update(ec, pContext); } } if(complement && candidx == 0 && pContext != NULL) { if(cx_dyncompmulti) { if(_pCandidateList == NULL) { showcandlist = FALSE; _ShowCandidateList(ec, pContext, FALSE, TRUE); } else { _pCandidateList->_UpdateComp(); } } else if(cx_stacompmulti) { showcandlist = FALSE; _ShowCandidateList(ec, pContext, FALSE, TRUE); } } return S_OK; } break; case SKK_PREV_COMP: if(inputkey && !showentry) { _PrevComp(); BOOL vertical = _GetVertical(ec, pContext); if(complement && cx_compuserdic) { if((!cx_stacompmulti && !cx_dyncompmulti) || !vertical || pContext == NULL) { okuriidx = kana.size(); if(candidx < candidates.size() && !candidates[candidx].first.second.empty()) { kana += markSP + candidates[candidx].first.second; } kana.insert(okuriidx, 1, CHAR_SKK_OKURI); _Update(ec, pContext); kana.erase(okuriidx); okuriidx = 0; } } else if(!complement && (cx_dynamiccomp || cx_dyncompmulti)) { _DynamicComp(ec, pContext, TRUE); } else { if(!complement && cx_stacompmulti) { _EndCompletionList(ec, pContext); } if((!cx_stacompmulti && !cx_dyncompmulti) || !vertical || pContext == NULL) { _Update(ec, pContext); } } return S_OK; } break; case SKK_HINT: if(!inputkey || abbrevmode) { break; } if(showentry) { candidx = 0; showentry = FALSE; } _ConvRoman(); if(!kana.empty() && kana.find_first_of(CHAR_SKK_HINT) == std::wstring::npos) { hintmode = TRUE; cursoridx = kana.size(); kana.insert(cursoridx, 1, CHAR_SKK_HINT); cursoridx++; } if(cx_dynamiccomp || cx_dyncompmulti) { _DynamicComp(ec, pContext); } else { _Update(ec, pContext); } return S_OK; break; case SKK_CONV_POINT: if(abbrevmode && !showentry) { break; } switch(inputmode) { case im_hiragana: case im_katakana: if(showentry) { _HandleCharShift(ec, pContext); } if(!inputkey) { if(_ConvShift(ch)) { if(!kana.empty()) { _HandleCharShift(ec, pContext); } //見出し入力開始 inputkey = TRUE; _Update(ec, pContext); } } else { if(_ConvShift(ch) && (okuriidx == 0) && (cursoridx != 0)) { //送り仮名入力開始 kana.insert(cursoridx, 1, CHAR_SKK_OKURI); //送りローマ字 okuriidx = cursoridx; cursoridx++; if(cx_dynamiccomp || cx_dyncompmulti) { _DynamicComp(ec, pContext); } else { _Update(ec, pContext); } } } if(ch == L'\0') { return S_OK; } break; default: break; } break; case SKK_DIRECT: if(inputkey && !showentry && ((okuriidx == 0) || ((okuriidx != 0) && (okuriidx + 1 != cursoridx)))) { _ConvRoman(); kana.insert(cursoridx, 1, ch); cursoridx++; if(cx_dynamiccomp || cx_dyncompmulti) { _DynamicComp(ec, pContext); } else { _Update(ec, pContext); } return S_OK; } break; case SKK_ENTER: _ConvRoman(); _HandleCharReturn(ec, pContext, (_GetSf(0, ch) == SKK_BACK ? TRUE : FALSE)); return S_OK; break; case SKK_CANCEL: _ConvRoman(); if(showentry) { candidx = 0; showentry = FALSE; if(cx_delokuricncl && okuriidx != 0) { kana = kana.substr(0, okuriidx); okuriidx = 0; cursoridx = kana.size(); } if(cx_delcvposcncl && okuriidx != 0) { kana.erase(okuriidx, 1); okuriidx = 0; cursoridx--; } if(cx_dynamiccomp || cx_dyncompmulti) { _DynamicComp(ec, pContext); } else { if(cx_stacompmulti) { _EndCompletionList(ec, pContext); } _Update(ec, pContext); } } else { kana.clear(); okuriidx = 0; cursoridx = 0; _HandleCharReturn(ec, pContext); } return S_OK; break; case SKK_BACK: if(showentry) { if(_HandleControl(ec, pContext, (cx_backincenter ? SKK_ENTER : SKK_PREV_CAND), ch) == S_OK) { return S_OK; } } if(inputkey && roman.empty() && kana.empty()) { _HandleCharReturn(ec, pContext); return S_OK; } if(!roman.empty()) { roman.pop_back(); if(roman.empty()) { if(okuriidx != 0 && okuriidx + 1 == cursoridx) { kana.erase(cursoridx - 1, 1); cursoridx--; okuriidx = 0; } } } else if(okuriidx != 0 && okuriidx + 1 == cursoridx) { kana.erase(cursoridx - 1, 1); cursoridx--; okuriidx = 0; } else if(!kana.empty()) { // surrogate pair if(cursoridx >= 2 && IS_SURROGATE_PAIR(kana[cursoridx - 2], kana[cursoridx - 1])) { kana.erase(cursoridx - 2, 2); cursoridx -= 2; if(okuriidx != 0 && cursoridx < okuriidx) { okuriidx -= 2; if(okuriidx == 0) { kana.erase(0, 1); } } } else if(cursoridx >= 1) { kana.erase(cursoridx - 1, 1); cursoridx--; if(okuriidx != 0 && cursoridx < okuriidx) { okuriidx--; if(okuriidx == 0) { kana.erase(0, 1); } } } if(okuriidx != 0 && okuriidx + 1 == cursoridx) { kana.erase(cursoridx - 1, 1); cursoridx--; okuriidx = 0; } } if(!inputkey && roman.empty() && kana.empty()) { _HandleCharReturn(ec, pContext); } else { if(cx_dynamiccomp || cx_dyncompmulti) { _DynamicComp(ec, pContext); } else { _Update(ec, pContext); } } return S_OK; break; case SKK_DELETE: if(!inputkey || showentry || kana.empty()) { break; } if(okuriidx != 0 && okuriidx == cursoridx) { kana.erase(cursoridx, 1); okuriidx = 0; } // surrogate pair if(kana.size() - cursoridx >= 2 && IS_SURROGATE_PAIR(kana[cursoridx], kana[cursoridx + 1])) { kana.erase(cursoridx, 2); if(okuriidx >= 2 && cursoridx < okuriidx) { okuriidx -= 2; if(okuriidx == 0) { kana.erase(cursoridx, 1); } } } else { kana.erase(cursoridx, 1); if(okuriidx >= 1 && cursoridx < okuriidx) { okuriidx--; if(okuriidx == 0) { kana.erase(cursoridx, 1); } } } if(cx_dynamiccomp || cx_dyncompmulti) { _DynamicComp(ec, pContext); } else { _Update(ec, pContext); } return S_OK; break; case SKK_VOID: return S_OK; break; case SKK_LEFT: if(showentry) { break; } if(!roman.empty() || (okuriidx != 0 && kana[okuriidx] == CHAR_SKK_OKURI)) { _ConvRoman(); _HandleCharShift(ec, pContext); } if(!kana.empty() && cursoridx > 0) { // surrogate pair if(cursoridx >= 2 && IS_SURROGATE_PAIR(kana[cursoridx - 2], kana[cursoridx - 1])) { cursoridx -= 2; } else { cursoridx--; } if(okuriidx != 0 && okuriidx + 1 == cursoridx) { cursoridx--; } } if(cx_dynamiccomp || cx_dyncompmulti) { _DynamicComp(ec, pContext); } else { _Update(ec, pContext); } return S_OK; break; case SKK_UP: if(showentry) { break; } if(!roman.empty() || (okuriidx != 0 && kana[okuriidx] == CHAR_SKK_OKURI)) { _ConvRoman(); _HandleCharShift(ec, pContext); } cursoridx = 0; if(cx_dynamiccomp || cx_dyncompmulti) { _DynamicComp(ec, pContext); } else { _Update(ec, pContext); } return S_OK; break; case SKK_RIGHT: if(showentry) { break; } if(!roman.empty() || (okuriidx != 0 && kana[okuriidx] == CHAR_SKK_OKURI)) { _ConvRoman(); _HandleCharShift(ec, pContext); } if(!kana.empty() && cursoridx < kana.size()) { // surrogate pair if(kana.size() - cursoridx >= 2 && IS_SURROGATE_PAIR(kana[cursoridx], kana[cursoridx + 1])) { cursoridx += 2; } else { cursoridx++; } if(okuriidx != 0 && okuriidx + 1 == cursoridx) { cursoridx++; } } if(cx_dynamiccomp || cx_dyncompmulti) { _DynamicComp(ec, pContext); } else { _Update(ec, pContext); } return S_OK; break; case SKK_DOWN: if(showentry) { break; } if(!roman.empty() || (okuriidx != 0 && kana[okuriidx] == CHAR_SKK_OKURI)) { _ConvRoman(); _HandleCharShift(ec, pContext); } cursoridx = kana.size(); if(cx_dynamiccomp || cx_dyncompmulti) { _DynamicComp(ec, pContext); } else { _Update(ec, pContext); } return S_OK; break; case SKK_PASTE: if(!inputkey || showentry) { break; } _ConvRoman(); if(IsClipboardFormatAvailable(CF_UNICODETEXT)) { if(OpenClipboard(NULL)) { HANDLE hCB = GetClipboardData(CF_UNICODETEXT); if(hCB != NULL) { PWCHAR pwCB = (PWCHAR)GlobalLock(hCB); if(pwCB != NULL) { std::wstring scb = std::regex_replace(std::wstring(pwCB), std::wregex(L"[\\x00-\\x19]"), std::wstring(L"")); kana.insert(cursoridx, scb); if(okuriidx != 0 && cursoridx <= okuriidx) { okuriidx += scb.size(); } cursoridx += scb.size(); if(cx_dynamiccomp || cx_dyncompmulti) { _DynamicComp(ec, pContext); } else { _Update(ec, pContext); } GlobalUnlock(hCB); } } CloseClipboard(); } } break; default: break; } return E_PENDING; }