void CTextService::_SearchDic(WCHAR command) { DWORD bytesWrite, bytesRead; std::wstring s, se, fmt, scd, scr, sad, sar, okurikey; std::wregex r; std::wsmatch m; _StartManager(); _ConnectDic(); ZeroMemory(pipebuf, sizeof(pipebuf)); if(okuriidx != 0) { okurikey = kana.substr(okuriidx + 1); if(okurikey.size() >= 2 && IS_SURROGATE_PAIR(okurikey.c_str()[0], okurikey.c_str()[1])) { okurikey = okurikey.substr(0, 2); } else { okurikey = okurikey.substr(0, 1); } } _snwprintf_s(pipebuf, _TRUNCATE, L"%c\n%s\t%s\t%s\n", command, searchkey.c_str(), searchkeyorg.c_str(), okurikey.c_str()); bytesWrite = (DWORD)((wcslen(pipebuf) + 1) * sizeof(WCHAR)); if(WriteFile(hPipe, pipebuf, bytesWrite, &bytesWrite, nullptr) == FALSE) { goto exit; } ZeroMemory(pipebuf, sizeof(pipebuf)); bytesRead = 0; if(ReadFile(hPipe, pipebuf, sizeof(pipebuf), &bytesRead, nullptr) == FALSE) { goto exit; } if(pipebuf[0] != REP_OK) { goto exit; } s.assign(pipebuf); r.assign(L"(.*)\t(.*)\t(.*)\t(.*)\n"); while(std::regex_search(s, m, r)) { se = m.str(); s = m.suffix(); fmt.assign(L"$1"); scd = std::regex_replace(se, r, fmt); fmt.assign(L"$2"); scr = std::regex_replace(se, r, fmt); fmt.assign(L"$3"); sad = std::regex_replace(se, r, fmt); fmt.assign(L"$4"); sar = std::regex_replace(se, r, fmt); if(scd.empty()) { scd = scr; } if(sad.empty()) { sad = sar; } candidates.push_back(CANDIDATE(CANDIDATEBASE(scd, sad), CANDIDATEBASE(scr, sar))); } exit: ZeroMemory(pipebuf, sizeof(pipebuf)); _DisconnectDic(); }
HRESULT CTextService::_Update(TfEditCookie ec, ITfContext *pContext, BOOL fixed, BOOL back) { std::wstring comptext; WCHAR candidatecount[16]; WCHAR useraddmode = REQ_USER_ADD_1; LONG cchCursor = 0; LONG cchOkuri = 0; BOOL showmodemark = cx_showmodemark; if(pContext == NULL) //辞書登録用 { showmodemark = TRUE; } if(showentry && ( (fixed && showcandlist) || (cx_untilcandlist == 0) || (candidx + 1 < cx_untilcandlist) || (candidates.size() + 1 == cx_untilcandlist) )) { if(!candidates.empty() && candidx < candidates.size()) { if(!fixed && showmodemark) { comptext.append(markHenkan); } comptext.append(candidates[candidx].first.first); if(okuriidx != 0) { cchOkuri = (LONG)comptext.size(); comptext.append(kana.substr(okuriidx + 1)); useraddmode = REQ_USER_ADD_0; } cchCursor = (LONG)comptext.size(); if(!fixed) { if(purgedicmode) { comptext.append(L" [削除?(Y/n)]"); } else { if(cx_annotation && !cx_annotatlst && !candidates[candidx].first.second.empty()) { comptext.append(markAnnotation + candidates[candidx].first.second); } if(cx_untilcandlist == 0 && cx_dispcandnum) { comptext.append(L" ("); _snwprintf_s(candidatecount, _TRUNCATE, L"%u", (UINT)candidx + 1); comptext.append(candidatecount); comptext.append(L"/"); _snwprintf_s(candidatecount, _TRUNCATE, L"%u", (UINT)candidates.size()); comptext.append(candidatecount); comptext.append(L")"); } if(!showmodemark && comptext.empty()) { comptext.append(markSP); } } } //ユーザー辞書登録 if(fixed && !candidates[candidx].second.first.empty()) { _AddUserDic(useraddmode, ((candorgcnt <= candidx) ? searchkey : searchkeyorg), candidates[candidx].second.first, candidates[candidx].second.second); } } else { //候補なし or 候補が尽きた if(!fixed) { if(!showmodemark) { if(kana.empty()) { comptext.append(markSP); } } else { comptext.append(markHenkan); } } if(okuriidx == 0) { comptext.append(kana); } else { comptext.append(kana.substr(0, okuriidx)); cchOkuri = (LONG)comptext.size(); if(!fixed && showmodemark) { comptext.append(markOkuri); } comptext.append(kana.substr(okuriidx + 1)); } cchCursor = (LONG)comptext.size(); if(pContext == NULL && _pCandidateList != NULL) //辞書登録用 { _pCandidateList->_SetText(comptext, FALSE, FALSE, TRUE); return S_OK; } else { _SetText(ec, pContext, comptext, cchCursor, cchOkuri, FALSE); //辞書登録表示開始 return _ShowCandidateList(ec, pContext, TRUE, FALSE); } } } else { if(inputkey) { if(!fixed) { if(!showmodemark) { if(kana.empty() && roman.empty()) { comptext.append(markSP); } } else { if(showentry && (candidx + 1 == cx_untilcandlist)) { comptext.append(markHenkan); } else { comptext.append(markMidashi); } } } if(!roman.empty() || !kana.empty()) { if(okuriidx == 0) { comptext.append(kana); if(pContext == NULL && !fixed && cursoridx != kana.size()) //辞書登録用 { comptext.insert(cursoridx + (comptext.size() - kana.size()), markCursor); } } else { comptext.append(kana.substr(0, okuriidx)); cchOkuri = (LONG)comptext.size(); if(!fixed && showmodemark && !complement) { comptext.append(markOkuri); } if(okuriidx + 1 < kana.size()) { comptext.append(kana.substr(okuriidx + 1)); } if(pContext == NULL && !fixed && roman.empty() && cursoridx != kana.size()) //辞書登録用 { if(!showmodemark) { if(cursoridx < okuriidx) { comptext.insert(cursoridx, markCursor); } else { comptext.insert(cursoridx - 1, markCursor); } } else { if(complement && okuriidx != 0) { comptext.insert(okuriidx + 1, L" ["); comptext.append(L"]"); } comptext.insert(cursoridx + 1, markCursor); } } } if(!fixed && !roman.empty()) { if(!showmodemark) { if(okuriidx != 0 && okuriidx < cursoridx) { if(cx_showroman) { comptext.insert(cursoridx - 1, roman); } else { comptext.insert(cursoridx - 1, markSP); } } else { if(cx_showroman) { comptext.insert(cursoridx, roman); } else { comptext.insert(cursoridx, markSP); } } } else { if(cx_showroman) { comptext.insert(cursoridx + 1, roman); } else { comptext.insert(cursoridx + 1, markSP); } } if(okuriidx != 0 && cursoridx <= okuriidx) { if(cx_showroman) { cchOkuri += (LONG)roman.size(); } else { cchOkuri += 1; } } } } if(showentry && (candidx + 1 == cx_untilcandlist)) { cchCursor = (LONG)comptext.size(); } } else { if(!kana.empty()) { comptext.append(kana); } else { if(!fixed) { if(cx_showroman) { comptext.append(roman); } else { comptext.append(markSP); } } } } } if(fixed && back && cx_backincenter && !comptext.empty()) { // surrogate pair if(comptext.size() >= 2 && IS_SURROGATE_PAIR(comptext[comptext.size() - 2], comptext[comptext.size() - 1])) { comptext.pop_back(); comptext.pop_back(); } else { comptext.pop_back(); } } _EndInputModeWindow(); if(inputkey && !fixed && !showcandlist && showentry && (((cx_untilcandlist != 1) && (candidx + 1 == cx_untilcandlist)) || (cx_untilcandlist == 1)) && (candidates.size() + 1 != cx_untilcandlist)) { if(pContext == NULL && _pCandidateList != NULL) //辞書登録用 { showcandlist = TRUE; candidx = 0; _pCandidateList->_SetText(comptext, FALSE, TRUE, FALSE); return S_OK; } else { _SetText(ec, pContext, comptext, cchCursor, cchOkuri, fixed); //候補一覧表示開始 showcandlist = TRUE; candidx = 0; return _ShowCandidateList(ec, pContext, FALSE, FALSE); } } if(pContext == NULL && _pCandidateList != NULL) //辞書登録用 { _pCandidateList->_SetText(comptext, fixed, FALSE, FALSE); return S_OK; } else { return _SetText(ec, pContext, comptext, cchCursor, cchOkuri, fixed); } }
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; }
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; }
void CCandidateWindow::_OnKeyDownRegword(UINT uVKey) { WCHAR ch; BYTE sf; _GetChSf(uVKey, ch, sf); //確定していないとき if(!regwordfixed) { _pTextService->showcandlist = FALSE; //候補一覧表示をループさせる _HandleKey((WPARAM)uVKey, SKK_NULL); _Update(); if(_pInputModeWindow != NULL) { _pInputModeWindow->_Redraw(); } return; } if(_pTextService->_IsKeyVoid(ch, (BYTE)uVKey)) { _pTextService->_UpdateLanguageBar(); if(_pInputModeWindow != NULL) { _pInputModeWindow->_Redraw(); } if(sf == SKK_ENTER) { return; } } switch(sf) { case SKK_ENTER: _RestoreStatusReg(); _ClearStatusReg(); regwordfixed = FALSE; regwordul = FALSE; regword = FALSE; //スペースのみのとき空として扱う if(std::regex_match(regwordtext, std::wregex(L"^\\s+$"))) { regwordtext.clear(); } if(regwordtext.empty()) //空のときはキャンセル扱い { regwordtext.clear(); regwordtextpos = 0; if(!_reg) { _InitList(); _uIndex = _PageIndex[_PageIndex.size() - 1]; _Update(); _UpdateUIElement(); if(_pInputModeWindow != NULL) { _pInputModeWindow->_Show(FALSE); } } else { if(_pCandidateWindowParent == NULL) { if(_pTextService->candidates.empty()) { _EndCandidateList(SKK_CANCEL); } else { _EndCandidateList(SKK_PREV_CAND); } } else { _PreEndReq(); if(_pTextService->candidates.empty()) { _HandleKey(0, SKK_CANCEL); } else { _HandleKey(0, SKK_PREV_CAND); } _EndReq(); } } } else { std::wstring conv; std::wstring candidate; std::wstring annotation; std::wsmatch result; std::wstring okurikey; //候補と注釈を、行頭以外の最後のセミコロンで分割 if(std::regex_search(regwordtext, result, std::wregex(L".+;"))) { candidate = result.str().substr(0, result.str().size() - 1); annotation = result.suffix(); } else { candidate = regwordtext; annotation.clear(); } if(_pTextService->okuriidx != 0) { okurikey = _pTextService->kana.substr(_pTextService->okuriidx + 1); if(okurikey.size() >= 2 && IS_SURROGATE_PAIR(okurikey.c_str()[0], okurikey.c_str()[1])) { okurikey = okurikey.substr(0, 2); } else { okurikey = okurikey.substr(0, 1); } } //候補変換 _pTextService->_ConvertWord(REQ_CONVERTCND, _pTextService->searchkeyorg, candidate, okurikey, conv); if(_pTextService->searchkey.empty() || conv.empty()) { //変換見出し語が空文字列または //変換済み候補が空文字列であれば未変換見出し語を見出し語とする _pTextService->searchkey = _pTextService->searchkeyorg; } if(conv.empty()) { conv = candidate; } _pTextService->candidates.push_back(CANDIDATE (CANDIDATEBASE(conv, annotation), (CANDIDATEBASE(candidate, annotation)))); _pTextService->candidx = _pTextService->candidates.size() - 1; _pTextService->candorgcnt = 0; regwordtext.clear(); regwordtextpos = 0; if(_pCandidateWindowParent == NULL) { _EndCandidateList(SKK_ENTER); } else { _PreEndReq(); _HandleKey(0, SKK_ENTER); _EndReq(); } } break; case SKK_CANCEL: _RestoreStatusReg(); _ClearStatusReg(); regwordfixed = FALSE; regwordul = FALSE; regword = FALSE; regwordtext.clear(); regwordtextpos = 0; if(!_reg) { _InitList(); _uIndex = _PageIndex[_PageIndex.size() - 1]; _Update(); _UpdateUIElement(); if(_pInputModeWindow != NULL) { _pInputModeWindow->_Show(FALSE); } } else { if(_pCandidateWindowParent == NULL) { if(_pTextService->candidates.empty()) { _EndCandidateList(SKK_CANCEL); } else { _EndCandidateList(SKK_PREV_CAND); } } else { _PreEndReq(); if(_pTextService->candidates.empty()) { _HandleKey(0, SKK_CANCEL); } else { _HandleKey(0, SKK_PREV_CAND); } _EndReq(); } } break; case SKK_BACK: if(comptext.empty() && regwordtextpos > 0 && regwordtext.size() > 0) { // surrogate pair if(regwordtext.size() >= 2 && regwordtextpos >= 2 && IS_SURROGATE_PAIR(regwordtext[regwordtextpos - 2], regwordtext[regwordtextpos - 1])) { regwordtextpos -= 2; regwordtext.erase(regwordtext.begin() + regwordtextpos); regwordtext.erase(regwordtext.begin() + regwordtextpos); } else { --regwordtextpos; regwordtext.erase(regwordtext.begin() + regwordtextpos); } _Update(); } break; case SKK_DELETE: if(comptext.empty() && regwordtextpos < regwordtext.size()) { // surrogate pair if(regwordtext.size() >= regwordtextpos + 2 && IS_SURROGATE_PAIR(regwordtext[regwordtextpos + 0], regwordtext[regwordtextpos + 1])) { regwordtext.erase(regwordtext.begin() + regwordtextpos); regwordtext.erase(regwordtext.begin() + regwordtextpos); } else { regwordtext.erase(regwordtext.begin() + regwordtextpos); } _Update(); } break; case SKK_LEFT: if(comptext.empty() && regwordtextpos > 0 && regwordtext.size() > 0) { // surrogate pair if(regwordtext.size() >= 2 && regwordtextpos >= 2 && IS_SURROGATE_PAIR(regwordtext[regwordtextpos - 2], regwordtext[regwordtextpos - 1])) { regwordtextpos -= 2; } else { --regwordtextpos; } _Update(); } break; case SKK_UP: if(comptext.empty()) { regwordtextpos = 0; _Update(); } break; case SKK_RIGHT: if(comptext.empty() && regwordtextpos < regwordtext.size()) { // surrogate pair if(regwordtext.size() >= regwordtextpos + 2 && IS_SURROGATE_PAIR(regwordtext[regwordtextpos + 0], regwordtext[regwordtextpos + 1])) { regwordtextpos += 2; } else { ++regwordtextpos; } _Update(); } break; case SKK_DOWN: if(comptext.empty()) { regwordtextpos = regwordtext.size(); _Update(); } break; case SKK_PASTE: if(IsClipboardFormatAvailable(CF_UNICODETEXT)) { if(OpenClipboard(NULL)) { HANDLE hCB = GetClipboardData(CF_UNICODETEXT); if(hCB != NULL) { LPWSTR pwCB = (LPWSTR)GlobalLock(hCB); if(pwCB != NULL) { std::wstring scb = std::regex_replace(std::wstring(pwCB), std::wregex(L"[\\x00-\\x19]"), std::wstring(L"")); regwordtext.insert(regwordtextpos, scb); regwordtextpos += scb.size(); _Update(); _UpdateUIElement(); GlobalUnlock(hCB); } } CloseClipboard(); } } break; default: _HandleKey((WPARAM)uVKey, SKK_NULL); if(_pInputModeWindow != NULL) { _pInputModeWindow->_Redraw(); } break; } }