From b6a4f14363ca25f2390f9e45cca95ae8fd20ee1d Mon Sep 17 00:00:00 2001 From: nathancorvussolis Date: Fri, 21 Nov 2014 04:08:28 +0900 Subject: [PATCH] 1.7.12 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ・ローマ字仮名変換表の内部構造を配列から木構造に変更しました。  ・ローマ字の検索方法を、これまでの最短一致検索から最長一致検索に変更しています。  ・ローマ字入力の場合、ローマ字仮名変換表に「n、ん、ン、ン」の行を追加してください。何行目でもOKです。  ・ローマ字仮名変換表のローマ字「nb」,「nc」,「nd」〜「nz」の行は不要となりますが、あっても問題ありません。 ・送り仮名の先頭が入力し直されたときの送りローマ字が上書きされていなかったバグを修正しました。  ・ローマ字入力のサンプル設定で「HasiGru」と入力したとき、「はしg」ではなく、"g"はキャンセルされて「はしr」で辞書検索するようになります。 ・変換位置指定の「代替」と「送り」が異なるACTなどの設定のとき、ローマ字2文字目以降で送り仮名を開始すると送りローマ字に「送り」ではなく「代替」が使われていたバグを修正しました。  ・ACTのサンプル設定で「AcU」と入力したとき「あc」ではなく「あk」で辞書検索するようになります。 ・Windows8以降のタッチキーボードでCtrl+次頁またはCtrl+前頁を押したとき「次頁」や「前頁」という文字列が入力されないようにしました。 --- CorvusSKK.sln | 2 +- common/common.h | 6 +- imcrvcnf/PropertyConfDictionary.cpp | 6 +- imcrvcnf/convtable.cpp | 20 +- imcrvmgr/SearchUserDictionary.cpp | 12 +- imcrvtip/FnConfigure.cpp | 132 +++++++++- imcrvtip/KeyHandler.cpp | 51 ++-- imcrvtip/KeyHandlerChar.cpp | 47 +++- imcrvtip/KeyHandlerControl.cpp | 4 +- imcrvtip/KeyHandlerConv.cpp | 291 +++++++++++---------- imcrvtip/TextService.h | 21 +- imcrvtip/imcrvtip.h | 22 +- installer/README.TXT | 4 +- installer/config-sample/config - act.xml | 4 +- installer/config-sample/config - kana.xml | 20 +- installer/config-sample/config - roman.xml | 20 +- installer/config-sample/kanatable.txt | 20 +- installer/corvusskk-x64.wxs | 2 +- installer/corvusskk-x86.wxs | 2 +- 19 files changed, 399 insertions(+), 287 deletions(-) diff --git a/CorvusSKK.sln b/CorvusSKK.sln index ec9abf46..59ce51b2 100644 --- a/CorvusSKK.sln +++ b/CorvusSKK.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Express 2013 for Windows Desktop -VisualStudioVersion = 12.0.30723.0 +VisualStudioVersion = 12.0.31101.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "installer", "installer\installer.vcxproj", "{C65505E2-5456-473C-91B1-C6D91B294DC3}" ProjectSection(ProjectDependencies) = postProject diff --git a/common/common.h b/common/common.h index 3a563acc..183c426f 100644 --- a/common/common.h +++ b/common/common.h @@ -3,7 +3,7 @@ #define COMMON_H #define TEXTSERVICE_NAME L"CorvusSKK" -#define TEXTSERVICE_VER L"1.7.11" +#define TEXTSERVICE_VER L"1.7.12" #ifndef _DEBUG #define TEXTSERVICE_DESC TEXTSERVICE_NAME @@ -14,8 +14,8 @@ //for resource #define RC_AUTHOR "nathancorvussolis" #define RC_PRODUCT "CorvusSKK" -#define RC_VERSION "1.7.11" -#define RC_VERSION_D 1,7,11,0 +#define RC_VERSION "1.7.12" +#define RC_VERSION_D 1,7,12,0 #define MAX_KRNLOBJNAME 256 #define CONV_POINT_NUM 256 diff --git a/imcrvcnf/PropertyConfDictionary.cpp b/imcrvcnf/PropertyConfDictionary.cpp index 9191c886..80ad762c 100644 --- a/imcrvcnf/PropertyConfDictionary.cpp +++ b/imcrvcnf/PropertyConfDictionary.cpp @@ -89,7 +89,7 @@ void LoadSKKDicAdd(SKKDIC &skkdic, const std::wstring &key, const std::wstring & } else { - bool hit = false; + bool exist = false; FORWARD_ITERATION_I(sc_itr, skkdic_itr->second) { if(sc_itr->first == candidate) @@ -107,11 +107,11 @@ void LoadSKKDicAdd(SKKDIC &skkdic, const std::wstring &key, const std::wstring & sc_itr->second.assign(MakeConcat(annotation_esc)); } } - hit = true; + exist = true; break; } } - if(!hit) + if(!exist) { skkdic_itr->second.push_back(SKKDICCANDIDATE(candidate, MakeConcat(annotation_seps))); } diff --git a/imcrvcnf/convtable.cpp b/imcrvcnf/convtable.cpp index c27e0999..0bf050ef 100644 --- a/imcrvcnf/convtable.cpp +++ b/imcrvcnf/convtable.cpp @@ -64,25 +64,9 @@ const ROMAN_KANA_CONV roman_kana_conv_default[ROMAN_KANA_TBL_DEF_NUM] = {L"fya", L"ふゃ", L"フャ", L"フャ"}, {L"fyi", L"ふぃ", L"フィ", L"フィ"}, {L"fyu", L"ふゅ", L"フュ", L"フュ"}, {L"fye", L"ふぇ", L"フェ", L"フェ"}, {L"fyo", L"ふょ", L"フョ", L"フョ"}, {L"hwya", L"ふゃ", L"フャ", L"フャ"}, {L"hwyi", L"ふぃ", L"フィ", L"フィ"}, {L"hwyu", L"ふゅ", L"フュ", L"フュ"}, {L"hwye", L"ふぇ", L"フェ", L"フェ"}, {L"hwyo", L"ふょ", L"フョ", L"フョ"}, + {L"n", L"ん", L"ン", L"ン"}, {L"nn", L"ん", L"ン", L"ン"}, {L"n'", L"ん", L"ン", L"ン"}, - {L"nb", L"ん", L"ン", L"ン", TRUE}, - {L"nc", L"ん", L"ン", L"ン", TRUE}, - {L"nd", L"ん", L"ン", L"ン", TRUE}, - {L"nf", L"ん", L"ン", L"ン", TRUE}, - {L"ng", L"ん", L"ン", L"ン", TRUE}, - {L"nh", L"ん", L"ン", L"ン", TRUE}, - {L"nj", L"ん", L"ン", L"ン", TRUE}, - {L"nk", L"ん", L"ン", L"ン", TRUE}, - {L"nm", L"ん", L"ン", L"ン", TRUE}, - {L"np", L"ん", L"ン", L"ン", TRUE}, - {L"nr", L"ん", L"ン", L"ン", TRUE}, - {L"ns", L"ん", L"ン", L"ン", TRUE}, - {L"nt", L"ん", L"ン", L"ン", TRUE}, - {L"nv", L"ん", L"ン", L"ン", TRUE}, - {L"nw", L"ん", L"ン", L"ン", TRUE}, - {L"nx", L"ん", L"ン", L"ン", TRUE}, - {L"nz", L"ん", L"ン", L"ン", TRUE}, {L"mb", L"ん", L"ン", L"ン", TRUE}, {L"mm", L"ん", L"ン", L"ン", TRUE}, @@ -104,8 +88,8 @@ const ROMAN_KANA_CONV roman_kana_conv_default[ROMAN_KANA_TBL_DEF_NUM] = {L"tt", L"っ", L"ッ", L"ッ", TRUE}, {L"vv", L"っ", L"ッ", L"ッ", TRUE}, {L"ww", L"っ", L"ッ", L"ッ", TRUE}, - {L"yy", L"っ", L"ッ", L"ッ", TRUE}, {L"xx", L"っ", L"ッ", L"ッ", TRUE}, + {L"yy", L"っ", L"ッ", L"ッ", TRUE}, {L"zz", L"っ", L"ッ", L"ッ", TRUE}, {L"xa", L"ぁ", L"ァ", L"ァ"}, diff --git a/imcrvmgr/SearchUserDictionary.cpp b/imcrvmgr/SearchUserDictionary.cpp index 10b3e15e..e4e66f49 100644 --- a/imcrvmgr/SearchUserDictionary.cpp +++ b/imcrvmgr/SearchUserDictionary.cpp @@ -369,16 +369,16 @@ BOOL LoadSKKUserDic() { FORWARD_ITERATION_I(sc_itr1, so_itr1->second) { - bool hit = false; + bool exist = false; FORWARD_ITERATION_I(sc_itr, so_itr->second) { if(sc_itr->first == sc_itr1->first) { - hit = true; + exist = true; break; } } - if(!hit) + if(!exist) { so_itr->second.push_back(*sc_itr1); } @@ -397,16 +397,16 @@ BOOL LoadSKKUserDic() { FORWARD_ITERATION(sc_itr, so_itr->second) { - bool hit = false; + bool exist = false; REVERSE_ITERATION_I(sc_ritr, sc) { if(sc_itr->first == sc_ritr->first) { - hit = true; + exist = true; break; } } - if(!hit) + if(!exist) { sc_itr = so_itr->second.erase(sc_itr); } diff --git a/imcrvtip/FnConfigure.cpp b/imcrvtip/FnConfigure.cpp index 4828fb39..1702abf4 100644 --- a/imcrvtip/FnConfigure.cpp +++ b/imcrvtip/FnConfigure.cpp @@ -576,8 +576,12 @@ void CTextService::_LoadConvPoint() { APPDATAXMLLIST list; int i = 0; + CONV_POINT cp; - ZeroMemory(conv_point, sizeof(conv_point)); + conv_point_s.clear(); + conv_point_s.shrink_to_fit(); + conv_point_a.clear(); + conv_point_a.shrink_to_fit(); if(ReadList(pathconfigxml, SectionConvPoint, list) == S_OK && list.size() != 0) { @@ -588,22 +592,40 @@ void CTextService::_LoadConvPoint() break; } + ZeroMemory(&cp, sizeof(cp)); + FORWARD_ITERATION_I(r_itr, *l_itr) { if(r_itr->first == AttributeCPStart) { - conv_point[i][0] = r_itr->second.c_str()[0]; + cp.ch[0] = r_itr->second.c_str()[0]; } else if(r_itr->first == AttributeCPAlter) { - conv_point[i][1] = r_itr->second.c_str()[0]; + cp.ch[1] = r_itr->second.c_str()[0]; } else if(r_itr->first == AttributeCPOkuri) { - conv_point[i][2] = r_itr->second.c_str()[0]; + cp.ch[2] = r_itr->second.c_str()[0]; } } + auto vs_itr = std::lower_bound(conv_point_s.begin(), conv_point_s.end(), + cp.ch[0], [] (CONV_POINT m, WCHAR v) { return (m.ch[0] < v); }); + + if(vs_itr == conv_point_s.end() || cp.ch[0] != vs_itr->ch[0]) + { + conv_point_s.insert(vs_itr, cp); + } + + auto va_itr = std::lower_bound(conv_point_a.begin(), conv_point_a.end(), + cp.ch[1], [] (CONV_POINT m, WCHAR v) { return (m.ch[1] < v); }); + + if(va_itr == conv_point_a.end() || cp.ch[1] != va_itr->ch[1]) + { + conv_point_a.insert(va_itr, cp); + } + i++; } } @@ -619,8 +641,10 @@ void CTextService::_LoadKana() std::wregex re(L"[\\x00-\\x19]"); std::wstring fmt(L""); - roman_kana_conv.clear(); - roman_kana_conv.shrink_to_fit(); + roman_kana_tree.ch = L'\0'; + ZeroMemory(&roman_kana_tree.conv, sizeof(roman_kana_tree.conv)); + roman_kana_tree.nodes.clear(); + roman_kana_tree.nodes.shrink_to_fit(); if(ReadList(pathconfigxml, SectionKana, list) == S_OK && list.size() != 0) { @@ -669,12 +693,84 @@ void CTextService::_LoadKana() } } - roman_kana_conv.push_back(rkc); + _AddKanaTree(roman_kana_tree, rkc, 0); + i++; } } } +BOOL CTextService::_AddKanaTree(ROMAN_KANA_NODE &tree, ROMAN_KANA_CONV rkc, int depth) +{ + BOOL added = FALSE; + + if((_countof(rkc.roman) <= depth) || (rkc.roman[depth] == L'\0')) + { + return FALSE; + } + + auto v_itr = std::lower_bound(tree.nodes.begin(), tree.nodes.end(), + rkc.roman[depth], [] (ROMAN_KANA_NODE m, WCHAR v) { return (m.ch < v); }); + + if(v_itr != tree.nodes.end() && v_itr->ch == rkc.roman[depth]) + { + if(rkc.roman[depth + 1] == L'\0') + { + if(v_itr->conv.roman[0] == L'\0') + { + //ローマ字探索最後のノードにローマ字仮名変換がなければ更新 + v_itr->conv = rkc; + } + added = TRUE; + } + else + { + //子ノードを探索 + added = _AddKanaTree(*v_itr, rkc, depth + 1); + } + } + + if(!added) + { + //子ノードを追加 + _AddKanaTreeItem(tree, rkc, depth); + added = TRUE; + } + + return added; +} + +void CTextService::_AddKanaTreeItem(ROMAN_KANA_NODE &tree, ROMAN_KANA_CONV rkc, int depth) +{ + ROMAN_KANA_NODE rkn; + + ZeroMemory(&rkn, sizeof(rkn)); + + if((_countof(rkc.roman) <= depth) || (rkc.roman[depth] == L'\0')) + { + return; + } + + rkn.ch = rkc.roman[depth]; + + auto v_itr = std::lower_bound(tree.nodes.begin(), tree.nodes.end(), + rkn.ch, [] (ROMAN_KANA_NODE m, WCHAR v) { return (m.ch < v); }); + + if(rkc.roman[depth + 1] == L'\0') + { + //ローマ字探索最後のノードにローマ字仮名変換ありの子ノードを追加 + rkn.conv = rkc; + tree.nodes.insert(v_itr, rkn); + } + else + { + //ローマ字探索途中のノードに探索対象のローマ字のみの子ノードを追加 + v_itr = tree.nodes.insert(v_itr, rkn); + //子ノードを探索 + _AddKanaTreeItem(*v_itr, rkc, depth + 1); + } +} + void CTextService::_LoadJLatin() { APPDATAXMLLIST list; @@ -683,8 +779,10 @@ void CTextService::_LoadJLatin() size_t blen = 0; std::wregex re(L"[\\x00-\\x19]"); std::wstring fmt(L""); + ASCII_JLATIN_CONV ajc; - ZeroMemory(ascii_jlatin_conv, sizeof(ascii_jlatin_conv)); + ascii_jlatin_conv.clear(); + ascii_jlatin_conv.shrink_to_fit(); if(ReadList(pathconfigxml, SectionJLatin, list) == S_OK && list.size() != 0) { @@ -695,19 +793,21 @@ void CTextService::_LoadJLatin() break; } + ZeroMemory(&ajc, sizeof(ajc)); + FORWARD_ITERATION_I(r_itr, *l_itr) { pszb = NULL; if(r_itr->first == AttributeLatin) { - pszb = ascii_jlatin_conv[i].ascii; - blen = _countof(ascii_jlatin_conv[i].ascii); + pszb = ajc.ascii; + blen = _countof(ajc.ascii); } else if(r_itr->first == AttributeJLatin) { - pszb = ascii_jlatin_conv[i].jlatin; - blen = _countof(ascii_jlatin_conv[i].jlatin); + pszb = ajc.jlatin; + blen = _countof(ajc.jlatin); } if(pszb != NULL) @@ -716,6 +816,14 @@ void CTextService::_LoadJLatin() } } + auto v_itr = std::lower_bound(ascii_jlatin_conv.begin(), ascii_jlatin_conv.end(), + ajc.ascii[0], [] (ASCII_JLATIN_CONV m, WCHAR v) { return (m.ascii[0] < v); }); + + if(v_itr == ascii_jlatin_conv.end() || ajc.ascii[0] != v_itr->ascii[0]) + { + ascii_jlatin_conv.insert(v_itr, ajc); + } + i++; } } diff --git a/imcrvtip/KeyHandler.cpp b/imcrvtip/KeyHandler.cpp index 3cd61db3..7e1662d3 100644 --- a/imcrvtip/KeyHandler.cpp +++ b/imcrvtip/KeyHandler.cpp @@ -57,7 +57,6 @@ HRESULT CTextService::_InvokeKeyHandler(ITfContext *pContext, WPARAM wParam, LPA HRESULT CTextService::_HandleKey(TfEditCookie ec, ITfContext *pContext, WPARAM wParam, BYTE bSf) { - size_t i; BYTE sf; WCHAR ch, chO = L'\0'; HRESULT hrc = E_ABORT; @@ -175,7 +174,7 @@ HRESULT CTextService::_HandleKey(TfEditCookie ec, ITfContext *pContext, WPARAM w return S_OK; } //"n;" -> "ん▽" - if(_ConvN(WCHAR_MAX)) + if(_ConvShift(WCHAR_MAX)) { ch = L'\0'; } @@ -213,31 +212,29 @@ HRESULT CTextService::_HandleKey(TfEditCookie ec, ITfContext *pContext, WPARAM w break; } - for(i = 0; i < CONV_POINT_NUM; i++) + auto vs_itr = std::lower_bound(conv_point_s.begin(), conv_point_s.end(), + ch, [] (CONV_POINT m, WCHAR v) { return (m.ch[0] < v); }); + + if(vs_itr != conv_point_s.end() && ch == vs_itr->ch[0]) { - if(conv_point[i][0] == L'\0' && - conv_point[i][1] == L'\0' && - conv_point[i][2] == L'\0') - { - break; - } - if(ch == conv_point[i][0]) + ch = vs_itr->ch[1]; + if(!inputkey || !kana.empty()) { - ch = conv_point[i][1]; - if(!inputkey || !kana.empty()) + chO = vs_itr->ch[2]; + if(_HandleControl(ec, pContext, SKK_CONV_POINT, ch) == S_OK) { - chO = conv_point[i][2]; - if(_HandleControl(ec, pContext, SKK_CONV_POINT, ch) == S_OK) - { - return S_OK; - } + return S_OK; } - break; } - else if(ch == conv_point[i][1]) + } + else + { + auto va_itr = std::lower_bound(conv_point_a.begin(), conv_point_a.end(), + ch, [] (CONV_POINT m, WCHAR v) { return (m.ch[1] < v); }); + + if(va_itr != conv_point_a.end() && ch == va_itr->ch[1]) { - chO = conv_point[i][2]; - break; + chO = va_itr->ch[2]; } } } @@ -250,11 +247,18 @@ HRESULT CTextService::_HandleKey(TfEditCookie ec, ITfContext *pContext, WPARAM w if(ch >= L'\x20') { std::wstring romanN = roman; + WCHAR chON = chO; //2文字目以降のローマ字で変換位置指定 if(!roman.empty() && chO != L'\0') { - chO = roman[0]; + auto va_itr = std::lower_bound(conv_point_a.begin(), conv_point_a.end(), + roman[0], [] (CONV_POINT m, WCHAR v) { return (m.ch[1] < v); }); + + if(va_itr != conv_point_a.end() && roman[0] == va_itr->ch[1]) + { + chO = va_itr->ch[2]; + } } //文字処理 @@ -269,7 +273,7 @@ HRESULT CTextService::_HandleKey(TfEditCookie ec, ITfContext *pContext, WPARAM w { //「ん」または待機中の文字を送り出し roman = romanN; - if(_ConvN(WCHAR_MAX)) + if(_ConvShift(WCHAR_MAX)) { if(!inputkey) { @@ -285,6 +289,7 @@ HRESULT CTextService::_HandleKey(TfEditCookie ec, ITfContext *pContext, WPARAM w roman.clear(); } //最後の入力で再処理 + chO = chON; if(_HandleChar(ec, pContext, wParam, ch, chO) == E_ABORT) { if(!inputkey) diff --git a/imcrvtip/KeyHandlerChar.cpp b/imcrvtip/KeyHandlerChar.cpp index 429a02ac..8b80f4ed 100644 --- a/imcrvtip/KeyHandlerChar.cpp +++ b/imcrvtip/KeyHandlerChar.cpp @@ -42,7 +42,8 @@ HRESULT CTextService::_HandleChar(TfEditCookie ec, ITfContext *pContext, WPARAM switch(ret) { case S_OK: //一致 - if(rkc.wait) //待機 + case E_PENDING: //途中まで一致 + if(rkc.roman[0] != L'\0' && rkc.wait) //待機 { ch = L'\0'; switch(inputmode) @@ -74,10 +75,13 @@ HRESULT CTextService::_HandleChar(TfEditCookie ec, ITfContext *pContext, WPARAM wcsncpy_s(rkc.roman, roman_conv.c_str(), _TRUNCATE); ret = _ConvRomanKana(&rkc); - if(wParam == VK_PACKET && ret == E_ABORT && ch != TKB_NEXT_PAGE && ch != TKB_PREV_PAGE) + //Windows8以降のタッチキーボード + if(ret == E_ABORT && wParam == VK_PACKET && + (ch != TKB_NEXT_PAGE && ch != TKB_PREV_PAGE) && + (ch != L'次' && ch != L'前' && ch != L'頁')) { - rkc.hiragana[0] = rkc.katakana[0] = rkc.katakana_ank[0] = ch; - rkc.hiragana[1] = rkc.katakana[1] = rkc.katakana_ank[1] = L'\0'; + rkc.roman[0] = rkc.hiragana[0] = rkc.katakana[0] = rkc.katakana_ank[0] = ch; + rkc.roman[1] = rkc.hiragana[1] = rkc.katakana[1] = rkc.katakana_ank[1] = L'\0'; rkc.soku = FALSE; rkc.wait = FALSE; ret = S_OK; @@ -86,8 +90,10 @@ HRESULT CTextService::_HandleChar(TfEditCookie ec, ITfContext *pContext, WPARAM switch(ret) { case S_OK: //一致 - if(rkc.wait) //待機 + if(rkc.roman[0] != L'\0' && rkc.wait) //待機 { + _HandleCharShift(ec, pContext); + switch(inputmode) { case im_hiragana: @@ -103,7 +109,6 @@ HRESULT CTextService::_HandleChar(TfEditCookie ec, ITfContext *pContext, WPARAM break; } - _HandleCharShift(ec, pContext); _Update(ec, pContext); } else @@ -169,9 +174,33 @@ HRESULT CTextService::_HandleChar(TfEditCookie ec, ITfContext *pContext, WPARAM break; case E_PENDING: //途中まで一致 - _HandleCharShift(ec, pContext); - roman.push_back(ch); - _Update(ec, pContext); + if(rkc.roman[0] != L'\0' && rkc.wait) //待機 + { + _HandleCharShift(ec, pContext); + + switch(inputmode) + { + case im_hiragana: + roman.assign(rkc.hiragana); + break; + case im_katakana: + roman.assign(rkc.katakana); + break; + case im_katakana_ank: + roman.assign(rkc.katakana_ank); + break; + default: + break; + } + + _Update(ec, pContext); + } + else + { + _HandleCharShift(ec, pContext); + roman.push_back(ch); + _Update(ec, pContext); + } break; case E_ABORT: //不一致 diff --git a/imcrvtip/KeyHandlerControl.cpp b/imcrvtip/KeyHandlerControl.cpp index c7295914..1074e840 100644 --- a/imcrvtip/KeyHandlerControl.cpp +++ b/imcrvtip/KeyHandlerControl.cpp @@ -390,7 +390,7 @@ HRESULT CTextService::_HandleControl(TfEditCookie ec, ITfContext *pContext, BYTE } if(!inputkey) { - if(_ConvN(ch)) + if(_ConvShift(ch)) { if(!kana.empty()) { @@ -403,7 +403,7 @@ HRESULT CTextService::_HandleControl(TfEditCookie ec, ITfContext *pContext, BYTE } else { - if(_ConvN(ch) && (okuriidx == 0) && (cursoridx != 0)) + if(_ConvShift(ch) && (okuriidx == 0) && (cursoridx != 0)) { //送り仮名入力開始 kana.insert(cursoridx, 1, CHAR_SKK_OKURI); //送りローマ字 diff --git a/imcrvtip/KeyHandlerConv.cpp b/imcrvtip/KeyHandlerConv.cpp index 6f2ce88e..7b5d6168 100644 --- a/imcrvtip/KeyHandlerConv.cpp +++ b/imcrvtip/KeyHandlerConv.cpp @@ -152,58 +152,74 @@ BYTE CTextService::_GetSf(BYTE vk, WCHAR ch) HRESULT CTextService::_ConvRomanKana(ROMAN_KANA_CONV *pconv) { - size_t i, count; - HRESULT ret = E_ABORT; //一致する可能性なし + HRESULT ret = _SearchRomanKanaNode(roman_kana_tree, pconv, 0); - count = roman_kana_conv.size(); + return ret; +} - for(i = 0; i < count; i++) +HRESULT CTextService::_SearchRomanKanaNode(const ROMAN_KANA_NODE &tree, ROMAN_KANA_CONV *pconv, int depth) +{ + HRESULT ret = E_ABORT; //一致なし + + if((pconv == NULL) || + (_countof(pconv->roman) <= depth) || (pconv->roman[depth] == L'\0')) { - if(roman_kana_conv[i].roman[0] == L'\0') - { - continue; - } - if(wcsncmp(roman_kana_conv[i].roman, pconv->roman, wcslen(pconv->roman)) == 0) + return ret; + } + + auto v_itr = std::lower_bound(tree.nodes.begin(), tree.nodes.end(), + pconv->roman[depth], [] (ROMAN_KANA_NODE m, WCHAR v) { return (m.ch < v); }); + + if(v_itr != tree.nodes.end() && v_itr->ch == pconv->roman[depth]) + { + if(pconv->roman[depth + 1] == L'\0') { - if(wcsncmp(roman_kana_conv[i].roman, pconv->roman, ROMAN_NUM) == 0) + *pconv = v_itr->conv; + if(v_itr->nodes.empty()) { - *pconv = roman_kana_conv[i]; - ret = S_OK; //一致 - break; + ret = S_OK; //一致 葉ノード } - ret = E_PENDING; //途中まで一致 + else + { + ret = E_PENDING; //途中まで一致 内部ノード + } + } + else + { + //子ノードを探索 + ret = _SearchRomanKanaNode(*v_itr, pconv, depth + 1); } } + if(ret == E_ABORT) + { + ZeroMemory(pconv, sizeof(*pconv)); + } + return ret; } HRESULT CTextService::_ConvAsciiJLatin(ASCII_JLATIN_CONV *pconv) { - size_t i; - HRESULT ret = E_ABORT; //一致する可能性なし + HRESULT ret = E_ABORT; //一致なし - for(i = 0; i < ASCII_JLATIN_TBL_NUM; i++) + if(pconv == NULL) { - if(ascii_jlatin_conv[i].ascii[0] == L'\0' && - ascii_jlatin_conv[i].jlatin[0] == L'\0') - { - break; - } - if(ascii_jlatin_conv[i].ascii[0] == L'\0') - { - continue; - } - if(wcsncmp(ascii_jlatin_conv[i].ascii, pconv->ascii, wcslen(pconv->ascii)) == 0) - { - if(wcsncmp(ascii_jlatin_conv[i].ascii, pconv->ascii, JLATIN_NUM) == 0) - { - *pconv = ascii_jlatin_conv[i]; - ret = S_OK; //一致 - break; - } - ret = E_PENDING; //途中まで一致 - } + return ret; + } + + auto v_itr = std::lower_bound(ascii_jlatin_conv.begin(), ascii_jlatin_conv.end(), + pconv->ascii[0], [] (ASCII_JLATIN_CONV m, WCHAR v) { return (m.ascii[0] < v); }); + + if(v_itr != ascii_jlatin_conv.end() && v_itr->ascii[0] == pconv->ascii[0]) + { + *pconv = *v_itr; + ret = S_OK; //一致 + } + + if(ret == E_ABORT) + { + ZeroMemory(pconv, sizeof(*pconv)); } return ret; @@ -509,7 +525,7 @@ void CTextService::_SetComp(const std::wstring &candidate) void CTextService::_ConvRoman() { - if(!_ConvN(WCHAR_MAX)) + if(!_ConvShift(WCHAR_MAX)) { roman.clear(); } @@ -522,24 +538,23 @@ void CTextService::_ConvRoman() } } -BOOL CTextService::_ConvN(WCHAR ch) +BOOL CTextService::_ConvShift(WCHAR ch) { ROMAN_KANA_CONV rkc; HRESULT ret; - size_t i; if(roman.empty()) { return TRUE; } - //「ん etc.」 wcsncpy_s(rkc.roman, roman.c_str(), _TRUNCATE); ret = _ConvRomanKana(&rkc); switch(ret) { case S_OK: //一致 - if(rkc.wait) //待機 + case E_PENDING: //途中まで一致 + if(rkc.roman != L'\0' && rkc.wait) //待機 { if(okuriidx != 0 && okuriidx + 1 == cursoridx) { @@ -560,19 +575,13 @@ BOOL CTextService::_ConvN(WCHAR ch) } WCHAR chO = L'\0'; - for(i = 0; i < CONV_POINT_NUM; i++) + + auto va_itr = std::lower_bound(conv_point_a.begin(), conv_point_a.end(), + chN, [] (CONV_POINT m, WCHAR v) { return (m.ch[1] < v); }); + + if(va_itr != conv_point_a.end() && chN == va_itr->ch[1]) { - if(conv_point[i][0] == L'\0' && - conv_point[i][1] == L'\0' && - conv_point[i][2] == L'\0') - { - break; - } - if(chN == conv_point[i][1]) - { - chO = conv_point[i][2]; - break; - } + chO = va_itr->ch[2]; } if(chO == L'\0') @@ -619,7 +628,7 @@ BOOL CTextService::_ConvN(WCHAR ch) break; } - // ( <"n*", ""> -> <"", "ん"> ) SKK_CONV_POINTのみ + // SKK_CONV_POINTのみ if(ch != L'\0' && ch != WCHAR_MAX) { std::wstring roman_conv = roman; @@ -629,7 +638,8 @@ BOOL CTextService::_ConvN(WCHAR ch) switch(ret) { case S_OK: //一致 - if(rkc.soku) //「n* soku==1」 + case E_PENDING: //途中まで一致 + if(rkc.roman != L'\0' && rkc.soku) { std::wstring kana_ins; switch(inputmode) @@ -658,30 +668,23 @@ BOOL CTextService::_ConvN(WCHAR ch) } roman.clear(); - return TRUE; //「nk」etc. + return TRUE; //「nk, ss」etc. } else { if(cx_shiftnnokuri || (!cx_shiftnnokuri && (!inputkey || (inputkey && okuriidx == 0)))) { - _ConvNN(); + _ConvN(); } - return TRUE; //「ka,na,nn」etc. - } - break; - case E_PENDING: //途中まで一致 - if(cx_shiftnnokuri || (!cx_shiftnnokuri && (!inputkey || (inputkey && okuriidx == 0)))) - { - _ConvNN(); + return TRUE; //「ka, na, nn」etc.「ky, ny」etc. } - return TRUE; //「ky,ny」etc. break; default: break; } } - if(_ConvNN()) + if(_ConvN()) { return TRUE; } @@ -689,60 +692,49 @@ BOOL CTextService::_ConvN(WCHAR ch) return FALSE; } -BOOL CTextService::_ConvNN() +BOOL CTextService::_ConvN() { ROMAN_KANA_CONV rkc; HRESULT ret; - // ( <"nn", ""> -> <"", "ん"> ) - if(roman.size() == 1) + wcsncpy_s(rkc.roman, roman.c_str(), _TRUNCATE); + ret = _ConvRomanKana(&rkc); + switch(ret) { - WCHAR chN = roman[0]; - rkc.roman[0] = chN; - rkc.roman[1] = chN; - rkc.roman[2] = L'\0'; - ret = _ConvRomanKana(&rkc); - switch(ret) + case S_OK: //一致 + case E_PENDING: //途中まで一致 + if(rkc.roman[0] != L'\0') { - case S_OK: //一致 - if(!rkc.soku && - wcscmp(rkc.hiragana, L"ん") == 0 && - wcscmp(rkc.katakana, L"ン") == 0 && - wcscmp(rkc.katakana_ank, L"ン") == 0) //「nn soku==0」 + std::wstring kana_ins; + switch(inputmode) { - std::wstring kana_ins; - switch(inputmode) - { - case im_hiragana: - kana_ins = rkc.hiragana; - break; - case im_katakana: - kana_ins = rkc.katakana; - break; - case im_katakana_ank: - kana_ins = rkc.katakana_ank; - break; - default: - break; - } + case im_hiragana: + kana_ins = rkc.hiragana; + break; + case im_katakana: + kana_ins = rkc.katakana; + break; + case im_katakana_ank: + kana_ins = rkc.katakana_ank; + break; + default: + break; + } - if(!kana_ins.empty()) + if(!kana_ins.empty()) + { + kana.insert(cursoridx, kana_ins); + if(okuriidx != 0 && cursoridx <= okuriidx) { - kana.insert(cursoridx, kana_ins); - if(okuriidx != 0 && cursoridx <= okuriidx) - { - okuriidx += kana_ins.size(); - } - cursoridx += kana_ins.size(); + okuriidx += kana_ins.size(); } - - roman.clear(); - return TRUE; //「nn」 + cursoridx += kana_ins.size(); } - break; - default: - break; + + roman.clear(); + return TRUE; } + break; } return FALSE; @@ -750,7 +742,7 @@ BOOL CTextService::_ConvNN() void CTextService::_ConvKanaToKana(std::wstring &dst, int dstmode, const std::wstring &src, int srcmode) { - size_t i, j, count; + size_t i; BOOL exist; WCHAR *convkana = NULL; WCHAR srckana[3]; @@ -776,10 +768,9 @@ void CTextService::_ConvKanaToKana(std::wstring &dst, int dstmode, const std::ws break; } - count = roman_kana_conv.size(); - for(i = 0; i < src.size(); i++) { + // surrogate pair, 「う゛」 if(((i + 1) < src.size()) && (IS_SURROGATE_PAIR(src[i], src[i + 1]) || (src[i] == L'う' && src[i + 1] == L'゛'))) { @@ -793,53 +784,73 @@ void CTextService::_ConvKanaToKana(std::wstring &dst, int dstmode, const std::ws srckana[0] = src[i]; srckana[1] = L'\0'; } - exist = FALSE; - for(j = 0; j < count; j++) + exist = _SearchKanaByKana(roman_kana_tree, srcmode, srckana, dstmode, dsttmp); + + if(!exist) //ローマ字仮名変換表に無ければそのまま { - if(roman_kana_conv[j].roman[0] == L'\0') + dsttmp.append(srckana); + } + } + + dst.assign(dsttmp); +} + +BOOL CTextService::_SearchKanaByKana(const ROMAN_KANA_NODE &tree, int srcmode, const WCHAR *src, int dstmode, std::wstring &dst) +{ + ROMAN_KANA_CONV rkc; + BOOL exist = FALSE; + + FORWARD_ITERATION_I(v_itr, tree.nodes) + { + switch(srcmode) + { + case im_hiragana: + if(wcscmp(src, v_itr->conv.hiragana) == 0) { - break; + rkc = v_itr->conv; + exist = TRUE; + } + break; + case im_katakana: + if(wcscmp(src, v_itr->conv.katakana) == 0) + { + rkc = v_itr->conv; + exist = TRUE; } + break; + default: + break; + } - switch(srcmode) + if(exist) + { + switch(dstmode) { case im_hiragana: - convkana = roman_kana_conv[j].hiragana; + dst.append(rkc.hiragana); break; case im_katakana: - convkana = roman_kana_conv[j].katakana; + dst.append(rkc.katakana); + break; + case im_katakana_ank: + dst.append(rkc.katakana_ank); break; default: break; } + break; + } + else if(!v_itr->nodes.empty()) + { + exist = _SearchKanaByKana(*v_itr, srcmode, src, dstmode, dst); - if(wcsncmp(convkana, srckana, KANA_NUM) == 0) + if(exist) { - exist = TRUE; - switch(dstmode) - { - case im_hiragana: - dsttmp.append(roman_kana_conv[j].hiragana); - break; - case im_katakana: - dsttmp.append(roman_kana_conv[j].katakana); - break; - case im_katakana_ank: - dsttmp.append(roman_kana_conv[j].katakana_ank); - break; - default: - break; - } break; } } - - if(!exist) //ローマ字仮名変換表に無ければそのまま - { - dsttmp.append(srckana); - } } - dst.assign(dsttmp); + return exist; } diff --git a/imcrvtip/TextService.h b/imcrvtip/TextService.h index 2c970a6e..71221825 100644 --- a/imcrvtip/TextService.h +++ b/imcrvtip/TextService.h @@ -162,6 +162,7 @@ class CTextService : WCHAR _GetCh(BYTE vk, BYTE vkoff = 0); BYTE _GetSf(BYTE vk, WCHAR ch); HRESULT _ConvRomanKana(ROMAN_KANA_CONV *pconv); + HRESULT _SearchRomanKanaNode(const ROMAN_KANA_NODE &tree, ROMAN_KANA_CONV *pconv, int depth); HRESULT _ConvAsciiJLatin(ASCII_JLATIN_CONV *pconv); void _StartConv(); void _StartSubConv(); @@ -171,9 +172,10 @@ class CTextService : void _PrevComp(); void _SetComp(const std::wstring &candidate); void _ConvRoman(); - BOOL _ConvN(WCHAR ch); - BOOL _ConvNN(); + BOOL _ConvShift(WCHAR ch); + BOOL _ConvN(); void _ConvKanaToKana(std::wstring &dst, int dstmode, const std::wstring &src, int srcmode); + BOOL _SearchKanaByKana(const ROMAN_KANA_NODE &tree, int srcmode, const WCHAR *src, int dstmode, std::wstring &dst); // KeyHandlerDictionary void _ConnectDic(); @@ -198,6 +200,8 @@ class CTextService : void _LoadVKeyMap(LPCWSTR section); void _LoadConvPoint(); void _LoadKana(); + BOOL _AddKanaTree(ROMAN_KANA_NODE &tree, ROMAN_KANA_CONV rkc, int depth); + void _AddKanaTreeItem(ROMAN_KANA_NODE &tree, ROMAN_KANA_CONV rkc, int depth); void _LoadJLatin(); private: @@ -277,12 +281,15 @@ class CTextService : VKEYMAP vkeymap_shift; //仮想キー(+Shift) VKEYMAP vkeymap_ctrl; //仮想キー(+Ctrl) - //変換位置指定(開始,代替,送り) - WCHAR conv_point[CONV_POINT_NUM][3]; + //変換位置指定(0:開始,1:代替,2:送り) + std::vector conv_point_s; //開始で昇順ソート + std::vector conv_point_a; //代替で昇順ソート - //変換テーブル - std::vector roman_kana_conv; - ASCII_JLATIN_CONV ascii_jlatin_conv[ASCII_JLATIN_TBL_NUM]; + //ローマ字仮名変換木 + ROMAN_KANA_NODE roman_kana_tree; + //ASCII全英変換テーブル + // メンバーasciiで昇順ソート + std::vector ascii_jlatin_conv; public: ID2D1Factory *_pD2DFactory; diff --git a/imcrvtip/imcrvtip.h b/imcrvtip/imcrvtip.h index 46569497..8f044763 100644 --- a/imcrvtip/imcrvtip.h +++ b/imcrvtip/imcrvtip.h @@ -3,6 +3,7 @@ #define IMCRVTIP_H #include "common.h" +#include "convtype.h" //入力モード enum InputMode @@ -61,8 +62,25 @@ typedef struct { //キー設定(仮想キー) BYTE keyvoid[VKEYMAPNUM]; //無効 } VKEYMAP; -#define CHAR_SKK_HINT L'\x20' -#define CHAR_SKK_OKURI L'\x20' +typedef struct { //変換位置指定(0:開始,1:代替,2:送り) + WCHAR ch[3]; +} CONV_POINT; + +//ローマ字仮名ノード +typedef struct _ROMAN_KANA_NODE { + //探索対象、ローマ字1文字分、ルートノードはL'\0' + WCHAR ch; + //ローマ字仮名変換 + // ルートノードの各メンバーは空文字列 + // 仮名があるとき、最短で探索したchとconv.romanは等しい + // 仮名がないとき、各メンバーは空文字列 + ROMAN_KANA_CONV conv; + //子ノード、メンバーchで昇順ソート + std::vector<_ROMAN_KANA_NODE> nodes; +} ROMAN_KANA_NODE; + +#define CHAR_SKK_HINT L'\x20' //絞り込みの区切り +#define CHAR_SKK_OKURI L'\x20' //送り仮名がまだ無い時点での送りローマ字 #define TKB_NEXT_PAGE L'\uF003' //next page key on touch-optimized keyboard #define TKB_PREV_PAGE L'\uF004' //previous page key on touch-optimized keyboard diff --git a/installer/README.TXT b/installer/README.TXT index 4186e998..f9522acd 100644 --- a/installer/README.TXT +++ b/installer/README.TXT @@ -1,6 +1,6 @@  ================================================================================ - CorvusSKK version 1.7.11 + CorvusSKK version 1.7.12 https://code.google.com/p/corvus-skk/ nathancorvussolis@gmail.com @@ -573,5 +573,5 @@ ・開発環境 - Visual Studio Express 2013 for Windows Desktop Update 3 + Visual Studio Express 2013 for Windows Desktop Update 4 WiX Toolset v3.9 diff --git a/installer/config-sample/config - act.xml b/installer/config-sample/config - act.xml index 18a40326..a1cef83b 100644 --- a/installer/config-sample/config - act.xml +++ b/installer/config-sample/config - act.xml @@ -733,8 +733,6 @@ - - @@ -789,7 +787,7 @@ - + diff --git a/installer/config-sample/config - kana.xml b/installer/config-sample/config - kana.xml index 71fd51a3..724deb5d 100644 --- a/installer/config-sample/config - kana.xml +++ b/installer/config-sample/config - kana.xml @@ -548,25 +548,9 @@ + - - - - - - - - - - - - - - - - - @@ -586,8 +570,8 @@ - + diff --git a/installer/config-sample/config - roman.xml b/installer/config-sample/config - roman.xml index f11ab9d6..27c6a13f 100644 --- a/installer/config-sample/config - roman.xml +++ b/installer/config-sample/config - roman.xml @@ -388,25 +388,9 @@ + - - - - - - - - - - - - - - - - - @@ -426,8 +410,8 @@ - + diff --git a/installer/config-sample/kanatable.txt b/installer/config-sample/kanatable.txt index db90b965..7e388bad 100644 --- a/installer/config-sample/kanatable.txt +++ b/installer/config-sample/kanatable.txt @@ -218,25 +218,9 @@ hwyi ふぃ フィ フィ 0 hwyu ふゅ フュ フュ 0 hwye ふぇ フェ フェ 0 hwyo ふょ フョ フョ 0 +n ん ン ン 0 nn ん ン ン 0 n' ん ン ン 0 -nb ん ン ン 1 -nc ん ン ン 1 -nd ん ン ン 1 -nf ん ン ン 1 -ng ん ン ン 1 -nh ん ン ン 1 -nj ん ン ン 1 -nk ん ン ン 1 -nm ん ン ン 1 -np ん ン ン 1 -nr ん ン ン 1 -ns ん ン ン 1 -nt ん ン ン 1 -nv ん ン ン 1 -nw ん ン ン 1 -nx ん ン ン 1 -nz ん ン ン 1 mb ん ン ン 1 mm ん ン ン 1 mp ん ン ン 1 @@ -256,8 +240,8 @@ ss っ ッ ッ 1 tt っ ッ ッ 1 vv っ ッ ッ 1 ww っ ッ ッ 1 -yy っ ッ ッ 1 xx っ ッ ッ 1 +yy っ ッ ッ 1 zz っ ッ ッ 1 xa ぁ ァ ァ 0 xi ぃ ィ ィ 0 diff --git a/installer/corvusskk-x64.wxs b/installer/corvusskk-x64.wxs index 0da289cf..9975d2dd 100644 --- a/installer/corvusskk-x64.wxs +++ b/installer/corvusskk-x64.wxs @@ -1,7 +1,7 @@ - + diff --git a/installer/corvusskk-x86.wxs b/installer/corvusskk-x86.wxs index 0cff936b..ade52e20 100644 --- a/installer/corvusskk-x86.wxs +++ b/installer/corvusskk-x86.wxs @@ -1,7 +1,7 @@ - +