diff --git a/README.md b/README.md index 6b45b757..97c60fad 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ 要注意的是 macOS 可能会限制同一次 login session 能终结同一个输入法的执行进程的次数(安装程式透过 kill input method process 来让新版的输入法生效)。如果安装若干次后,发现程式修改的结果并没有出现、或甚至输入法已无法再选用,只需要登出目前的 macOS 系统帐号、再重新登入即可。 -补记: 该输入法是在 2021 年 11 月初「28ae7deb4092f067539cff600397292e66a5dd56」这一版小麦注音建置的基础上完成的。因为在清洗词库的时候清洗了全部的 git commit 历史,所以无法自动从小麦注音官方仓库上游继承任何改动,只能手动同步任何在此之后的程式修正。最近一次同步參照是小麦注音 2.0.1 版。 +补记: 该输入法是在 2021 年 11 月初「28ae7deb4092f067539cff600397292e66a5dd56」这一版小麦注音建置的基础上完成的。因为在清洗词库的时候清洗了全部的 git commit 历史,所以无法自动从小麦注音官方仓库上游继承任何改动,只能手动同步任何在此之后的程式修正。最近一次同步參照是 zonble 的分支「5cb6819e132a02bbcba77dbf083ada418750dab7」。 ## 应用授权 diff --git a/Source/3rdParty/OVMandarin/Mandarin.cpp b/Source/3rdParty/OVMandarin/Mandarin.cpp index 9776bb65..813012a2 100644 --- a/Source/3rdParty/OVMandarin/Mandarin.cpp +++ b/Source/3rdParty/OVMandarin/Mandarin.cpp @@ -26,1226 +26,1281 @@ namespace Taiyan { namespace Mandarin { class PinyinParseHelper { - public: - static const bool ConsumePrefix(std::string& target, - const std::string& prefix) { - if (target.length() < prefix.length()) { - return false; +public: + static const bool ConsumePrefix(std::string& target, + const std::string& prefix) { + if (target.length() < prefix.length()) { + return false; + } + + if (target.substr(0, prefix.length()) == prefix) { + target = + target.substr(prefix.length(), target.length() - prefix.length()); + return true; + } + + return false; } - - if (target.substr(0, prefix.length()) == prefix) { - target = - target.substr(prefix.length(), target.length() - prefix.length()); - return true; - } - - return false; - } }; class BopomofoCharacterMap { - public: - static const BopomofoCharacterMap& SharedInstance(); - - std::map componentToCharacter; - std::map characterToComponent; - - protected: - BopomofoCharacterMap(); +public: + static const BopomofoCharacterMap& SharedInstance(); + + std::map componentToCharacter; + std::map characterToComponent; + +protected: + BopomofoCharacterMap(); }; const BPMF BPMF::FromHanyuPinyin(const std::string& str) { - if (!str.length()) { - return BPMF(); - } - - std::string pinyin = str; - transform(pinyin.begin(), pinyin.end(), pinyin.begin(), ::tolower); - - BPMF::Component firstComponent = 0; - BPMF::Component secondComponent = 0; - BPMF::Component thirdComponent = 0; - BPMF::Component toneComponent = 0; - - // lookup consonants and consume them - bool independentConsonant = false; - - // the y exceptions fist - if (0) { - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "yuan")) { - secondComponent = BPMF::UE; - thirdComponent = BPMF::AN; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "ying")) { - secondComponent = BPMF::I; - thirdComponent = BPMF::ENG; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "yung")) { - secondComponent = BPMF::UE; - thirdComponent = BPMF::ENG; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "yong")) { - secondComponent = BPMF::UE; - thirdComponent = BPMF::ENG; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "yue")) { - secondComponent = BPMF::UE; - thirdComponent = BPMF::E; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "yun")) { - secondComponent = BPMF::UE; - thirdComponent = BPMF::EN; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "you")) { - secondComponent = BPMF::I; - thirdComponent = BPMF::OU; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "yu")) { - secondComponent = BPMF::UE; - } - - // try the first character - char c = pinyin.length() ? pinyin[0] : 0; - switch (c) { - case 'b': - firstComponent = BPMF::B; - pinyin = pinyin.substr(1); - break; - case 'p': - firstComponent = BPMF::P; - pinyin = pinyin.substr(1); - break; - case 'm': - firstComponent = BPMF::M; - pinyin = pinyin.substr(1); - break; - case 'f': - firstComponent = BPMF::F; - pinyin = pinyin.substr(1); - break; - case 'd': - firstComponent = BPMF::D; - pinyin = pinyin.substr(1); - break; - case 't': - firstComponent = BPMF::T; - pinyin = pinyin.substr(1); - break; - case 'n': - firstComponent = BPMF::N; - pinyin = pinyin.substr(1); - break; - case 'l': - firstComponent = BPMF::L; - pinyin = pinyin.substr(1); - break; - case 'g': - firstComponent = BPMF::G; - pinyin = pinyin.substr(1); - break; - case 'k': - firstComponent = BPMF::K; - pinyin = pinyin.substr(1); - break; - case 'h': - firstComponent = BPMF::H; - pinyin = pinyin.substr(1); - break; - case 'j': - firstComponent = BPMF::J; - pinyin = pinyin.substr(1); - break; - case 'q': - firstComponent = BPMF::Q; - pinyin = pinyin.substr(1); - break; - case 'x': - firstComponent = BPMF::X; - pinyin = pinyin.substr(1); - break; - - // special hanlding for w and y - case 'w': - secondComponent = BPMF::U; - pinyin = pinyin.substr(1); - break; - case 'y': - if (!secondComponent && !thirdComponent) { + if (!str.length()) { + return BPMF(); + } + + std::string pinyin = str; + transform(pinyin.begin(), pinyin.end(), pinyin.begin(), ::tolower); + + BPMF::Component firstComponent = 0; + BPMF::Component secondComponent = 0; + BPMF::Component thirdComponent = 0; + BPMF::Component toneComponent = 0; + + // lookup consonants and consume them + bool independentConsonant = false; + + // the y exceptions fist + if (0) { + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "yuan")) { + secondComponent = BPMF::UE; + thirdComponent = BPMF::AN; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "ying")) { secondComponent = BPMF::I; - } - pinyin = pinyin.substr(1); - break; - } - - // then we try ZH, CH, SH, R, Z, C, S (in that order) - if (0) { - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "zh")) { - firstComponent = BPMF::ZH; - independentConsonant = true; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "ch")) { - firstComponent = BPMF::CH; - independentConsonant = true; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "sh")) { - firstComponent = BPMF::SH; - independentConsonant = true; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "r")) { - firstComponent = BPMF::R; - independentConsonant = true; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "z")) { - firstComponent = BPMF::Z; - independentConsonant = true; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "c")) { - firstComponent = BPMF::C; - independentConsonant = true; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "s")) { - firstComponent = BPMF::S; - independentConsonant = true; - } - - // consume exceptions first: (ien, in), (iou, iu), (uen, un), (veng, iong), - // (ven, vn), (uei, ui), ung but longer sequence takes precedence - if (0) { - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "veng")) { - secondComponent = BPMF::UE; - thirdComponent = BPMF::ENG; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "iong")) { - secondComponent = BPMF::UE; - thirdComponent = BPMF::ENG; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "ing")) { - secondComponent = BPMF::I; - thirdComponent = BPMF::ENG; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "ien")) { - secondComponent = BPMF::I; - thirdComponent = BPMF::EN; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "iou")) { - secondComponent = BPMF::I; - thirdComponent = BPMF::OU; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "uen")) { - secondComponent = BPMF::U; - thirdComponent = BPMF::EN; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "ven")) { - secondComponent = BPMF::UE; - thirdComponent = BPMF::EN; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "uei")) { - secondComponent = BPMF::U; - thirdComponent = BPMF::EI; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "ung")) { - // f exception - if (firstComponent == BPMF::F) { - thirdComponent = BPMF::ENG; - } else { - secondComponent = BPMF::U; - thirdComponent = BPMF::ENG; + thirdComponent = BPMF::ENG; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "yung")) { + secondComponent = BPMF::UE; + thirdComponent = BPMF::ENG; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "yong")) { + secondComponent = BPMF::UE; + thirdComponent = BPMF::ENG; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "yue")) { + secondComponent = BPMF::UE; + thirdComponent = BPMF::E; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "yun")) { + secondComponent = BPMF::UE; + thirdComponent = BPMF::EN; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "you")) { + secondComponent = BPMF::I; + thirdComponent = BPMF::OU; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "yu")) { + secondComponent = BPMF::UE; } - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "ong")) { - // f exception - if (firstComponent == BPMF::F) { - thirdComponent = BPMF::ENG; - } else { - secondComponent = BPMF::U; - thirdComponent = BPMF::ENG; + + // try the first character + char c = pinyin.length() ? pinyin[0] : 0; + switch (c) { + case 'b': + firstComponent = BPMF::B; + pinyin = pinyin.substr(1); + break; + case 'p': + firstComponent = BPMF::P; + pinyin = pinyin.substr(1); + break; + case 'm': + firstComponent = BPMF::M; + pinyin = pinyin.substr(1); + break; + case 'f': + firstComponent = BPMF::F; + pinyin = pinyin.substr(1); + break; + case 'd': + firstComponent = BPMF::D; + pinyin = pinyin.substr(1); + break; + case 't': + firstComponent = BPMF::T; + pinyin = pinyin.substr(1); + break; + case 'n': + firstComponent = BPMF::N; + pinyin = pinyin.substr(1); + break; + case 'l': + firstComponent = BPMF::L; + pinyin = pinyin.substr(1); + break; + case 'g': + firstComponent = BPMF::G; + pinyin = pinyin.substr(1); + break; + case 'k': + firstComponent = BPMF::K; + pinyin = pinyin.substr(1); + break; + case 'h': + firstComponent = BPMF::H; + pinyin = pinyin.substr(1); + break; + case 'j': + firstComponent = BPMF::J; + pinyin = pinyin.substr(1); + break; + case 'q': + firstComponent = BPMF::Q; + pinyin = pinyin.substr(1); + break; + case 'x': + firstComponent = BPMF::X; + pinyin = pinyin.substr(1); + break; + + // special hanlding for w and y + case 'w': + secondComponent = BPMF::U; + pinyin = pinyin.substr(1); + break; + case 'y': + if (!secondComponent && !thirdComponent) { + secondComponent = BPMF::I; + } + pinyin = pinyin.substr(1); + break; } - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "un")) { - if (firstComponent == BPMF::J || firstComponent == BPMF::Q || - firstComponent == BPMF::X) { - secondComponent = BPMF::UE; - } else { - secondComponent = BPMF::U; + + // then we try ZH, CH, SH, R, Z, C, S (in that order) + if (0) { + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "zh")) { + firstComponent = BPMF::ZH; + independentConsonant = true; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "ch")) { + firstComponent = BPMF::CH; + independentConsonant = true; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "sh")) { + firstComponent = BPMF::SH; + independentConsonant = true; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "r")) { + firstComponent = BPMF::R; + independentConsonant = true; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "z")) { + firstComponent = BPMF::Z; + independentConsonant = true; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "c")) { + firstComponent = BPMF::C; + independentConsonant = true; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "s")) { + firstComponent = BPMF::S; + independentConsonant = true; } - thirdComponent = BPMF::EN; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "iu")) { - secondComponent = BPMF::I; - thirdComponent = BPMF::OU; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "in")) { - secondComponent = BPMF::I; - thirdComponent = BPMF::EN; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "vn")) { - secondComponent = BPMF::UE; - thirdComponent = BPMF::EN; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "ui")) { - secondComponent = BPMF::U; - thirdComponent = BPMF::EI; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "ue")) { - secondComponent = BPMF::UE; - thirdComponent = BPMF::E; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, u8"ü")) { - secondComponent = BPMF::UE; - } - - // then consume the middle component... - if (0) { - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "i")) { - secondComponent = independentConsonant ? 0 : BPMF::I; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "u")) { - if (firstComponent == BPMF::J || firstComponent == BPMF::Q || - firstComponent == BPMF::X) { - secondComponent = BPMF::UE; - } else { - secondComponent = BPMF::U; + + // consume exceptions first: (ien, in), (iou, iu), (uen, un), (veng, iong), + // (ven, vn), (uei, ui), ung but longer sequence takes precedence + if (0) { + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "veng")) { + secondComponent = BPMF::UE; + thirdComponent = BPMF::ENG; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "iong")) { + secondComponent = BPMF::UE; + thirdComponent = BPMF::ENG; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "ing")) { + secondComponent = BPMF::I; + thirdComponent = BPMF::ENG; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "ien")) { + secondComponent = BPMF::I; + thirdComponent = BPMF::EN; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "iou")) { + secondComponent = BPMF::I; + thirdComponent = BPMF::OU; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "uen")) { + secondComponent = BPMF::U; + thirdComponent = BPMF::EN; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "ven")) { + secondComponent = BPMF::UE; + thirdComponent = BPMF::EN; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "uei")) { + secondComponent = BPMF::U; + thirdComponent = BPMF::EI; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "ung")) { + // f exception + if (firstComponent == BPMF::F) { + thirdComponent = BPMF::ENG; + } else { + secondComponent = BPMF::U; + thirdComponent = BPMF::ENG; + } + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "ong")) { + // f exception + if (firstComponent == BPMF::F) { + thirdComponent = BPMF::ENG; + } else { + secondComponent = BPMF::U; + thirdComponent = BPMF::ENG; + } + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "un")) { + if (firstComponent == BPMF::J || firstComponent == BPMF::Q || + firstComponent == BPMF::X) { + secondComponent = BPMF::UE; + } else { + secondComponent = BPMF::U; + } + thirdComponent = BPMF::EN; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "iu")) { + secondComponent = BPMF::I; + thirdComponent = BPMF::OU; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "in")) { + secondComponent = BPMF::I; + thirdComponent = BPMF::EN; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "vn")) { + secondComponent = BPMF::UE; + thirdComponent = BPMF::EN; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "ui")) { + secondComponent = BPMF::U; + thirdComponent = BPMF::EI; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "ue")) { + secondComponent = BPMF::UE; + thirdComponent = BPMF::E; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, u8"ü")) { + secondComponent = BPMF::UE; } - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "v")) { - secondComponent = BPMF::UE; - } - - // the vowels, longer sequence takes precedence - if (0) { - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "ang")) { - thirdComponent = BPMF::ANG; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "eng")) { - thirdComponent = BPMF::ENG; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "err")) { - thirdComponent = BPMF::ERR; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "ai")) { - thirdComponent = BPMF::AI; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "ei")) { - thirdComponent = BPMF::EI; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "ao")) { - thirdComponent = BPMF::AO; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "ou")) { - thirdComponent = BPMF::OU; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "an")) { - thirdComponent = BPMF::AN; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "en")) { - thirdComponent = BPMF::EN; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "er")) { - thirdComponent = BPMF::ERR; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "a")) { - thirdComponent = BPMF::A; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "o")) { - thirdComponent = BPMF::O; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "e")) { - if (secondComponent) { - thirdComponent = BPMF::E; - } else { - thirdComponent = BPMF::ER; + + // then consume the middle component... + if (0) { + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "i")) { + secondComponent = independentConsonant ? 0 : BPMF::I; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "u")) { + if (firstComponent == BPMF::J || firstComponent == BPMF::Q || + firstComponent == BPMF::X) { + secondComponent = BPMF::UE; + } else { + secondComponent = BPMF::U; + } + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "v")) { + secondComponent = BPMF::UE; } - } - - // at last! - if (0) { - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "1")) { - toneComponent = BPMF::Tone1; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "2")) { - toneComponent = BPMF::Tone2; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "3")) { - toneComponent = BPMF::Tone3; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "4")) { - toneComponent = BPMF::Tone4; - } else if (PinyinParseHelper::ConsumePrefix(pinyin, "5")) { - toneComponent = BPMF::Tone5; - } - - return BPMF(firstComponent | secondComponent | thirdComponent | - toneComponent); + + // the vowels, longer sequence takes precedence + if (0) { + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "ang")) { + thirdComponent = BPMF::ANG; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "eng")) { + thirdComponent = BPMF::ENG; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "err")) { + thirdComponent = BPMF::ERR; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "ai")) { + thirdComponent = BPMF::AI; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "ei")) { + thirdComponent = BPMF::EI; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "ao")) { + thirdComponent = BPMF::AO; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "ou")) { + thirdComponent = BPMF::OU; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "an")) { + thirdComponent = BPMF::AN; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "en")) { + thirdComponent = BPMF::EN; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "er")) { + thirdComponent = BPMF::ERR; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "a")) { + thirdComponent = BPMF::A; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "o")) { + thirdComponent = BPMF::O; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "e")) { + if (secondComponent) { + thirdComponent = BPMF::E; + } else { + thirdComponent = BPMF::ER; + } + } + + // at last! + if (0) { + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "1")) { + toneComponent = BPMF::Tone1; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "2")) { + toneComponent = BPMF::Tone2; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "3")) { + toneComponent = BPMF::Tone3; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "4")) { + toneComponent = BPMF::Tone4; + } else if (PinyinParseHelper::ConsumePrefix(pinyin, "5")) { + toneComponent = BPMF::Tone5; + } + + return BPMF(firstComponent | secondComponent | thirdComponent | + toneComponent); } const std::string BPMF::HanyuPinyinString(bool includesTone, bool useVForUUmlaut) const { - std::string consonant, middle, vowel, tone; - - Component cc = consonantComponent(), mvc = middleVowelComponent(), - vc = vowelComponent(); - bool hasNoMVCOrVC = !(mvc || vc); - - switch (cc) { - case B: - consonant = "b"; - break; - case P: - consonant = "p"; - break; - case M: - consonant = "m"; - break; - case F: - consonant = "f"; - break; - case D: - consonant = "d"; - break; - case T: - consonant = "t"; - break; - case N: - consonant = "n"; - break; - case L: - consonant = "l"; - break; - case G: - consonant = "g"; - break; - case K: - consonant = "k"; - break; - case H: - consonant = "h"; - break; - case J: - consonant = "j"; - if (hasNoMVCOrVC) middle = "i"; - break; - case Q: - consonant = "q"; - if (hasNoMVCOrVC) middle = "i"; - break; - case X: - consonant = "x"; - if (hasNoMVCOrVC) middle = "i"; - break; - case ZH: - consonant = "zh"; - if (hasNoMVCOrVC) middle = "i"; - break; - case CH: - consonant = "ch"; - if (hasNoMVCOrVC) middle = "i"; - break; - case SH: - consonant = "sh"; - if (hasNoMVCOrVC) middle = "i"; - break; - case R: - consonant = "r"; - if (hasNoMVCOrVC) middle = "i"; - break; - case Z: - consonant = "z"; - if (hasNoMVCOrVC) middle = "i"; - break; - case C: - consonant = "c"; - if (hasNoMVCOrVC) middle = "i"; - break; - case S: - consonant = "s"; - if (hasNoMVCOrVC) middle = "i"; - break; - } - - switch (mvc) { - case I: - if (!cc) { - consonant = "y"; - } - - middle = (!vc || cc) ? "i" : ""; - break; - case U: - if (!cc) { - consonant = "w"; - } - middle = (!vc || cc) ? "u" : ""; - break; - case UE: - if (!cc) { - consonant = "y"; - } - - if ((cc == N || cc == L) && vc != E) { - middle = useVForUUmlaut ? "v" : "ü"; - } else { - middle = "u"; - } - - break; - } - - switch (vc) { - case A: - vowel = "a"; - break; - case O: - vowel = "o"; - break; - case ER: - vowel = "e"; - break; - case E: - vowel = "e"; - break; - case AI: - vowel = "ai"; - break; - case EI: - vowel = "ei"; - break; - case AO: - vowel = "ao"; - break; - case OU: - vowel = "ou"; - break; - case AN: - vowel = "an"; - break; - case EN: - vowel = "en"; - break; - case ANG: - vowel = "ang"; - break; - case ENG: - vowel = "eng"; - break; - case ERR: - vowel = "er"; - break; - } - - // combination rules - - // ueng -> ong, but note "weng" - if ((mvc == U || mvc == UE) && vc == ENG) { - middle = ""; - vowel = (cc == J || cc == Q || cc == X) - ? "iong" - : ((!cc && mvc == U) ? "eng" : "ong"); - } - - // ien, uen, üen -> in, un, ün ; but note "wen", "yin" and "yun" - if (mvc && vc == EN) { - if (cc) { - vowel = "n"; - } else { - if (mvc == UE) { - vowel = "n"; // yun - } else if (mvc == U) { - vowel = "en"; // wen - } else { - vowel = "in"; // yin - } + std::string consonant, middle, vowel, tone; + + Component cc = consonantComponent(), mvc = middleVowelComponent(), + vc = vowelComponent(); + bool hasNoMVCOrVC = !(mvc || vc); + + switch (cc) { + case B: + consonant = "b"; + break; + case P: + consonant = "p"; + break; + case M: + consonant = "m"; + break; + case F: + consonant = "f"; + break; + case D: + consonant = "d"; + break; + case T: + consonant = "t"; + break; + case N: + consonant = "n"; + break; + case L: + consonant = "l"; + break; + case G: + consonant = "g"; + break; + case K: + consonant = "k"; + break; + case H: + consonant = "h"; + break; + case J: + consonant = "j"; + if (hasNoMVCOrVC) middle = "i"; + break; + case Q: + consonant = "q"; + if (hasNoMVCOrVC) middle = "i"; + break; + case X: + consonant = "x"; + if (hasNoMVCOrVC) middle = "i"; + break; + case ZH: + consonant = "zh"; + if (hasNoMVCOrVC) middle = "i"; + break; + case CH: + consonant = "ch"; + if (hasNoMVCOrVC) middle = "i"; + break; + case SH: + consonant = "sh"; + if (hasNoMVCOrVC) middle = "i"; + break; + case R: + consonant = "r"; + if (hasNoMVCOrVC) middle = "i"; + break; + case Z: + consonant = "z"; + if (hasNoMVCOrVC) middle = "i"; + break; + case C: + consonant = "c"; + if (hasNoMVCOrVC) middle = "i"; + break; + case S: + consonant = "s"; + if (hasNoMVCOrVC) middle = "i"; + break; } - } - - // iou -> iu - if (cc && mvc == I && vc == OU) { - middle = ""; - vowel = "iu"; - } - - // ieng -> ing - if (mvc == I && vc == ENG) { - middle = ""; - vowel = "ing"; - } - - // uei -> ui - if (cc && mvc == U && vc == EI) { - middle = ""; - vowel = "ui"; - } - - if (includesTone) { - switch (toneMarkerComponent()) { - case Tone2: - tone = "2"; - break; - case Tone3: - tone = "3"; - break; - case Tone4: - tone = "4"; - break; - case Tone5: - tone = "5"; - break; + + switch (mvc) { + case I: + if (!cc) { + consonant = "y"; + } + + middle = (!vc || cc) ? "i" : ""; + break; + case U: + if (!cc) { + consonant = "w"; + } + middle = (!vc || cc) ? "u" : ""; + break; + case UE: + if (!cc) { + consonant = "y"; + } + + if ((cc == N || cc == L) && vc != E) { + middle = useVForUUmlaut ? "v" : "ü"; + } else { + middle = "u"; + } + + break; } - } - - return consonant + middle + vowel + tone; + + switch (vc) { + case A: + vowel = "a"; + break; + case O: + vowel = "o"; + break; + case ER: + vowel = "e"; + break; + case E: + vowel = "e"; + break; + case AI: + vowel = "ai"; + break; + case EI: + vowel = "ei"; + break; + case AO: + vowel = "ao"; + break; + case OU: + vowel = "ou"; + break; + case AN: + vowel = "an"; + break; + case EN: + vowel = "en"; + break; + case ANG: + vowel = "ang"; + break; + case ENG: + vowel = "eng"; + break; + case ERR: + vowel = "er"; + break; + } + + // combination rules + + // ueng -> ong, but note "weng" + if ((mvc == U || mvc == UE) && vc == ENG) { + middle = ""; + vowel = (cc == J || cc == Q || cc == X) + ? "iong" + : ((!cc && mvc == U) ? "eng" : "ong"); + } + + // ien, uen, üen -> in, un, ün ; but note "wen", "yin" and "yun" + if (mvc && vc == EN) { + if (cc) { + vowel = "n"; + } else { + if (mvc == UE) { + vowel = "n"; // yun + } else if (mvc == U) { + vowel = "en"; // wen + } else { + vowel = "in"; // yin + } + } + } + + // iou -> iu + if (cc && mvc == I && vc == OU) { + middle = ""; + vowel = "iu"; + } + + // ieng -> ing + if (mvc == I && vc == ENG) { + middle = ""; + vowel = "ing"; + } + + // uei -> ui + if (cc && mvc == U && vc == EI) { + middle = ""; + vowel = "ui"; + } + + if (includesTone) { + switch (toneMarkerComponent()) { + case Tone2: + tone = "2"; + break; + case Tone3: + tone = "3"; + break; + case Tone4: + tone = "4"; + break; + case Tone5: + tone = "5"; + break; + } + } + + return consonant + middle + vowel + tone; } const std::string BPMF::PHTString(bool includesTone) const { - std::string consonant, middle, vowel, tone; - - Component cc = consonantComponent(), mvc = middleVowelComponent(), - vc = vowelComponent(); - bool hasNoMVCOrVC = !(mvc || vc); - - switch (cc) { - case B: - consonant = "p"; - break; - case P: - consonant = "ph"; - break; - case M: - consonant = "m"; - break; - case F: - consonant = "f"; - break; - case D: - consonant = "t"; - break; - case T: - consonant = "th"; - break; - case N: - consonant = "n"; - break; - case L: - consonant = "l"; - break; - case G: - consonant = "k"; - break; - case K: - consonant = "kh"; - break; - case H: - consonant = "h"; - break; - case J: - consonant = "ch"; - if (mvc != I) middle = "i"; - break; - case Q: - consonant = "chh"; - if (mvc != I) middle = "i"; - break; - case X: - consonant = "hs"; - if (mvc != I) middle = "i"; - break; - case ZH: - consonant = "ch"; - if (hasNoMVCOrVC) middle = "i"; - break; - case CH: - consonant = "chh"; - if (hasNoMVCOrVC) middle = "i"; - break; - case SH: - consonant = "sh"; - if (hasNoMVCOrVC) middle = "i"; - break; - case R: - consonant = "r"; - if (hasNoMVCOrVC) middle = "i"; - break; - case Z: - consonant = "ts"; - if (hasNoMVCOrVC) middle = "i"; - break; - case C: - consonant = "tsh"; - if (hasNoMVCOrVC) middle = "i"; - break; - case S: - consonant = "s"; - if (hasNoMVCOrVC) middle = "i"; - break; - } - - switch (mvc) { - case I: - middle = "i"; - break; - case U: - middle = "u"; - break; - case UE: - middle = "uu"; - break; - } - - switch (vc) { - case A: - vowel = "a"; - break; - case O: - vowel = "o"; - break; - case ER: - vowel = "e"; - break; - case E: - vowel = (!(cc || mvc)) ? "eh" : "e"; - break; - case AI: - vowel = "ai"; - break; - case EI: - vowel = "ei"; - break; - case AO: - vowel = "ao"; - break; - case OU: - vowel = "ou"; - break; - case AN: - vowel = "an"; - break; - case EN: - vowel = "en"; - break; - case ANG: - vowel = "ang"; - break; - case ENG: - vowel = "eng"; - break; - case ERR: - vowel = "err"; - break; - } - - // ieng -> ing - if (mvc == I && vc == ENG) { - middle = ""; - vowel = "ing"; - } - - // zh/ch + i without third component -> append h - if (cc == BPMF::ZH || cc == BPMF::CH) { - if (!mvc && !vc) { - vowel = "h"; + std::string consonant, middle, vowel, tone; + + Component cc = consonantComponent(), mvc = middleVowelComponent(), + vc = vowelComponent(); + bool hasNoMVCOrVC = !(mvc || vc); + + switch (cc) { + case B: + consonant = "p"; + break; + case P: + consonant = "ph"; + break; + case M: + consonant = "m"; + break; + case F: + consonant = "f"; + break; + case D: + consonant = "t"; + break; + case T: + consonant = "th"; + break; + case N: + consonant = "n"; + break; + case L: + consonant = "l"; + break; + case G: + consonant = "k"; + break; + case K: + consonant = "kh"; + break; + case H: + consonant = "h"; + break; + case J: + consonant = "ch"; + if (mvc != I) middle = "i"; + break; + case Q: + consonant = "chh"; + if (mvc != I) middle = "i"; + break; + case X: + consonant = "hs"; + if (mvc != I) middle = "i"; + break; + case ZH: + consonant = "ch"; + if (hasNoMVCOrVC) middle = "i"; + break; + case CH: + consonant = "chh"; + if (hasNoMVCOrVC) middle = "i"; + break; + case SH: + consonant = "sh"; + if (hasNoMVCOrVC) middle = "i"; + break; + case R: + consonant = "r"; + if (hasNoMVCOrVC) middle = "i"; + break; + case Z: + consonant = "ts"; + if (hasNoMVCOrVC) middle = "i"; + break; + case C: + consonant = "tsh"; + if (hasNoMVCOrVC) middle = "i"; + break; + case S: + consonant = "s"; + if (hasNoMVCOrVC) middle = "i"; + break; } - } - - if (includesTone) { - switch (toneMarkerComponent()) { - case Tone2: - tone = "2"; - break; - case Tone3: - tone = "3"; - break; - case Tone4: - tone = "4"; - break; - case Tone5: - tone = "5"; - break; + + switch (mvc) { + case I: + middle = "i"; + break; + case U: + middle = "u"; + break; + case UE: + middle = "uu"; + break; } - } - - return consonant + middle + vowel + tone; + + switch (vc) { + case A: + vowel = "a"; + break; + case O: + vowel = "o"; + break; + case ER: + vowel = "e"; + break; + case E: + vowel = (!(cc || mvc)) ? "eh" : "e"; + break; + case AI: + vowel = "ai"; + break; + case EI: + vowel = "ei"; + break; + case AO: + vowel = "ao"; + break; + case OU: + vowel = "ou"; + break; + case AN: + vowel = "an"; + break; + case EN: + vowel = "en"; + break; + case ANG: + vowel = "ang"; + break; + case ENG: + vowel = "eng"; + break; + case ERR: + vowel = "err"; + break; + } + + // ieng -> ing + if (mvc == I && vc == ENG) { + middle = ""; + vowel = "ing"; + } + + // zh/ch + i without third component -> append h + if (cc == BPMF::ZH || cc == BPMF::CH) { + if (!mvc && !vc) { + vowel = "h"; + } + } + + if (includesTone) { + switch (toneMarkerComponent()) { + case Tone2: + tone = "2"; + break; + case Tone3: + tone = "3"; + break; + case Tone4: + tone = "4"; + break; + case Tone5: + tone = "5"; + break; + } + } + + return consonant + middle + vowel + tone; } const BPMF BPMF::FromPHT(const std::string& str) { - if (!str.length()) { - return BPMF(); - } - - std::string pht = str; - transform(pht.begin(), pht.end(), pht.begin(), ::tolower); - - BPMF::Component firstComponent = 0; - BPMF::Component secondComponent = 0; - BPMF::Component thirdComponent = 0; - BPMF::Component toneComponent = 0; - -#define IF_CONSUME1(k, v) \ - else if (PinyinParseHelper::ConsumePrefix(pht, k)) { \ - firstComponent = v; \ - } - - // consume the first part - if (0) { - } - IF_CONSUME1("ph", BPMF::P) - IF_CONSUME1("p", BPMF::B) - IF_CONSUME1("m", BPMF::M) - IF_CONSUME1("f", BPMF::F) - IF_CONSUME1("th", BPMF::T) - IF_CONSUME1("n", BPMF::N) - IF_CONSUME1("l", BPMF::L) - IF_CONSUME1("kh", BPMF::K) - IF_CONSUME1("k", BPMF::G) - IF_CONSUME1("chh", BPMF::Q) - IF_CONSUME1("ch", BPMF::J) - IF_CONSUME1("hs", BPMF::X) - IF_CONSUME1("sh", BPMF::SH) - IF_CONSUME1("r", BPMF::R) - IF_CONSUME1("tsh", BPMF::C) - IF_CONSUME1("ts", BPMF::Z) - IF_CONSUME1("s", BPMF::S) - IF_CONSUME1("t", BPMF::D) - IF_CONSUME1("h", BPMF::H) - -#define IF_CONSUME2(k, v) \ - else if (PinyinParseHelper::ConsumePrefix(pht, k)) { \ - secondComponent = v; \ - } - // consume the second part - if (0) { - } else if (PinyinParseHelper::ConsumePrefix(pht, "ing")) { - secondComponent = BPMF::I; - thirdComponent = BPMF::ENG; - } else if (PinyinParseHelper::ConsumePrefix(pht, "ih")) { - if (firstComponent == BPMF::J) { - firstComponent = BPMF::ZH; - } else if (firstComponent == BPMF::Q) { - firstComponent = BPMF::CH; + if (!str.length()) { + return BPMF(); } - } - IF_CONSUME2("i", BPMF::I) - IF_CONSUME2("uu", BPMF::UE) - IF_CONSUME2("u", BPMF::U) - + + std::string pht = str; + transform(pht.begin(), pht.end(), pht.begin(), ::tolower); + + BPMF::Component firstComponent = 0; + BPMF::Component secondComponent = 0; + BPMF::Component thirdComponent = 0; + BPMF::Component toneComponent = 0; + +#define IF_CONSUME1(k, v) \ +else if (PinyinParseHelper::ConsumePrefix(pht, k)) { \ +firstComponent = v; \ +} + + // consume the first part + if (0) { + } + IF_CONSUME1("ph", BPMF::P) + IF_CONSUME1("p", BPMF::B) + IF_CONSUME1("m", BPMF::M) + IF_CONSUME1("f", BPMF::F) + IF_CONSUME1("th", BPMF::T) + IF_CONSUME1("n", BPMF::N) + IF_CONSUME1("l", BPMF::L) + IF_CONSUME1("kh", BPMF::K) + IF_CONSUME1("k", BPMF::G) + IF_CONSUME1("chh", BPMF::Q) + IF_CONSUME1("ch", BPMF::J) + IF_CONSUME1("hs", BPMF::X) + IF_CONSUME1("sh", BPMF::SH) + IF_CONSUME1("r", BPMF::R) + IF_CONSUME1("tsh", BPMF::C) + IF_CONSUME1("ts", BPMF::Z) + IF_CONSUME1("s", BPMF::S) + IF_CONSUME1("t", BPMF::D) + IF_CONSUME1("h", BPMF::H) + +#define IF_CONSUME2(k, v) \ +else if (PinyinParseHelper::ConsumePrefix(pht, k)) { \ +secondComponent = v; \ +} + // consume the second part + if (0) { + } else if (PinyinParseHelper::ConsumePrefix(pht, "ing")) { + secondComponent = BPMF::I; + thirdComponent = BPMF::ENG; + } else if (PinyinParseHelper::ConsumePrefix(pht, "ih")) { + if (firstComponent == BPMF::J) { + firstComponent = BPMF::ZH; + } else if (firstComponent == BPMF::Q) { + firstComponent = BPMF::CH; + } + } + IF_CONSUME2("i", BPMF::I) + IF_CONSUME2("uu", BPMF::UE) + IF_CONSUME2("u", BPMF::U) + #undef IF_CONSUME1 #undef IF_CONSUME2 - - // the vowels, longer sequence takes precedence - if (0) { - } else if (PinyinParseHelper::ConsumePrefix(pht, "ang")) { - thirdComponent = BPMF::ANG; - } else if (PinyinParseHelper::ConsumePrefix(pht, "eng")) { - thirdComponent = BPMF::ENG; - } else if (PinyinParseHelper::ConsumePrefix(pht, "err")) { - thirdComponent = BPMF::ERR; - } else if (PinyinParseHelper::ConsumePrefix(pht, "ai")) { - thirdComponent = BPMF::AI; - } else if (PinyinParseHelper::ConsumePrefix(pht, "ei")) { - thirdComponent = BPMF::EI; - } else if (PinyinParseHelper::ConsumePrefix(pht, "ao")) { - thirdComponent = BPMF::AO; - } else if (PinyinParseHelper::ConsumePrefix(pht, "ou")) { - thirdComponent = BPMF::OU; - } else if (PinyinParseHelper::ConsumePrefix(pht, "an")) { - thirdComponent = BPMF::AN; - } else if (PinyinParseHelper::ConsumePrefix(pht, "en")) { - thirdComponent = BPMF::EN; - } else if (PinyinParseHelper::ConsumePrefix(pht, "er")) { - thirdComponent = BPMF::ERR; - } else if (PinyinParseHelper::ConsumePrefix(pht, "a")) { - thirdComponent = BPMF::A; - } else if (PinyinParseHelper::ConsumePrefix(pht, "o")) { - thirdComponent = BPMF::O; - } else if (PinyinParseHelper::ConsumePrefix(pht, "eh")) { - thirdComponent = BPMF::E; - } else if (PinyinParseHelper::ConsumePrefix(pht, "e")) { - if (secondComponent) { - thirdComponent = BPMF::E; - } else { - thirdComponent = BPMF::ER; + + // the vowels, longer sequence takes precedence + if (0) { + } else if (PinyinParseHelper::ConsumePrefix(pht, "ang")) { + thirdComponent = BPMF::ANG; + } else if (PinyinParseHelper::ConsumePrefix(pht, "eng")) { + thirdComponent = BPMF::ENG; + } else if (PinyinParseHelper::ConsumePrefix(pht, "err")) { + thirdComponent = BPMF::ERR; + } else if (PinyinParseHelper::ConsumePrefix(pht, "ai")) { + thirdComponent = BPMF::AI; + } else if (PinyinParseHelper::ConsumePrefix(pht, "ei")) { + thirdComponent = BPMF::EI; + } else if (PinyinParseHelper::ConsumePrefix(pht, "ao")) { + thirdComponent = BPMF::AO; + } else if (PinyinParseHelper::ConsumePrefix(pht, "ou")) { + thirdComponent = BPMF::OU; + } else if (PinyinParseHelper::ConsumePrefix(pht, "an")) { + thirdComponent = BPMF::AN; + } else if (PinyinParseHelper::ConsumePrefix(pht, "en")) { + thirdComponent = BPMF::EN; + } else if (PinyinParseHelper::ConsumePrefix(pht, "er")) { + thirdComponent = BPMF::ERR; + } else if (PinyinParseHelper::ConsumePrefix(pht, "a")) { + thirdComponent = BPMF::A; + } else if (PinyinParseHelper::ConsumePrefix(pht, "o")) { + thirdComponent = BPMF::O; + } else if (PinyinParseHelper::ConsumePrefix(pht, "eh")) { + thirdComponent = BPMF::E; + } else if (PinyinParseHelper::ConsumePrefix(pht, "e")) { + if (secondComponent) { + thirdComponent = BPMF::E; + } else { + thirdComponent = BPMF::ER; + } } - } - - // fix ch/chh mappings - Component corresponding = 0; - if (firstComponent == BPMF::J) { - corresponding = BPMF::ZH; - } else if (firstComponent == BPMF::Q) { - corresponding = BPMF::CH; - } - - if (corresponding) { - if (secondComponent == BPMF::I && !thirdComponent) { - // if the second component is I and there's no third component, we use the - // corresponding part firstComponent = corresponding; - } else if (secondComponent == BPMF::U) { - // if second component is U, we use the corresponding part - firstComponent = corresponding; - } else if (!secondComponent) { - // if there's no second component, it must be a corresponding part - firstComponent = corresponding; + + // fix ch/chh mappings + Component corresponding = 0; + if (firstComponent == BPMF::J) { + corresponding = BPMF::ZH; + } else if (firstComponent == BPMF::Q) { + corresponding = BPMF::CH; } - } - - if (secondComponent == BPMF::I) { - // fixes a few impossible occurances - switch (firstComponent) { - case BPMF::ZH: - case BPMF::CH: - case BPMF::SH: - case BPMF::R: - case BPMF::Z: - case BPMF::C: - case BPMF::S: - secondComponent = 0; + + if (corresponding) { + if (secondComponent == BPMF::I && !thirdComponent) { + // if the second component is I and there's no third component, we use the + // corresponding part firstComponent = corresponding; + } else if (secondComponent == BPMF::U) { + // if second component is U, we use the corresponding part + firstComponent = corresponding; + } else if (!secondComponent) { + // if there's no second component, it must be a corresponding part + firstComponent = corresponding; + } } - } - - // at last! - if (0) { - } else if (PinyinParseHelper::ConsumePrefix(pht, "1")) { - toneComponent = BPMF::Tone1; - } else if (PinyinParseHelper::ConsumePrefix(pht, "2")) { - toneComponent = BPMF::Tone2; - } else if (PinyinParseHelper::ConsumePrefix(pht, "3")) { - toneComponent = BPMF::Tone3; - } else if (PinyinParseHelper::ConsumePrefix(pht, "4")) { - toneComponent = BPMF::Tone4; - } else if (PinyinParseHelper::ConsumePrefix(pht, "5")) { - toneComponent = BPMF::Tone5; - } - - return BPMF(firstComponent | secondComponent | thirdComponent | - toneComponent); + + if (secondComponent == BPMF::I) { + // fixes a few impossible occurances + switch (firstComponent) { + case BPMF::ZH: + case BPMF::CH: + case BPMF::SH: + case BPMF::R: + case BPMF::Z: + case BPMF::C: + case BPMF::S: + secondComponent = 0; + } + } + + // at last! + if (0) { + } else if (PinyinParseHelper::ConsumePrefix(pht, "1")) { + toneComponent = BPMF::Tone1; + } else if (PinyinParseHelper::ConsumePrefix(pht, "2")) { + toneComponent = BPMF::Tone2; + } else if (PinyinParseHelper::ConsumePrefix(pht, "3")) { + toneComponent = BPMF::Tone3; + } else if (PinyinParseHelper::ConsumePrefix(pht, "4")) { + toneComponent = BPMF::Tone4; + } else if (PinyinParseHelper::ConsumePrefix(pht, "5")) { + toneComponent = BPMF::Tone5; + } + + return BPMF(firstComponent | secondComponent | thirdComponent | + toneComponent); } const BPMF BPMF::FromComposedString(const std::string& str) { - BPMF syllable; - auto iter = str.begin(); - while (iter != str.end()) { - // This is a naive implementation and we bail early at anything we don't - // recognize. A sound implementation would require to either use a trie for - // the Bopomofo character map or to split the input by codepoints. This - // suffices for now. - - // Illegal. - if (!(*iter & 0x80)) { - break; - } - - size_t utf8_length = -1; - - // These are the code points for the tone markers. - if ((*iter & (0x80 | 0x40)) && !(*iter & 0x20)) { - utf8_length = 2; - } else if ((*iter & (0x80 | 0x40 | 0x20)) && !(*iter & 0x10)) { - utf8_length = 3; - } else { - // Illegal. - break; - } - - if (iter + (utf8_length - 1) == str.end()) { - break; - } - - std::string component = std::string(iter, iter + utf8_length); - const std::map& charToComp = + BPMF syllable; + auto iter = str.begin(); + while (iter != str.end()) { + // This is a naive implementation and we bail early at anything we don't + // recognize. A sound implementation would require to either use a trie for + // the Bopomofo character map or to split the input by codepoints. This + // suffices for now. + + // Illegal. + if (!(*iter & 0x80)) { + break; + } + + size_t utf8_length = -1; + + // These are the code points for the tone markers. + if ((*iter & (0x80 | 0x40)) && !(*iter & 0x20)) { + utf8_length = 2; + } else if ((*iter & (0x80 | 0x40 | 0x20)) && !(*iter & 0x10)) { + utf8_length = 3; + } else { + // Illegal. + break; + } + + if (iter + (utf8_length - 1) == str.end()) { + break; + } + + std::string component = std::string(iter, iter + utf8_length); + const std::map& charToComp = BopomofoCharacterMap::SharedInstance().characterToComponent; - std::map::const_iterator result = + std::map::const_iterator result = charToComp.find(component); - if (result == charToComp.end()) { - break; - } else { - syllable += BPMF((*result).second); + if (result == charToComp.end()) { + break; + } else { + syllable += BPMF((*result).second); + } + iter += utf8_length; } - iter += utf8_length; - } - return syllable; + return syllable; } const std::string BPMF::composedString() const { - std::string result; + std::string result; #define APPEND(c) \ - if (syllable_ & c) \ - result += \ - (*BopomofoCharacterMap::SharedInstance().componentToCharacter.find( \ - syllable_ & c)) \ - .second - APPEND(ConsonantMask); - APPEND(MiddleVowelMask); - APPEND(VowelMask); - APPEND(ToneMarkerMask); +if (syllable_ & c) \ +result += \ +(*BopomofoCharacterMap::SharedInstance().componentToCharacter.find( \ +syllable_ & c)) \ +.second + APPEND(ConsonantMask); + APPEND(MiddleVowelMask); + APPEND(VowelMask); + APPEND(ToneMarkerMask); #undef APPEND - return result; + return result; } const BopomofoCharacterMap& BopomofoCharacterMap::SharedInstance() { - static BopomofoCharacterMap* map = new BopomofoCharacterMap(); - return *map; + static BopomofoCharacterMap* map = new BopomofoCharacterMap(); + return *map; } BopomofoCharacterMap::BopomofoCharacterMap() { - characterToComponent[u8"ㄅ"] = BPMF::B; - characterToComponent[u8"ㄆ"] = BPMF::P; - characterToComponent[u8"ㄇ"] = BPMF::M; - characterToComponent[u8"ㄈ"] = BPMF::F; - characterToComponent[u8"ㄉ"] = BPMF::D; - characterToComponent[u8"ㄊ"] = BPMF::T; - characterToComponent[u8"ㄋ"] = BPMF::N; - characterToComponent[u8"ㄌ"] = BPMF::L; - characterToComponent[u8"ㄎ"] = BPMF::K; - characterToComponent[u8"ㄍ"] = BPMF::G; - characterToComponent[u8"ㄏ"] = BPMF::H; - characterToComponent[u8"ㄐ"] = BPMF::J; - characterToComponent[u8"ㄑ"] = BPMF::Q; - characterToComponent[u8"ㄒ"] = BPMF::X; - characterToComponent[u8"ㄓ"] = BPMF::ZH; - characterToComponent[u8"ㄔ"] = BPMF::CH; - characterToComponent[u8"ㄕ"] = BPMF::SH; - characterToComponent[u8"ㄖ"] = BPMF::R; - characterToComponent[u8"ㄗ"] = BPMF::Z; - characterToComponent[u8"ㄘ"] = BPMF::C; - characterToComponent[u8"ㄙ"] = BPMF::S; - characterToComponent[u8"ㄧ"] = BPMF::I; - characterToComponent[u8"ㄨ"] = BPMF::U; - characterToComponent[u8"ㄩ"] = BPMF::UE; - characterToComponent[u8"ㄚ"] = BPMF::A; - characterToComponent[u8"ㄛ"] = BPMF::O; - characterToComponent[u8"ㄜ"] = BPMF::ER; - characterToComponent[u8"ㄝ"] = BPMF::E; - characterToComponent[u8"ㄞ"] = BPMF::AI; - characterToComponent[u8"ㄟ"] = BPMF::EI; - characterToComponent[u8"ㄠ"] = BPMF::AO; - characterToComponent[u8"ㄡ"] = BPMF::OU; - characterToComponent[u8"ㄢ"] = BPMF::AN; - characterToComponent[u8"ㄣ"] = BPMF::EN; - characterToComponent[u8"ㄤ"] = BPMF::ANG; - characterToComponent[u8"ㄥ"] = BPMF::ENG; - characterToComponent[u8"ㄦ"] = BPMF::ERR; - characterToComponent[u8"ˊ"] = BPMF::Tone2; - characterToComponent[u8"ˇ"] = BPMF::Tone3; - characterToComponent[u8"ˋ"] = BPMF::Tone4; - characterToComponent[u8"˙"] = BPMF::Tone5; - - for (std::map::iterator iter = - characterToComponent.begin(); - iter != characterToComponent.end(); ++iter) - componentToCharacter[(*iter).second] = (*iter).first; + characterToComponent[u8"ㄅ"] = BPMF::B; + characterToComponent[u8"ㄆ"] = BPMF::P; + characterToComponent[u8"ㄇ"] = BPMF::M; + characterToComponent[u8"ㄈ"] = BPMF::F; + characterToComponent[u8"ㄉ"] = BPMF::D; + characterToComponent[u8"ㄊ"] = BPMF::T; + characterToComponent[u8"ㄋ"] = BPMF::N; + characterToComponent[u8"ㄌ"] = BPMF::L; + characterToComponent[u8"ㄎ"] = BPMF::K; + characterToComponent[u8"ㄍ"] = BPMF::G; + characterToComponent[u8"ㄏ"] = BPMF::H; + characterToComponent[u8"ㄐ"] = BPMF::J; + characterToComponent[u8"ㄑ"] = BPMF::Q; + characterToComponent[u8"ㄒ"] = BPMF::X; + characterToComponent[u8"ㄓ"] = BPMF::ZH; + characterToComponent[u8"ㄔ"] = BPMF::CH; + characterToComponent[u8"ㄕ"] = BPMF::SH; + characterToComponent[u8"ㄖ"] = BPMF::R; + characterToComponent[u8"ㄗ"] = BPMF::Z; + characterToComponent[u8"ㄘ"] = BPMF::C; + characterToComponent[u8"ㄙ"] = BPMF::S; + characterToComponent[u8"ㄧ"] = BPMF::I; + characterToComponent[u8"ㄨ"] = BPMF::U; + characterToComponent[u8"ㄩ"] = BPMF::UE; + characterToComponent[u8"ㄚ"] = BPMF::A; + characterToComponent[u8"ㄛ"] = BPMF::O; + characterToComponent[u8"ㄜ"] = BPMF::ER; + characterToComponent[u8"ㄝ"] = BPMF::E; + characterToComponent[u8"ㄞ"] = BPMF::AI; + characterToComponent[u8"ㄟ"] = BPMF::EI; + characterToComponent[u8"ㄠ"] = BPMF::AO; + characterToComponent[u8"ㄡ"] = BPMF::OU; + characterToComponent[u8"ㄢ"] = BPMF::AN; + characterToComponent[u8"ㄣ"] = BPMF::EN; + characterToComponent[u8"ㄤ"] = BPMF::ANG; + characterToComponent[u8"ㄥ"] = BPMF::ENG; + characterToComponent[u8"ㄦ"] = BPMF::ERR; + characterToComponent[u8"ˊ"] = BPMF::Tone2; + characterToComponent[u8"ˇ"] = BPMF::Tone3; + characterToComponent[u8"ˋ"] = BPMF::Tone4; + characterToComponent[u8"˙"] = BPMF::Tone5; + + for (std::map::iterator iter = + characterToComponent.begin(); + iter != characterToComponent.end(); ++iter) + componentToCharacter[(*iter).second] = (*iter).first; } #define ASSIGNKEY1(m, vec, k, val) \ - m[k] = (vec.clear(), vec.push_back((BPMF::Component)val), vec) +m[k] = (vec.clear(), vec.push_back((BPMF::Component)val), vec) #define ASSIGNKEY2(m, vec, k, val1, val2) \ - m[k] = (vec.clear(), vec.push_back((BPMF::Component)val1), \ - vec.push_back((BPMF::Component)val2), vec) +m[k] = (vec.clear(), vec.push_back((BPMF::Component)val1), \ +vec.push_back((BPMF::Component)val2), vec) #define ASSIGNKEY3(m, vec, k, val1, val2, val3) \ - m[k] = (vec.clear(), vec.push_back((BPMF::Component)val1), \ - vec.push_back((BPMF::Component)val2), \ - vec.push_back((BPMF::Component)val3), vec) +m[k] = (vec.clear(), vec.push_back((BPMF::Component)val1), \ +vec.push_back((BPMF::Component)val2), \ +vec.push_back((BPMF::Component)val3), vec) static BopomofoKeyboardLayout* CreateStandardLayout() { - std::vector vec; - BopomofoKeyToComponentMap ktcm; - - ASSIGNKEY1(ktcm, vec, '1', BPMF::B); - ASSIGNKEY1(ktcm, vec, 'q', BPMF::P); - ASSIGNKEY1(ktcm, vec, 'a', BPMF::M); - ASSIGNKEY1(ktcm, vec, 'z', BPMF::F); - ASSIGNKEY1(ktcm, vec, '2', BPMF::D); - ASSIGNKEY1(ktcm, vec, 'w', BPMF::T); - ASSIGNKEY1(ktcm, vec, 's', BPMF::N); - ASSIGNKEY1(ktcm, vec, 'x', BPMF::L); - ASSIGNKEY1(ktcm, vec, 'e', BPMF::G); - ASSIGNKEY1(ktcm, vec, 'd', BPMF::K); - ASSIGNKEY1(ktcm, vec, 'c', BPMF::H); - ASSIGNKEY1(ktcm, vec, 'r', BPMF::J); - ASSIGNKEY1(ktcm, vec, 'f', BPMF::Q); - ASSIGNKEY1(ktcm, vec, 'v', BPMF::X); - ASSIGNKEY1(ktcm, vec, '5', BPMF::ZH); - ASSIGNKEY1(ktcm, vec, 't', BPMF::CH); - ASSIGNKEY1(ktcm, vec, 'g', BPMF::SH); - ASSIGNKEY1(ktcm, vec, 'b', BPMF::R); - ASSIGNKEY1(ktcm, vec, 'y', BPMF::Z); - ASSIGNKEY1(ktcm, vec, 'h', BPMF::C); - ASSIGNKEY1(ktcm, vec, 'n', BPMF::S); - ASSIGNKEY1(ktcm, vec, 'u', BPMF::I); - ASSIGNKEY1(ktcm, vec, 'j', BPMF::U); - ASSIGNKEY1(ktcm, vec, 'm', BPMF::UE); - ASSIGNKEY1(ktcm, vec, '8', BPMF::A); - ASSIGNKEY1(ktcm, vec, 'i', BPMF::O); - ASSIGNKEY1(ktcm, vec, 'k', BPMF::ER); - ASSIGNKEY1(ktcm, vec, ',', BPMF::E); - ASSIGNKEY1(ktcm, vec, '9', BPMF::AI); - ASSIGNKEY1(ktcm, vec, 'o', BPMF::EI); - ASSIGNKEY1(ktcm, vec, 'l', BPMF::AO); - ASSIGNKEY1(ktcm, vec, '.', BPMF::OU); - ASSIGNKEY1(ktcm, vec, '0', BPMF::AN); - ASSIGNKEY1(ktcm, vec, 'p', BPMF::EN); - ASSIGNKEY1(ktcm, vec, ';', BPMF::ANG); - ASSIGNKEY1(ktcm, vec, '/', BPMF::ENG); - ASSIGNKEY1(ktcm, vec, '-', BPMF::ERR); - ASSIGNKEY1(ktcm, vec, '3', BPMF::Tone3); - ASSIGNKEY1(ktcm, vec, '4', BPMF::Tone4); - ASSIGNKEY1(ktcm, vec, '6', BPMF::Tone2); - ASSIGNKEY1(ktcm, vec, '7', BPMF::Tone5); - - return new BopomofoKeyboardLayout(ktcm, "Standard"); + std::vector vec; + BopomofoKeyToComponentMap ktcm; + + ASSIGNKEY1(ktcm, vec, '1', BPMF::B); + ASSIGNKEY1(ktcm, vec, 'q', BPMF::P); + ASSIGNKEY1(ktcm, vec, 'a', BPMF::M); + ASSIGNKEY1(ktcm, vec, 'z', BPMF::F); + ASSIGNKEY1(ktcm, vec, '2', BPMF::D); + ASSIGNKEY1(ktcm, vec, 'w', BPMF::T); + ASSIGNKEY1(ktcm, vec, 's', BPMF::N); + ASSIGNKEY1(ktcm, vec, 'x', BPMF::L); + ASSIGNKEY1(ktcm, vec, 'e', BPMF::G); + ASSIGNKEY1(ktcm, vec, 'd', BPMF::K); + ASSIGNKEY1(ktcm, vec, 'c', BPMF::H); + ASSIGNKEY1(ktcm, vec, 'r', BPMF::J); + ASSIGNKEY1(ktcm, vec, 'f', BPMF::Q); + ASSIGNKEY1(ktcm, vec, 'v', BPMF::X); + ASSIGNKEY1(ktcm, vec, '5', BPMF::ZH); + ASSIGNKEY1(ktcm, vec, 't', BPMF::CH); + ASSIGNKEY1(ktcm, vec, 'g', BPMF::SH); + ASSIGNKEY1(ktcm, vec, 'b', BPMF::R); + ASSIGNKEY1(ktcm, vec, 'y', BPMF::Z); + ASSIGNKEY1(ktcm, vec, 'h', BPMF::C); + ASSIGNKEY1(ktcm, vec, 'n', BPMF::S); + ASSIGNKEY1(ktcm, vec, 'u', BPMF::I); + ASSIGNKEY1(ktcm, vec, 'j', BPMF::U); + ASSIGNKEY1(ktcm, vec, 'm', BPMF::UE); + ASSIGNKEY1(ktcm, vec, '8', BPMF::A); + ASSIGNKEY1(ktcm, vec, 'i', BPMF::O); + ASSIGNKEY1(ktcm, vec, 'k', BPMF::ER); + ASSIGNKEY1(ktcm, vec, ',', BPMF::E); + ASSIGNKEY1(ktcm, vec, '9', BPMF::AI); + ASSIGNKEY1(ktcm, vec, 'o', BPMF::EI); + ASSIGNKEY1(ktcm, vec, 'l', BPMF::AO); + ASSIGNKEY1(ktcm, vec, '.', BPMF::OU); + ASSIGNKEY1(ktcm, vec, '0', BPMF::AN); + ASSIGNKEY1(ktcm, vec, 'p', BPMF::EN); + ASSIGNKEY1(ktcm, vec, ';', BPMF::ANG); + ASSIGNKEY1(ktcm, vec, '/', BPMF::ENG); + ASSIGNKEY1(ktcm, vec, '-', BPMF::ERR); + ASSIGNKEY1(ktcm, vec, '3', BPMF::Tone3); + ASSIGNKEY1(ktcm, vec, '4', BPMF::Tone4); + ASSIGNKEY1(ktcm, vec, '6', BPMF::Tone2); + ASSIGNKEY1(ktcm, vec, '7', BPMF::Tone5); + + return new BopomofoKeyboardLayout(ktcm, "Standard"); } static BopomofoKeyboardLayout* CreateIBMLayout() { - std::vector vec; - BopomofoKeyToComponentMap ktcm; + std::vector vec; + BopomofoKeyToComponentMap ktcm; + + ASSIGNKEY1(ktcm, vec, '1', BPMF::B); + ASSIGNKEY1(ktcm, vec, '2', BPMF::P); + ASSIGNKEY1(ktcm, vec, '3', BPMF::M); + ASSIGNKEY1(ktcm, vec, '4', BPMF::F); + ASSIGNKEY1(ktcm, vec, '5', BPMF::D); + ASSIGNKEY1(ktcm, vec, '6', BPMF::T); + ASSIGNKEY1(ktcm, vec, '7', BPMF::N); + ASSIGNKEY1(ktcm, vec, '8', BPMF::L); + ASSIGNKEY1(ktcm, vec, '9', BPMF::G); + ASSIGNKEY1(ktcm, vec, '0', BPMF::K); + ASSIGNKEY1(ktcm, vec, '-', BPMF::H); + ASSIGNKEY1(ktcm, vec, 'q', BPMF::J); + ASSIGNKEY1(ktcm, vec, 'w', BPMF::Q); + ASSIGNKEY1(ktcm, vec, 'e', BPMF::X); + ASSIGNKEY1(ktcm, vec, 'r', BPMF::ZH); + ASSIGNKEY1(ktcm, vec, 't', BPMF::CH); + ASSIGNKEY1(ktcm, vec, 'y', BPMF::SH); + ASSIGNKEY1(ktcm, vec, 'u', BPMF::R); + ASSIGNKEY1(ktcm, vec, 'i', BPMF::Z); + ASSIGNKEY1(ktcm, vec, 'o', BPMF::C); + ASSIGNKEY1(ktcm, vec, 'p', BPMF::S); + ASSIGNKEY1(ktcm, vec, 'a', BPMF::I); + ASSIGNKEY1(ktcm, vec, 's', BPMF::U); + ASSIGNKEY1(ktcm, vec, 'd', BPMF::UE); + ASSIGNKEY1(ktcm, vec, 'f', BPMF::A); + ASSIGNKEY1(ktcm, vec, 'g', BPMF::O); + ASSIGNKEY1(ktcm, vec, 'h', BPMF::ER); + ASSIGNKEY1(ktcm, vec, 'j', BPMF::E); + ASSIGNKEY1(ktcm, vec, 'k', BPMF::AI); + ASSIGNKEY1(ktcm, vec, 'l', BPMF::EI); + ASSIGNKEY1(ktcm, vec, ';', BPMF::AO); + ASSIGNKEY1(ktcm, vec, 'z', BPMF::OU); + ASSIGNKEY1(ktcm, vec, 'x', BPMF::AN); + ASSIGNKEY1(ktcm, vec, 'c', BPMF::EN); + ASSIGNKEY1(ktcm, vec, 'v', BPMF::ANG); + ASSIGNKEY1(ktcm, vec, 'b', BPMF::ENG); + ASSIGNKEY1(ktcm, vec, 'n', BPMF::ERR); + ASSIGNKEY1(ktcm, vec, 'm', BPMF::Tone2); + ASSIGNKEY1(ktcm, vec, ',', BPMF::Tone3); + ASSIGNKEY1(ktcm, vec, '.', BPMF::Tone4); + ASSIGNKEY1(ktcm, vec, '/', BPMF::Tone5); + + return new BopomofoKeyboardLayout(ktcm, "IBM"); +} - ASSIGNKEY1(ktcm, vec, '1', BPMF::B); - ASSIGNKEY1(ktcm, vec, '2', BPMF::P); - ASSIGNKEY1(ktcm, vec, '3', BPMF::M); - ASSIGNKEY1(ktcm, vec, '4', BPMF::F); - ASSIGNKEY1(ktcm, vec, '5', BPMF::D); - ASSIGNKEY1(ktcm, vec, '6', BPMF::T); - ASSIGNKEY1(ktcm, vec, '7', BPMF::N); - ASSIGNKEY1(ktcm, vec, '8', BPMF::L); - ASSIGNKEY1(ktcm, vec, '9', BPMF::G); - ASSIGNKEY1(ktcm, vec, '0', BPMF::K); - ASSIGNKEY1(ktcm, vec, '-', BPMF::H); - ASSIGNKEY1(ktcm, vec, 'q', BPMF::J); - ASSIGNKEY1(ktcm, vec, 'w', BPMF::Q); - ASSIGNKEY1(ktcm, vec, 'e', BPMF::X); - ASSIGNKEY1(ktcm, vec, 'r', BPMF::ZH); - ASSIGNKEY1(ktcm, vec, 't', BPMF::CH); - ASSIGNKEY1(ktcm, vec, 'y', BPMF::SH); - ASSIGNKEY1(ktcm, vec, 'u', BPMF::R); - ASSIGNKEY1(ktcm, vec, 'i', BPMF::Z); - ASSIGNKEY1(ktcm, vec, 'o', BPMF::C); - ASSIGNKEY1(ktcm, vec, 'p', BPMF::S); - ASSIGNKEY1(ktcm, vec, 'a', BPMF::I); - ASSIGNKEY1(ktcm, vec, 's', BPMF::U); - ASSIGNKEY1(ktcm, vec, 'd', BPMF::UE); - ASSIGNKEY1(ktcm, vec, 'f', BPMF::A); - ASSIGNKEY1(ktcm, vec, 'g', BPMF::O); - ASSIGNKEY1(ktcm, vec, 'h', BPMF::ER); - ASSIGNKEY1(ktcm, vec, 'j', BPMF::E); - ASSIGNKEY1(ktcm, vec, 'k', BPMF::AI); - ASSIGNKEY1(ktcm, vec, 'l', BPMF::EI); - ASSIGNKEY1(ktcm, vec, ';', BPMF::AO); - ASSIGNKEY1(ktcm, vec, 'z', BPMF::OU); - ASSIGNKEY1(ktcm, vec, 'x', BPMF::AN); - ASSIGNKEY1(ktcm, vec, 'c', BPMF::EN); - ASSIGNKEY1(ktcm, vec, 'v', BPMF::ANG); - ASSIGNKEY1(ktcm, vec, 'b', BPMF::ENG); - ASSIGNKEY1(ktcm, vec, 'n', BPMF::ERR); - ASSIGNKEY1(ktcm, vec, 'm', BPMF::Tone2); - ASSIGNKEY1(ktcm, vec, ',', BPMF::Tone3); - ASSIGNKEY1(ktcm, vec, '.', BPMF::Tone4); - ASSIGNKEY1(ktcm, vec, '/', BPMF::Tone5); - - return new BopomofoKeyboardLayout(ktcm, "IBM"); +static BopomofoKeyboardLayout* CreateMiTACLayout() { + std::vector vec; + BopomofoKeyToComponentMap ktcm; + + ASSIGNKEY1(ktcm, vec, '1', BPMF::Tone5); + ASSIGNKEY1(ktcm, vec, '2', BPMF::Tone2); + ASSIGNKEY1(ktcm, vec, '3', BPMF::Tone3); + ASSIGNKEY1(ktcm, vec, '4', BPMF::Tone4); + ASSIGNKEY1(ktcm, vec, '5', BPMF::AI); + ASSIGNKEY1(ktcm, vec, '6', BPMF::AO); + ASSIGNKEY1(ktcm, vec, '7', BPMF::AN); + ASSIGNKEY1(ktcm, vec, '8', BPMF::EN); + ASSIGNKEY1(ktcm, vec, '9', BPMF::ANG); + ASSIGNKEY1(ktcm, vec, '0', BPMF::ENG); + ASSIGNKEY1(ktcm, vec, '-', BPMF::ERR); + ASSIGNKEY1(ktcm, vec, ';', BPMF::E); + ASSIGNKEY1(ktcm, vec, ',', BPMF::ZH); + ASSIGNKEY1(ktcm, vec, '.', BPMF::CH); + ASSIGNKEY1(ktcm, vec, '/', BPMF::SH); + ASSIGNKEY1(ktcm, vec, 'a', BPMF::A); + ASSIGNKEY1(ktcm, vec, 'b', BPMF::B); + ASSIGNKEY1(ktcm, vec, 'c', BPMF::C); + ASSIGNKEY1(ktcm, vec, 'd', BPMF::D); + ASSIGNKEY1(ktcm, vec, 'e', BPMF::ER); + ASSIGNKEY1(ktcm, vec, 'f', BPMF::F); + ASSIGNKEY1(ktcm, vec, 'g', BPMF::G); + ASSIGNKEY1(ktcm, vec, 'h', BPMF::H); + ASSIGNKEY1(ktcm, vec, 'i', BPMF::EI); + ASSIGNKEY1(ktcm, vec, 'j', BPMF::J); + ASSIGNKEY1(ktcm, vec, 'k', BPMF::K); + ASSIGNKEY1(ktcm, vec, 'l', BPMF::L); + ASSIGNKEY1(ktcm, vec, 'm', BPMF::M); + ASSIGNKEY1(ktcm, vec, 'n', BPMF::N); + ASSIGNKEY1(ktcm, vec, 'o', BPMF::O); + ASSIGNKEY1(ktcm, vec, 'p', BPMF::P); + ASSIGNKEY1(ktcm, vec, 'q', BPMF::Q); + ASSIGNKEY1(ktcm, vec, 'r', BPMF::R); + ASSIGNKEY1(ktcm, vec, 's', BPMF::S); + ASSIGNKEY1(ktcm, vec, 't', BPMF::T); + ASSIGNKEY1(ktcm, vec, 'u', BPMF::OU); + ASSIGNKEY1(ktcm, vec, 'v', BPMF::UE); + ASSIGNKEY1(ktcm, vec, 'w', BPMF::U); + ASSIGNKEY1(ktcm, vec, 'x', BPMF::X); + ASSIGNKEY1(ktcm, vec, 'y', BPMF::I); + ASSIGNKEY1(ktcm, vec, 'z', BPMF::Z); + + return new BopomofoKeyboardLayout(ktcm, "MiTAC"); } static BopomofoKeyboardLayout* CreateETenLayout() { - std::vector vec; - BopomofoKeyToComponentMap ktcm; - - ASSIGNKEY1(ktcm, vec, 'b', BPMF::B); - ASSIGNKEY1(ktcm, vec, 'p', BPMF::P); - ASSIGNKEY1(ktcm, vec, 'm', BPMF::M); - ASSIGNKEY1(ktcm, vec, 'f', BPMF::F); - ASSIGNKEY1(ktcm, vec, 'd', BPMF::D); - ASSIGNKEY1(ktcm, vec, 't', BPMF::T); - ASSIGNKEY1(ktcm, vec, 'n', BPMF::N); - ASSIGNKEY1(ktcm, vec, 'l', BPMF::L); - ASSIGNKEY1(ktcm, vec, 'v', BPMF::G); - ASSIGNKEY1(ktcm, vec, 'k', BPMF::K); - ASSIGNKEY1(ktcm, vec, 'h', BPMF::H); - ASSIGNKEY1(ktcm, vec, 'g', BPMF::J); - ASSIGNKEY1(ktcm, vec, '7', BPMF::Q); - ASSIGNKEY1(ktcm, vec, 'c', BPMF::X); - ASSIGNKEY1(ktcm, vec, ',', BPMF::ZH); - ASSIGNKEY1(ktcm, vec, '.', BPMF::CH); - ASSIGNKEY1(ktcm, vec, '/', BPMF::SH); - ASSIGNKEY1(ktcm, vec, 'j', BPMF::R); - ASSIGNKEY1(ktcm, vec, ';', BPMF::Z); - ASSIGNKEY1(ktcm, vec, '\'', BPMF::C); - ASSIGNKEY1(ktcm, vec, 's', BPMF::S); - ASSIGNKEY1(ktcm, vec, 'e', BPMF::I); - ASSIGNKEY1(ktcm, vec, 'x', BPMF::U); - ASSIGNKEY1(ktcm, vec, 'u', BPMF::UE); - ASSIGNKEY1(ktcm, vec, 'a', BPMF::A); - ASSIGNKEY1(ktcm, vec, 'o', BPMF::O); - ASSIGNKEY1(ktcm, vec, 'r', BPMF::ER); - ASSIGNKEY1(ktcm, vec, 'w', BPMF::E); - ASSIGNKEY1(ktcm, vec, 'i', BPMF::AI); - ASSIGNKEY1(ktcm, vec, 'q', BPMF::EI); - ASSIGNKEY1(ktcm, vec, 'z', BPMF::AO); - ASSIGNKEY1(ktcm, vec, 'y', BPMF::OU); - ASSIGNKEY1(ktcm, vec, '8', BPMF::AN); - ASSIGNKEY1(ktcm, vec, '9', BPMF::EN); - ASSIGNKEY1(ktcm, vec, '0', BPMF::ANG); - ASSIGNKEY1(ktcm, vec, '-', BPMF::ENG); - ASSIGNKEY1(ktcm, vec, '=', BPMF::ERR); - ASSIGNKEY1(ktcm, vec, '2', BPMF::Tone2); - ASSIGNKEY1(ktcm, vec, '3', BPMF::Tone3); - ASSIGNKEY1(ktcm, vec, '4', BPMF::Tone4); - ASSIGNKEY1(ktcm, vec, '1', BPMF::Tone5); - - return new BopomofoKeyboardLayout(ktcm, "ETen"); + std::vector vec; + BopomofoKeyToComponentMap ktcm; + + ASSIGNKEY1(ktcm, vec, 'b', BPMF::B); + ASSIGNKEY1(ktcm, vec, 'p', BPMF::P); + ASSIGNKEY1(ktcm, vec, 'm', BPMF::M); + ASSIGNKEY1(ktcm, vec, 'f', BPMF::F); + ASSIGNKEY1(ktcm, vec, 'd', BPMF::D); + ASSIGNKEY1(ktcm, vec, 't', BPMF::T); + ASSIGNKEY1(ktcm, vec, 'n', BPMF::N); + ASSIGNKEY1(ktcm, vec, 'l', BPMF::L); + ASSIGNKEY1(ktcm, vec, 'v', BPMF::G); + ASSIGNKEY1(ktcm, vec, 'k', BPMF::K); + ASSIGNKEY1(ktcm, vec, 'h', BPMF::H); + ASSIGNKEY1(ktcm, vec, 'g', BPMF::J); + ASSIGNKEY1(ktcm, vec, '7', BPMF::Q); + ASSIGNKEY1(ktcm, vec, 'c', BPMF::X); + ASSIGNKEY1(ktcm, vec, ',', BPMF::ZH); + ASSIGNKEY1(ktcm, vec, '.', BPMF::CH); + ASSIGNKEY1(ktcm, vec, '/', BPMF::SH); + ASSIGNKEY1(ktcm, vec, 'j', BPMF::R); + ASSIGNKEY1(ktcm, vec, ';', BPMF::Z); + ASSIGNKEY1(ktcm, vec, '\'', BPMF::C); + ASSIGNKEY1(ktcm, vec, 's', BPMF::S); + ASSIGNKEY1(ktcm, vec, 'e', BPMF::I); + ASSIGNKEY1(ktcm, vec, 'x', BPMF::U); + ASSIGNKEY1(ktcm, vec, 'u', BPMF::UE); + ASSIGNKEY1(ktcm, vec, 'a', BPMF::A); + ASSIGNKEY1(ktcm, vec, 'o', BPMF::O); + ASSIGNKEY1(ktcm, vec, 'r', BPMF::ER); + ASSIGNKEY1(ktcm, vec, 'w', BPMF::E); + ASSIGNKEY1(ktcm, vec, 'i', BPMF::AI); + ASSIGNKEY1(ktcm, vec, 'q', BPMF::EI); + ASSIGNKEY1(ktcm, vec, 'z', BPMF::AO); + ASSIGNKEY1(ktcm, vec, 'y', BPMF::OU); + ASSIGNKEY1(ktcm, vec, '8', BPMF::AN); + ASSIGNKEY1(ktcm, vec, '9', BPMF::EN); + ASSIGNKEY1(ktcm, vec, '0', BPMF::ANG); + ASSIGNKEY1(ktcm, vec, '-', BPMF::ENG); + ASSIGNKEY1(ktcm, vec, '=', BPMF::ERR); + ASSIGNKEY1(ktcm, vec, '2', BPMF::Tone2); + ASSIGNKEY1(ktcm, vec, '3', BPMF::Tone3); + ASSIGNKEY1(ktcm, vec, '4', BPMF::Tone4); + ASSIGNKEY1(ktcm, vec, '1', BPMF::Tone5); + + return new BopomofoKeyboardLayout(ktcm, "ETen"); } static BopomofoKeyboardLayout* CreateHsuLayout() { - std::vector vec; - BopomofoKeyToComponentMap ktcm; - - ASSIGNKEY1(ktcm, vec, 'b', BPMF::B); - ASSIGNKEY1(ktcm, vec, 'p', BPMF::P); - ASSIGNKEY2(ktcm, vec, 'm', BPMF::M, BPMF::AN); - ASSIGNKEY2(ktcm, vec, 'f', BPMF::F, BPMF::Tone3); - ASSIGNKEY2(ktcm, vec, 'd', BPMF::D, BPMF::Tone2); - ASSIGNKEY1(ktcm, vec, 't', BPMF::T); - ASSIGNKEY2(ktcm, vec, 'n', BPMF::N, BPMF::EN); - ASSIGNKEY3(ktcm, vec, 'l', BPMF::L, BPMF::ENG, BPMF::ERR); - ASSIGNKEY2(ktcm, vec, 'g', BPMF::G, BPMF::ER); - ASSIGNKEY2(ktcm, vec, 'k', BPMF::K, BPMF::ANG); - ASSIGNKEY2(ktcm, vec, 'h', BPMF::H, BPMF::O); - ASSIGNKEY3(ktcm, vec, 'j', BPMF::J, BPMF::ZH, BPMF::Tone4); - ASSIGNKEY2(ktcm, vec, 'v', BPMF::Q, BPMF::CH); - ASSIGNKEY2(ktcm, vec, 'c', BPMF::X, BPMF::SH); - ASSIGNKEY1(ktcm, vec, 'r', BPMF::R); - ASSIGNKEY1(ktcm, vec, 'z', BPMF::Z); - ASSIGNKEY2(ktcm, vec, 'a', BPMF::C, BPMF::EI); - ASSIGNKEY2(ktcm, vec, 's', BPMF::S, BPMF::Tone5); - ASSIGNKEY2(ktcm, vec, 'e', BPMF::I, BPMF::E); - ASSIGNKEY1(ktcm, vec, 'x', BPMF::U); - ASSIGNKEY1(ktcm, vec, 'u', BPMF::UE); - ASSIGNKEY1(ktcm, vec, 'y', BPMF::A); - ASSIGNKEY1(ktcm, vec, 'i', BPMF::AI); - ASSIGNKEY1(ktcm, vec, 'w', BPMF::AO); - ASSIGNKEY1(ktcm, vec, 'o', BPMF::OU); - - return new BopomofoKeyboardLayout(ktcm, "Hsu"); + std::vector vec; + BopomofoKeyToComponentMap ktcm; + + ASSIGNKEY1(ktcm, vec, 'b', BPMF::B); + ASSIGNKEY1(ktcm, vec, 'p', BPMF::P); + ASSIGNKEY2(ktcm, vec, 'm', BPMF::M, BPMF::AN); + ASSIGNKEY2(ktcm, vec, 'f', BPMF::F, BPMF::Tone3); + ASSIGNKEY2(ktcm, vec, 'd', BPMF::D, BPMF::Tone2); + ASSIGNKEY1(ktcm, vec, 't', BPMF::T); + ASSIGNKEY2(ktcm, vec, 'n', BPMF::N, BPMF::EN); + ASSIGNKEY3(ktcm, vec, 'l', BPMF::L, BPMF::ENG, BPMF::ERR); + ASSIGNKEY2(ktcm, vec, 'g', BPMF::G, BPMF::ER); + ASSIGNKEY2(ktcm, vec, 'k', BPMF::K, BPMF::ANG); + ASSIGNKEY2(ktcm, vec, 'h', BPMF::H, BPMF::O); + ASSIGNKEY3(ktcm, vec, 'j', BPMF::J, BPMF::ZH, BPMF::Tone4); + ASSIGNKEY2(ktcm, vec, 'v', BPMF::Q, BPMF::CH); + ASSIGNKEY2(ktcm, vec, 'c', BPMF::X, BPMF::SH); + ASSIGNKEY1(ktcm, vec, 'r', BPMF::R); + ASSIGNKEY1(ktcm, vec, 'z', BPMF::Z); + ASSIGNKEY2(ktcm, vec, 'a', BPMF::C, BPMF::EI); + ASSIGNKEY2(ktcm, vec, 's', BPMF::S, BPMF::Tone5); + ASSIGNKEY2(ktcm, vec, 'e', BPMF::I, BPMF::E); + ASSIGNKEY1(ktcm, vec, 'x', BPMF::U); + ASSIGNKEY1(ktcm, vec, 'u', BPMF::UE); + ASSIGNKEY1(ktcm, vec, 'y', BPMF::A); + ASSIGNKEY1(ktcm, vec, 'i', BPMF::AI); + ASSIGNKEY1(ktcm, vec, 'w', BPMF::AO); + ASSIGNKEY1(ktcm, vec, 'o', BPMF::OU); + + return new BopomofoKeyboardLayout(ktcm, "Hsu"); } static BopomofoKeyboardLayout* CreateETen26Layout() { - std::vector vec; - BopomofoKeyToComponentMap ktcm; - - ASSIGNKEY1(ktcm, vec, 'b', BPMF::B); - ASSIGNKEY2(ktcm, vec, 'p', BPMF::P, BPMF::OU); - ASSIGNKEY2(ktcm, vec, 'm', BPMF::M, BPMF::AN); - ASSIGNKEY2(ktcm, vec, 'f', BPMF::F, BPMF::Tone2); - ASSIGNKEY2(ktcm, vec, 'd', BPMF::D, BPMF::Tone5); - ASSIGNKEY2(ktcm, vec, 't', BPMF::T, BPMF::ANG); - ASSIGNKEY2(ktcm, vec, 'n', BPMF::N, BPMF::EN); - ASSIGNKEY2(ktcm, vec, 'l', BPMF::L, BPMF::ENG); - ASSIGNKEY2(ktcm, vec, 'v', BPMF::G, BPMF::Q); - ASSIGNKEY2(ktcm, vec, 'k', BPMF::K, BPMF::Tone4); - ASSIGNKEY2(ktcm, vec, 'h', BPMF::H, BPMF::ERR); - ASSIGNKEY2(ktcm, vec, 'g', BPMF::ZH, BPMF::J); - ASSIGNKEY2(ktcm, vec, 'c', BPMF::SH, BPMF::X); - ASSIGNKEY1(ktcm, vec, 'y', BPMF::CH); - ASSIGNKEY2(ktcm, vec, 'j', BPMF::R, BPMF::Tone3); - ASSIGNKEY2(ktcm, vec, 'q', BPMF::Z, BPMF::EI); - ASSIGNKEY2(ktcm, vec, 'w', BPMF::C, BPMF::E); - ASSIGNKEY1(ktcm, vec, 's', BPMF::S); - ASSIGNKEY1(ktcm, vec, 'e', BPMF::I); - ASSIGNKEY1(ktcm, vec, 'x', BPMF::U); - ASSIGNKEY1(ktcm, vec, 'u', BPMF::UE); - ASSIGNKEY1(ktcm, vec, 'a', BPMF::A); - ASSIGNKEY1(ktcm, vec, 'o', BPMF::O); - ASSIGNKEY1(ktcm, vec, 'r', BPMF::ER); - ASSIGNKEY1(ktcm, vec, 'i', BPMF::AI); - ASSIGNKEY1(ktcm, vec, 'z', BPMF::AO); - return new BopomofoKeyboardLayout(ktcm, "ETen26"); + std::vector vec; + BopomofoKeyToComponentMap ktcm; + + ASSIGNKEY1(ktcm, vec, 'b', BPMF::B); + ASSIGNKEY2(ktcm, vec, 'p', BPMF::P, BPMF::OU); + ASSIGNKEY2(ktcm, vec, 'm', BPMF::M, BPMF::AN); + ASSIGNKEY2(ktcm, vec, 'f', BPMF::F, BPMF::Tone2); + ASSIGNKEY2(ktcm, vec, 'd', BPMF::D, BPMF::Tone5); + ASSIGNKEY2(ktcm, vec, 't', BPMF::T, BPMF::ANG); + ASSIGNKEY2(ktcm, vec, 'n', BPMF::N, BPMF::EN); + ASSIGNKEY2(ktcm, vec, 'l', BPMF::L, BPMF::ENG); + ASSIGNKEY2(ktcm, vec, 'v', BPMF::G, BPMF::Q); + ASSIGNKEY2(ktcm, vec, 'k', BPMF::K, BPMF::Tone4); + ASSIGNKEY2(ktcm, vec, 'h', BPMF::H, BPMF::ERR); + ASSIGNKEY2(ktcm, vec, 'g', BPMF::ZH, BPMF::J); + ASSIGNKEY2(ktcm, vec, 'c', BPMF::SH, BPMF::X); + ASSIGNKEY1(ktcm, vec, 'y', BPMF::CH); + ASSIGNKEY2(ktcm, vec, 'j', BPMF::R, BPMF::Tone3); + ASSIGNKEY2(ktcm, vec, 'q', BPMF::Z, BPMF::EI); + ASSIGNKEY2(ktcm, vec, 'w', BPMF::C, BPMF::E); + ASSIGNKEY1(ktcm, vec, 's', BPMF::S); + ASSIGNKEY1(ktcm, vec, 'e', BPMF::I); + ASSIGNKEY1(ktcm, vec, 'x', BPMF::U); + ASSIGNKEY1(ktcm, vec, 'u', BPMF::UE); + ASSIGNKEY1(ktcm, vec, 'a', BPMF::A); + ASSIGNKEY1(ktcm, vec, 'o', BPMF::O); + ASSIGNKEY1(ktcm, vec, 'r', BPMF::ER); + ASSIGNKEY1(ktcm, vec, 'i', BPMF::AI); + ASSIGNKEY1(ktcm, vec, 'z', BPMF::AO); + return new BopomofoKeyboardLayout(ktcm, "ETen26"); } static BopomofoKeyboardLayout* CreateHanyuPinyinLayout() { - BopomofoKeyToComponentMap ktcm; - return new BopomofoKeyboardLayout(ktcm, "HanyuPinyin"); + BopomofoKeyToComponentMap ktcm; + return new BopomofoKeyboardLayout(ktcm, "HanyuPinyin"); } const BopomofoKeyboardLayout* BopomofoKeyboardLayout::StandardLayout() { - static BopomofoKeyboardLayout* layout = CreateStandardLayout(); - return layout; + static BopomofoKeyboardLayout* layout = CreateStandardLayout(); + return layout; } const BopomofoKeyboardLayout* BopomofoKeyboardLayout::ETenLayout() { - static BopomofoKeyboardLayout* layout = CreateETenLayout(); - return layout; + static BopomofoKeyboardLayout* layout = CreateETenLayout(); + return layout; } const BopomofoKeyboardLayout* BopomofoKeyboardLayout::HsuLayout() { - static BopomofoKeyboardLayout* layout = CreateHsuLayout(); - return layout; + static BopomofoKeyboardLayout* layout = CreateHsuLayout(); + return layout; } const BopomofoKeyboardLayout* BopomofoKeyboardLayout::ETen26Layout() { - static BopomofoKeyboardLayout* layout = CreateETen26Layout(); - return layout; + static BopomofoKeyboardLayout* layout = CreateETen26Layout(); + return layout; } const BopomofoKeyboardLayout* BopomofoKeyboardLayout::IBMLayout() { - static BopomofoKeyboardLayout* layout = CreateIBMLayout(); - return layout; + static BopomofoKeyboardLayout* layout = CreateIBMLayout(); + return layout; +} + +const BopomofoKeyboardLayout* BopomofoKeyboardLayout::MiTACLayout() { + static BopomofoKeyboardLayout* layout = CreateMiTACLayout(); + return layout; } const BopomofoKeyboardLayout* BopomofoKeyboardLayout::HanyuPinyinLayout() { - static BopomofoKeyboardLayout* layout = CreateHanyuPinyinLayout(); - return layout; + static BopomofoKeyboardLayout* layout = CreateHanyuPinyinLayout(); + return layout; } } // namespace Mandarin } // namespace Taiyan + diff --git a/Source/3rdParty/OVMandarin/Mandarin.h b/Source/3rdParty/OVMandarin/Mandarin.h index d1fd2be9..50be17cf 100644 --- a/Source/3rdParty/OVMandarin/Mandarin.h +++ b/Source/3rdParty/OVMandarin/Mandarin.h @@ -29,176 +29,176 @@ namespace Taiyan { namespace Mandarin { class BopomofoSyllable { - public: - typedef uint16_t Component; - - explicit BopomofoSyllable(Component syllable = 0) : syllable_(syllable) {} - - BopomofoSyllable(const BopomofoSyllable&) = default; - BopomofoSyllable(BopomofoSyllable&& another) = default; - BopomofoSyllable& operator=(const BopomofoSyllable&) = default; - BopomofoSyllable& operator=(BopomofoSyllable&&) = default; - - // takes the ASCII-form, "v"-tolerant, TW-style Hanyu Pinyin (fong, pong, bong - // acceptable) - static const BopomofoSyllable FromHanyuPinyin(const std::string& str); - - // TO DO: Support accented vowels - const std::string HanyuPinyinString(bool includesTone, - bool useVForUUmlaut) const; - // const std::string HanyuPinyinString(bool includesTone, bool useVForUUmlaut, - // bool composeAccentedVowel) const; - - // PHT = Pai-hua-tsi - static const BopomofoSyllable FromPHT(const std::string& str); - const std::string PHTString(bool includesTone) const; - - static const BopomofoSyllable FromComposedString(const std::string& str); - const std::string composedString() const; - - void clear() { syllable_ = 0; } - - bool isEmpty() const { return !syllable_; } - - bool hasConsonant() const { return !!(syllable_ & ConsonantMask); } - - bool hasMiddleVowel() const { return !!(syllable_ & MiddleVowelMask); } - bool hasVowel() const { return !!(syllable_ & VowelMask); } - - bool hasToneMarker() const { return !!(syllable_ & ToneMarkerMask); } - - Component consonantComponent() const { return syllable_ & ConsonantMask; } - - Component middleVowelComponent() const { - return syllable_ & MiddleVowelMask; - } - - Component vowelComponent() const { return syllable_ & VowelMask; } - - Component toneMarkerComponent() const { return syllable_ & ToneMarkerMask; } - - bool operator==(const BopomofoSyllable& another) const { - return syllable_ == another.syllable_; - } - - bool operator!=(const BopomofoSyllable& another) const { - return syllable_ != another.syllable_; - } - - bool isOverlappingWith(const BopomofoSyllable& another) const { +public: + typedef uint16_t Component; + + explicit BopomofoSyllable(Component syllable = 0) : syllable_(syllable) {} + + BopomofoSyllable(const BopomofoSyllable&) = default; + BopomofoSyllable(BopomofoSyllable&& another) = default; + BopomofoSyllable& operator=(const BopomofoSyllable&) = default; + BopomofoSyllable& operator=(BopomofoSyllable&&) = default; + + // takes the ASCII-form, "v"-tolerant, TW-style Hanyu Pinyin (fong, pong, bong + // acceptable) + static const BopomofoSyllable FromHanyuPinyin(const std::string& str); + + // TO DO: Support accented vowels + const std::string HanyuPinyinString(bool includesTone, + bool useVForUUmlaut) const; + // const std::string HanyuPinyinString(bool includesTone, bool useVForUUmlaut, + // bool composeAccentedVowel) const; + + // PHT = Pai-hua-tsi + static const BopomofoSyllable FromPHT(const std::string& str); + const std::string PHTString(bool includesTone) const; + + static const BopomofoSyllable FromComposedString(const std::string& str); + const std::string composedString() const; + + void clear() { syllable_ = 0; } + + bool isEmpty() const { return !syllable_; } + + bool hasConsonant() const { return !!(syllable_ & ConsonantMask); } + + bool hasMiddleVowel() const { return !!(syllable_ & MiddleVowelMask); } + bool hasVowel() const { return !!(syllable_ & VowelMask); } + + bool hasToneMarker() const { return !!(syllable_ & ToneMarkerMask); } + + Component consonantComponent() const { return syllable_ & ConsonantMask; } + + Component middleVowelComponent() const { + return syllable_ & MiddleVowelMask; + } + + Component vowelComponent() const { return syllable_ & VowelMask; } + + Component toneMarkerComponent() const { return syllable_ & ToneMarkerMask; } + + bool operator==(const BopomofoSyllable& another) const { + return syllable_ == another.syllable_; + } + + bool operator!=(const BopomofoSyllable& another) const { + return syllable_ != another.syllable_; + } + + bool isOverlappingWith(const BopomofoSyllable& another) const { #define IOW_SAND(mask) ((syllable_ & mask) && (another.syllable_ & mask)) - return IOW_SAND(ConsonantMask) || IOW_SAND(MiddleVowelMask) || - IOW_SAND(VowelMask) || IOW_SAND(ToneMarkerMask); + return IOW_SAND(ConsonantMask) || IOW_SAND(MiddleVowelMask) || + IOW_SAND(VowelMask) || IOW_SAND(ToneMarkerMask); #undef IOW_SAND - } - - // consonants J, Q, X all require the existence of vowel I or UE - bool belongsToJQXClass() const { - Component consonant = syllable_ & ConsonantMask; - return (consonant == J || consonant == Q || consonant == X); - } - - // zi, ci, si, chi, chi, shi, ri - bool belongsToZCSRClass() const { - Component consonant = syllable_ & ConsonantMask; - return (consonant >= ZH && consonant <= S); - } - - Component maskType() const { - Component mask = 0; - mask |= (syllable_ & ConsonantMask) ? ConsonantMask : 0; - mask |= (syllable_ & MiddleVowelMask) ? MiddleVowelMask : 0; - mask |= (syllable_ & VowelMask) ? VowelMask : 0; - mask |= (syllable_ & ToneMarkerMask) ? ToneMarkerMask : 0; - return mask; - } - - const BopomofoSyllable operator+(const BopomofoSyllable& another) const { - Component newSyllable = syllable_; + } + + // consonants J, Q, X all require the existence of vowel I or UE + bool belongsToJQXClass() const { + Component consonant = syllable_ & ConsonantMask; + return (consonant == J || consonant == Q || consonant == X); + } + + // zi, ci, si, chi, chi, shi, ri + bool belongsToZCSRClass() const { + Component consonant = syllable_ & ConsonantMask; + return (consonant >= ZH && consonant <= S); + } + + Component maskType() const { + Component mask = 0; + mask |= (syllable_ & ConsonantMask) ? ConsonantMask : 0; + mask |= (syllable_ & MiddleVowelMask) ? MiddleVowelMask : 0; + mask |= (syllable_ & VowelMask) ? VowelMask : 0; + mask |= (syllable_ & ToneMarkerMask) ? ToneMarkerMask : 0; + return mask; + } + + const BopomofoSyllable operator+(const BopomofoSyllable& another) const { + Component newSyllable = syllable_; #define OP_SOVER(mask) \ - if (another.syllable_ & mask) { \ - newSyllable = (newSyllable & ~mask) | (another.syllable_ & mask); \ - } - OP_SOVER(ConsonantMask); - OP_SOVER(MiddleVowelMask); - OP_SOVER(VowelMask); - OP_SOVER(ToneMarkerMask); +if (another.syllable_ & mask) { \ +newSyllable = (newSyllable & ~mask) | (another.syllable_ & mask); \ +} + OP_SOVER(ConsonantMask); + OP_SOVER(MiddleVowelMask); + OP_SOVER(VowelMask); + OP_SOVER(ToneMarkerMask); #undef OP_SOVER - return BopomofoSyllable(newSyllable); - } - - BopomofoSyllable& operator+=(const BopomofoSyllable& another) { + return BopomofoSyllable(newSyllable); + } + + BopomofoSyllable& operator+=(const BopomofoSyllable& another) { #define OPE_SOVER(mask) \ - if (another.syllable_ & mask) { \ - syllable_ = (syllable_ & ~mask) | (another.syllable_ & mask); \ - } - OPE_SOVER(ConsonantMask); - OPE_SOVER(MiddleVowelMask); - OPE_SOVER(VowelMask); - OPE_SOVER(ToneMarkerMask); +if (another.syllable_ & mask) { \ +syllable_ = (syllable_ & ~mask) | (another.syllable_ & mask); \ +} + OPE_SOVER(ConsonantMask); + OPE_SOVER(MiddleVowelMask); + OPE_SOVER(VowelMask); + OPE_SOVER(ToneMarkerMask); #undef OPE_SOVER - return *this; - } - - uint16_t absoluteOrder() const { - // turn BPMF syllable into a 4*14*4*22 number - return (uint16_t)(syllable_ & ConsonantMask) + - (uint16_t)((syllable_ & MiddleVowelMask) >> 5) * 22 + - (uint16_t)((syllable_ & VowelMask) >> 7) * 22 * 4 + - (uint16_t)((syllable_ & ToneMarkerMask) >> 11) * 22 * 4 * 14; - } - - const std::string absoluteOrderString() const { - // 5*14*4*22 = 6160, we use a 79*79 encoding to represent that - uint16_t order = absoluteOrder(); - char low = 48 + static_cast(order % 79); - char high = 48 + static_cast(order / 79); - std::string result(2, ' '); - result[0] = low; - result[1] = high; - return result; - } - - static BopomofoSyllable FromAbsoluteOrder(uint16_t order) { - return BopomofoSyllable((order % 22) | ((order / 22) % 4) << 5 | - ((order / (22 * 4)) % 14) << 7 | - ((order / (22 * 4 * 14)) % 5) << 11); - } - - static BopomofoSyllable FromAbsoluteOrderString(const std::string& str) { - if (str.length() != 2) return BopomofoSyllable(); - - return FromAbsoluteOrder((uint16_t)(str[1] - 48) * 79 + - (uint16_t)(str[0] - 48)); - } - - friend std::ostream& operator<<(std::ostream& stream, - const BopomofoSyllable& syllable); - - static constexpr Component - ConsonantMask = 0x001f, // 0000 0000 0001 1111, 21 consonants - MiddleVowelMask = 0x0060, // 0000 0000 0110 0000, 3 middle vowels - VowelMask = 0x0780, // 0000 0111 1000 0000, 13 vowels - ToneMarkerMask = 0x3800, // 0011 1000 0000 0000, 5 tones (tone1 = 0x00) - B = 0x0001, P = 0x0002, M = 0x0003, F = 0x0004, D = 0x0005, T = 0x0006, - N = 0x0007, L = 0x0008, G = 0x0009, K = 0x000a, H = 0x000b, J = 0x000c, - Q = 0x000d, X = 0x000e, ZH = 0x000f, CH = 0x0010, SH = 0x0011, R = 0x0012, - Z = 0x0013, C = 0x0014, S = 0x0015, I = 0x0020, U = 0x0040, - UE = 0x0060, // ue = u umlaut (we use the German convention here as an - // ersatz to the /ju:/ sound) - A = 0x0080, O = 0x0100, ER = 0x0180, E = 0x0200, AI = 0x0280, EI = 0x0300, - AO = 0x0380, OU = 0x0400, AN = 0x0480, EN = 0x0500, ANG = 0x0580, - ENG = 0x0600, ERR = 0x0680, Tone1 = 0x0000, Tone2 = 0x0800, - Tone3 = 0x1000, Tone4 = 0x1800, Tone5 = 0x2000; - - protected: - Component syllable_; + return *this; + } + + uint16_t absoluteOrder() const { + // turn BPMF syllable into a 4*14*4*22 number + return (uint16_t)(syllable_ & ConsonantMask) + + (uint16_t)((syllable_ & MiddleVowelMask) >> 5) * 22 + + (uint16_t)((syllable_ & VowelMask) >> 7) * 22 * 4 + + (uint16_t)((syllable_ & ToneMarkerMask) >> 11) * 22 * 4 * 14; + } + + const std::string absoluteOrderString() const { + // 5*14*4*22 = 6160, we use a 79*79 encoding to represent that + uint16_t order = absoluteOrder(); + char low = 48 + static_cast(order % 79); + char high = 48 + static_cast(order / 79); + std::string result(2, ' '); + result[0] = low; + result[1] = high; + return result; + } + + static BopomofoSyllable FromAbsoluteOrder(uint16_t order) { + return BopomofoSyllable((order % 22) | ((order / 22) % 4) << 5 | + ((order / (22 * 4)) % 14) << 7 | + ((order / (22 * 4 * 14)) % 5) << 11); + } + + static BopomofoSyllable FromAbsoluteOrderString(const std::string& str) { + if (str.length() != 2) return BopomofoSyllable(); + + return FromAbsoluteOrder((uint16_t)(str[1] - 48) * 79 + + (uint16_t)(str[0] - 48)); + } + + friend std::ostream& operator<<(std::ostream& stream, + const BopomofoSyllable& syllable); + + static constexpr Component + ConsonantMask = 0x001f, // 0000 0000 0001 1111, 21 consonants + MiddleVowelMask = 0x0060, // 0000 0000 0110 0000, 3 middle vowels + VowelMask = 0x0780, // 0000 0111 1000 0000, 13 vowels + ToneMarkerMask = 0x3800, // 0011 1000 0000 0000, 5 tones (tone1 = 0x00) + B = 0x0001, P = 0x0002, M = 0x0003, F = 0x0004, D = 0x0005, T = 0x0006, + N = 0x0007, L = 0x0008, G = 0x0009, K = 0x000a, H = 0x000b, J = 0x000c, + Q = 0x000d, X = 0x000e, ZH = 0x000f, CH = 0x0010, SH = 0x0011, R = 0x0012, + Z = 0x0013, C = 0x0014, S = 0x0015, I = 0x0020, U = 0x0040, + UE = 0x0060, // ue = u umlaut (we use the German convention here as an + // ersatz to the /ju:/ sound) + A = 0x0080, O = 0x0100, ER = 0x0180, E = 0x0200, AI = 0x0280, EI = 0x0300, + AO = 0x0380, OU = 0x0400, AN = 0x0480, EN = 0x0500, ANG = 0x0580, + ENG = 0x0600, ERR = 0x0680, Tone1 = 0x0000, Tone2 = 0x0800, + Tone3 = 0x1000, Tone4 = 0x1800, Tone5 = 0x2000; + +protected: + Component syllable_; }; inline std::ostream& operator<<(std::ostream& stream, const BopomofoSyllable& syllable) { - stream << syllable.composedString(); - return stream; + stream << syllable.composedString(); + return stream; } typedef BopomofoSyllable BPMF; @@ -207,309 +207,309 @@ typedef std::map > BopomofoKeyToComponentMap; typedef std::map BopomofoComponentToKeyMap; class BopomofoKeyboardLayout { - public: - static const BopomofoKeyboardLayout* StandardLayout(); - static const BopomofoKeyboardLayout* ETenLayout(); - static const BopomofoKeyboardLayout* HsuLayout(); - static const BopomofoKeyboardLayout* ETen26Layout(); - static const BopomofoKeyboardLayout* IBMLayout(); - static const BopomofoKeyboardLayout* HanyuPinyinLayout(); - - BopomofoKeyboardLayout(const BopomofoKeyToComponentMap& ktcm, - const std::string& name) - : m_keyToComponent(ktcm), m_name(name) { - for (BopomofoKeyToComponentMap::const_iterator miter = +public: + static const BopomofoKeyboardLayout* StandardLayout(); + static const BopomofoKeyboardLayout* ETenLayout(); + static const BopomofoKeyboardLayout* HsuLayout(); + static const BopomofoKeyboardLayout* ETen26Layout(); + static const BopomofoKeyboardLayout* IBMLayout(); + static const BopomofoKeyboardLayout* MiTACLayout(); + static const BopomofoKeyboardLayout* HanyuPinyinLayout(); + + BopomofoKeyboardLayout(const BopomofoKeyToComponentMap& ktcm, + const std::string& name) + : m_keyToComponent(ktcm), m_name(name) { + for (BopomofoKeyToComponentMap::const_iterator miter = m_keyToComponent.begin(); - miter != m_keyToComponent.end(); ++miter) - for (std::vector::const_iterator viter = - (*miter).second.begin(); - viter != (*miter).second.end(); ++viter) - m_componentToKey[*viter] = (*miter).first; - } - - const std::string name() const { return m_name; } - - char componentToKey(BPMF::Component component) const { - BopomofoComponentToKeyMap::const_iterator iter = + miter != m_keyToComponent.end(); ++miter) + for (std::vector::const_iterator viter = + (*miter).second.begin(); + viter != (*miter).second.end(); ++viter) + m_componentToKey[*viter] = (*miter).first; + } + + const std::string name() const { return m_name; } + + char componentToKey(BPMF::Component component) const { + BopomofoComponentToKeyMap::const_iterator iter = m_componentToKey.find(component); - return (iter == m_componentToKey.end()) ? 0 : (*iter).second; - } - - const std::vector keyToComponents(char key) const { - BopomofoKeyToComponentMap::const_iterator iter = m_keyToComponent.find(key); - return (iter == m_keyToComponent.end()) ? std::vector() - : (*iter).second; - } - - const std::string keySequenceFromSyllable(BPMF syllable) const { - std::string sequence; - - BPMF::Component c; - char k; + return (iter == m_componentToKey.end()) ? 0 : (*iter).second; + } + + const std::vector keyToComponents(char key) const { + BopomofoKeyToComponentMap::const_iterator iter = m_keyToComponent.find(key); + return (iter == m_keyToComponent.end()) ? std::vector() + : (*iter).second; + } + + const std::string keySequenceFromSyllable(BPMF syllable) const { + std::string sequence; + + BPMF::Component c; + char k; #define STKS_COMBINE(component) \ - if ((c = component)) { \ - if ((k = componentToKey(c))) sequence += std::string(1, k); \ - } - STKS_COMBINE(syllable.consonantComponent()); - STKS_COMBINE(syllable.middleVowelComponent()); - STKS_COMBINE(syllable.vowelComponent()); - STKS_COMBINE(syllable.toneMarkerComponent()); +if ((c = component)) { \ +if ((k = componentToKey(c))) sequence += std::string(1, k); \ +} + STKS_COMBINE(syllable.consonantComponent()); + STKS_COMBINE(syllable.middleVowelComponent()); + STKS_COMBINE(syllable.vowelComponent()); + STKS_COMBINE(syllable.toneMarkerComponent()); #undef STKS_COMBINE - return sequence; - } - - const BPMF syllableFromKeySequence(const std::string& sequence) const { - BPMF syllable; - - for (std::string::const_iterator iter = sequence.begin(); - iter != sequence.end(); ++iter) { - bool beforeSeqHasIorUE = sequenceContainsIorUE(sequence.begin(), iter); - bool aheadSeqHasIorUE = sequenceContainsIorUE(iter + 1, sequence.end()); - - std::vector components = keyToComponents(*iter); - - if (!components.size()) continue; - - if (components.size() == 1) { - syllable += BPMF(components[0]); - continue; - } - - BPMF head = BPMF(components[0]); - BPMF follow = BPMF(components[1]); - BPMF ending = components.size() > 2 ? BPMF(components[2]) : follow; - - // apply the I/UE + E rule - if (head.vowelComponent() == BPMF::E && - follow.vowelComponent() != BPMF::E) { - syllable += beforeSeqHasIorUE ? head : follow; - continue; - } - - if (head.vowelComponent() != BPMF::E && - follow.vowelComponent() == BPMF::E) { - syllable += beforeSeqHasIorUE ? follow : head; - continue; - } - - // apply the J/Q/X + I/UE rule, only two components are allowed in the - // components vector here - if (head.belongsToJQXClass() && !follow.belongsToJQXClass()) { - if (!syllable.isEmpty()) { - if (ending != follow) syllable += ending; - } else { - syllable += aheadSeqHasIorUE ? head : follow; - } - - continue; - } - - if (!head.belongsToJQXClass() && follow.belongsToJQXClass()) { - if (!syllable.isEmpty()) { - if (ending != follow) syllable += ending; - } else { - syllable += aheadSeqHasIorUE ? follow : head; - } - - continue; - } - - // the nasty issue of only one char in the buffer - if (iter == sequence.begin() && iter + 1 == sequence.end()) { - if (head.hasVowel() || follow.hasToneMarker() || - head.belongsToZCSRClass()) { - syllable += head; - } else { - if (follow.hasVowel() || ending.hasToneMarker()) { - syllable += follow; - } else { - syllable += ending; - } - } - - continue; - } - - if (!(syllable.maskType() & head.maskType()) && - !endAheadOrAheadHasToneMarkKey(iter + 1, sequence.end())) { - syllable += head; - } else { - if (endAheadOrAheadHasToneMarkKey(iter + 1, sequence.end()) && - head.belongsToZCSRClass() && syllable.isEmpty()) { - syllable += head; - } else if (syllable.maskType() < follow.maskType()) { - syllable += follow; - } else { - syllable += ending; - } - } + return sequence; } - - // heuristics for Hsu keyboard layout - if (this == HsuLayout()) { - // fix the left out L to ERR when it has sound, and GI, GUE -> JI, JUE - if (syllable.vowelComponent() == BPMF::ENG && !syllable.hasConsonant() && - !syllable.hasMiddleVowel()) { - syllable += BPMF(BPMF::ERR); - } else if (syllable.consonantComponent() == BPMF::G && - (syllable.middleVowelComponent() == BPMF::I || - syllable.middleVowelComponent() == BPMF::UE)) { - syllable += BPMF(BPMF::J); - } + + const BPMF syllableFromKeySequence(const std::string& sequence) const { + BPMF syllable; + + for (std::string::const_iterator iter = sequence.begin(); + iter != sequence.end(); ++iter) { + bool beforeSeqHasIorUE = sequenceContainsIorUE(sequence.begin(), iter); + bool aheadSeqHasIorUE = sequenceContainsIorUE(iter + 1, sequence.end()); + + std::vector components = keyToComponents(*iter); + + if (!components.size()) continue; + + if (components.size() == 1) { + syllable += BPMF(components[0]); + continue; + } + + BPMF head = BPMF(components[0]); + BPMF follow = BPMF(components[1]); + BPMF ending = components.size() > 2 ? BPMF(components[2]) : follow; + + // apply the I/UE + E rule + if (head.vowelComponent() == BPMF::E && + follow.vowelComponent() != BPMF::E) { + syllable += beforeSeqHasIorUE ? head : follow; + continue; + } + + if (head.vowelComponent() != BPMF::E && + follow.vowelComponent() == BPMF::E) { + syllable += beforeSeqHasIorUE ? follow : head; + continue; + } + + // apply the J/Q/X + I/UE rule, only two components are allowed in the + // components vector here + if (head.belongsToJQXClass() && !follow.belongsToJQXClass()) { + if (!syllable.isEmpty()) { + if (ending != follow) syllable += ending; + } else { + syllable += aheadSeqHasIorUE ? head : follow; + } + + continue; + } + + if (!head.belongsToJQXClass() && follow.belongsToJQXClass()) { + if (!syllable.isEmpty()) { + if (ending != follow) syllable += ending; + } else { + syllable += aheadSeqHasIorUE ? follow : head; + } + + continue; + } + + // the nasty issue of only one char in the buffer + if (iter == sequence.begin() && iter + 1 == sequence.end()) { + if (head.hasVowel() || follow.hasToneMarker() || + head.belongsToZCSRClass()) { + syllable += head; + } else { + if (follow.hasVowel() || ending.hasToneMarker()) { + syllable += follow; + } else { + syllable += ending; + } + } + + continue; + } + + if (!(syllable.maskType() & head.maskType()) && + !endAheadOrAheadHasToneMarkKey(iter + 1, sequence.end())) { + syllable += head; + } else { + if (endAheadOrAheadHasToneMarkKey(iter + 1, sequence.end()) && + head.belongsToZCSRClass() && syllable.isEmpty()) { + syllable += head; + } else if (syllable.maskType() < follow.maskType()) { + syllable += follow; + } else { + syllable += ending; + } + } + } + + // heuristics for Hsu keyboard layout + if (this == HsuLayout()) { + // fix the left out L to ERR when it has sound, and GI, GUE -> JI, JUE + if (syllable.vowelComponent() == BPMF::ENG && !syllable.hasConsonant() && + !syllable.hasMiddleVowel()) { + syllable += BPMF(BPMF::ERR); + } else if (syllable.consonantComponent() == BPMF::G && + (syllable.middleVowelComponent() == BPMF::I || + syllable.middleVowelComponent() == BPMF::UE)) { + syllable += BPMF(BPMF::J); + } + } + + return syllable; } - - return syllable; - } - - protected: - bool endAheadOrAheadHasToneMarkKey(std::string::const_iterator ahead, - std::string::const_iterator end) const { - if (ahead == end) return true; - - char tone1 = componentToKey(BPMF::Tone1); - char tone2 = componentToKey(BPMF::Tone2); - char tone3 = componentToKey(BPMF::Tone3); - char tone4 = componentToKey(BPMF::Tone4); - char tone5 = componentToKey(BPMF::Tone5); - - if (tone1) - if (*ahead == tone1) return true; - - if (*ahead == tone2 || *ahead == tone3 || *ahead == tone4 || - *ahead == tone5) - return true; - - return false; - } - - bool sequenceContainsIorUE(std::string::const_iterator start, - std::string::const_iterator end) const { - char iChar = componentToKey(BPMF::I); - char ueChar = componentToKey(BPMF::UE); - - for (; start != end; ++start) - if (*start == iChar || *start == ueChar) return true; - return false; - } - - std::string m_name; - BopomofoKeyToComponentMap m_keyToComponent; - BopomofoComponentToKeyMap m_componentToKey; + +protected: + bool endAheadOrAheadHasToneMarkKey(std::string::const_iterator ahead, + std::string::const_iterator end) const { + if (ahead == end) return true; + + char tone1 = componentToKey(BPMF::Tone1); + char tone2 = componentToKey(BPMF::Tone2); + char tone3 = componentToKey(BPMF::Tone3); + char tone4 = componentToKey(BPMF::Tone4); + char tone5 = componentToKey(BPMF::Tone5); + + if (tone1) + if (*ahead == tone1) return true; + + if (*ahead == tone2 || *ahead == tone3 || *ahead == tone4 || + *ahead == tone5) + return true; + + return false; + } + + bool sequenceContainsIorUE(std::string::const_iterator start, + std::string::const_iterator end) const { + char iChar = componentToKey(BPMF::I); + char ueChar = componentToKey(BPMF::UE); + + for (; start != end; ++start) + if (*start == iChar || *start == ueChar) return true; + return false; + } + + std::string m_name; + BopomofoKeyToComponentMap m_keyToComponent; + BopomofoComponentToKeyMap m_componentToKey; }; class BopomofoReadingBuffer { - public: - explicit BopomofoReadingBuffer(const BopomofoKeyboardLayout* layout) - : layout_(layout), pinyin_mode_(false) { - if (layout == BopomofoKeyboardLayout::HanyuPinyinLayout()) { - pinyin_mode_ = true; - pinyin_sequence_ = ""; - } - } - - void setKeyboardLayout(const BopomofoKeyboardLayout* layout) { - layout_ = layout; - - if (layout == BopomofoKeyboardLayout::HanyuPinyinLayout()) { - pinyin_mode_ = true; - pinyin_sequence_ = ""; - } - } - - bool isValidKey(char k) const { - if (!pinyin_mode_) { - return layout_ ? (layout_->keyToComponents(k)).size() > 0 : false; - } - - char lk = tolower(k); - if (lk >= 'a' && lk <= 'z') { - // if a tone marker is already in place - if (pinyin_sequence_.length()) { - char lastc = pinyin_sequence_[pinyin_sequence_.length() - 1]; - if (lastc >= '2' && lastc <= '5') { - return false; +public: + explicit BopomofoReadingBuffer(const BopomofoKeyboardLayout* layout) + : layout_(layout), pinyin_mode_(false) { + if (layout == BopomofoKeyboardLayout::HanyuPinyinLayout()) { + pinyin_mode_ = true; + pinyin_sequence_ = ""; } - return true; - } - return true; } - - if (pinyin_sequence_.length() && (lk >= '2' && lk <= '5')) { - return true; + + void setKeyboardLayout(const BopomofoKeyboardLayout* layout) { + layout_ = layout; + + if (layout == BopomofoKeyboardLayout::HanyuPinyinLayout()) { + pinyin_mode_ = true; + pinyin_sequence_ = ""; + } } - - return false; - } - - bool combineKey(char k) { - if (!isValidKey(k)) return false; - - if (pinyin_mode_) { - pinyin_sequence_ += std::string(1, tolower(k)); - syllable_ = BPMF::FromHanyuPinyin(pinyin_sequence_); - return true; + + bool isValidKey(char k) const { + if (!pinyin_mode_) { + return layout_ ? (layout_->keyToComponents(k)).size() > 0 : false; + } + + char lk = tolower(k); + if (lk >= 'a' && lk <= 'z') { + // if a tone marker is already in place + if (pinyin_sequence_.length()) { + char lastc = pinyin_sequence_[pinyin_sequence_.length() - 1]; + if (lastc >= '2' && lastc <= '5') { + return false; + } + return true; + } + return true; + } + + if (pinyin_sequence_.length() && (lk >= '2' && lk <= '5')) { + return true; + } + + return false; } - - std::string sequence = + + bool combineKey(char k) { + if (!isValidKey(k)) return false; + + if (pinyin_mode_) { + pinyin_sequence_ += std::string(1, tolower(k)); + syllable_ = BPMF::FromHanyuPinyin(pinyin_sequence_); + return true; + } + + std::string sequence = layout_->keySequenceFromSyllable(syllable_) + std::string(1, k); - syllable_ = layout_->syllableFromKeySequence(sequence); - return true; - } - - void clear() { - pinyin_sequence_.clear(); - syllable_.clear(); - } - - void backspace() { - if (!layout_) return; - - if (pinyin_mode_) { - if (pinyin_sequence_.length()) { - pinyin_sequence_ = - pinyin_sequence_.substr(0, pinyin_sequence_.length() - 1); - } - - syllable_ = BPMF::FromHanyuPinyin(pinyin_sequence_); - return; + syllable_ = layout_->syllableFromKeySequence(sequence); + return true; } - - std::string sequence = layout_->keySequenceFromSyllable(syllable_); - if (sequence.length()) { - sequence = sequence.substr(0, sequence.length() - 1); - syllable_ = layout_->syllableFromKeySequence(sequence); + + void clear() { + pinyin_sequence_.clear(); + syllable_.clear(); } - } - - bool isEmpty() const { return syllable_.isEmpty(); } - - const std::string composedString() const { - if (pinyin_mode_) { - return pinyin_sequence_; + + void backspace() { + if (!layout_) return; + + if (pinyin_mode_) { + if (pinyin_sequence_.length()) { + pinyin_sequence_ = + pinyin_sequence_.substr(0, pinyin_sequence_.length() - 1); + } + + syllable_ = BPMF::FromHanyuPinyin(pinyin_sequence_); + return; + } + + std::string sequence = layout_->keySequenceFromSyllable(syllable_); + if (sequence.length()) { + sequence = sequence.substr(0, sequence.length() - 1); + syllable_ = layout_->syllableFromKeySequence(sequence); + } } - - return syllable_.composedString(); - } - - const BPMF syllable() const { return syllable_; } - - const std::string standardLayoutQueryString() const { - return BopomofoKeyboardLayout::StandardLayout()->keySequenceFromSyllable( - syllable_); - } - - const std::string absoluteOrderQueryString() const { - return syllable_.absoluteOrderString(); - } - - bool hasToneMarker() const { return syllable_.hasToneMarker(); } - - protected: - const BopomofoKeyboardLayout* layout_; - BPMF syllable_; - - bool pinyin_mode_; - std::string pinyin_sequence_; + + bool isEmpty() const { return syllable_.isEmpty(); } + + const std::string composedString() const { + if (pinyin_mode_) { + return pinyin_sequence_; + } + + return syllable_.composedString(); + } + + const BPMF syllable() const { return syllable_; } + + const std::string standardLayoutQueryString() const { + return BopomofoKeyboardLayout::StandardLayout()->keySequenceFromSyllable(syllable_); + } + + const std::string absoluteOrderQueryString() const { + return syllable_.absoluteOrderString(); + } + + bool hasToneMarker() const { return syllable_.hasToneMarker(); } + +protected: + const BopomofoKeyboardLayout* layout_; + BPMF syllable_; + + bool pinyin_mode_; + std::string pinyin_sequence_; }; } // namespace Mandarin } // namespace Taiyan diff --git a/Source/Modules/ControllerModules/InputState.swift b/Source/Modules/ControllerModules/InputState.swift index 6bafd8b3..94f37529 100644 --- a/Source/Modules/ControllerModules/InputState.swift +++ b/Source/Modules/ControllerModules/InputState.swift @@ -343,22 +343,38 @@ class InputState: NSObject { super.init() } + @objc static let catCommonSymbols = String(format: NSLocalizedString("catCommonSymbols", comment: "")) + @objc static let catHoriBrackets = String(format: NSLocalizedString("catHoriBrackets", comment: "")) + @objc static let catVertBrackets = String(format: NSLocalizedString("catVertBrackets", comment: "")) + @objc static let catGreekLetters = String(format: NSLocalizedString("catGreekLetters", comment: "")) + @objc static let catMathSymbols = String(format: NSLocalizedString("catMathSymbols", comment: "")) + @objc static let catCurrencyUnits = String(format: NSLocalizedString("catCurrencyUnits", comment: "")) + @objc static let catSpecialSymbols = String(format: NSLocalizedString("catSpecialSymbols", comment: "")) + @objc static let catUnicodeSymbols = String(format: NSLocalizedString("catUnicodeSymbols", comment: "")) + @objc static let catCircledKanjis = String(format: NSLocalizedString("catCircledKanjis", comment: "")) + @objc static let catCircledKataKana = String(format: NSLocalizedString("catCircledKataKana", comment: "")) + @objc static let catBracketKanjis = String(format: NSLocalizedString("catBracketKanjis", comment: "")) + @objc static let catSingleTableLines = String(format: NSLocalizedString("catSingleTableLines", comment: "")) + @objc static let catDoubleTableLines = String(format: NSLocalizedString("catDoubleTableLines", comment: "")) + @objc static let catFillingBlocks = String(format: NSLocalizedString("catFillingBlocks", comment: "")) + @objc static let catLineSegments = String(format: NSLocalizedString("catLineSegments", comment: "")) + @objc static let root: SymbolNode = SymbolNode("/", [ SymbolNode("`"), - SymbolNode("常用", symbols:",、。.?!;:‧‥﹐﹒˙·‘’“”〝〞‵′〃~$%@&#*"), - SymbolNode("橫括", symbols:"()「」〔〕{}〈〉『』《》【】﹙﹚﹝﹞﹛﹜"), - SymbolNode("縱括", symbols:"︵︶﹁﹂︹︺︷︸︿﹀﹃﹄︽︾︻︼"), - SymbolNode("希臘", symbols:"αβγδεζηθικλμνξοπρστυφχψωΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ"), - SymbolNode("數學", symbols:"+-×÷=≠≒∞±√<>﹤﹥≦≧∩∪ˇ⊥∠∟⊿㏒㏑∫∮∵∴╳﹢"), - SymbolNode("貨幣", symbols:"$€¥¢£₽₨₩฿₺₮₱₭₴₦৲৳૱௹﷼₹₲₪₡₫៛₵₢₸₤₳₥₠₣₰₧₯₶₷"), - SymbolNode("特殊", symbols:"↑↓←→↖↗↙↘↺⇧⇩⇦⇨⇄⇆⇅⇵↻◎○●⊕⊙※△▲☆★◇◆□■▽▼§¥〒¢£♀♂↯"), - SymbolNode("萬國", symbols:"♨☀☁☂☃♠♥♣♦♩♪♫♬☺☻"), - SymbolNode("圈字", symbols:"㊟㊞㊚㊛㊊㊋㊌㊍㊎㊏㊐㊑㊒㊓㊔㊕㊖㊗︎㊘㊙︎㊜㊝㊠㊡㊢㊣㊤㊥㊦㊧㊨㊩㊪㊫㊬㊭㊮㊯㊰🈚︎🈯︎"), - SymbolNode("圈假", symbols:"㋐㋑㋒㋓㋔㋕㋖㋗㋘㋙㋚㋛㋜㋝㋞㋟㋠㋡㋢㋣㋤㋥㋦㋧㋨㋩㋪㋫㋬㋭㋮㋯㋰㋱㋲㋳㋴㋵㋶㋷㋸㋹㋺㋻㋼㋾"), - SymbolNode("括字", symbols:"㈪㈫㈬㈭㈮㈯㈰㈱㈲㈳㈴㈵㈶㈷㈸㈹㈺㈻㈼㈽㈾㈿㉀㉁㉂㉃"), - SymbolNode("單線", symbols:"├─┼┴┬┤┌┐╞═╪╡│▕└┘╭╮╰╯"), - SymbolNode("雙線", symbols:"╔╦╗╠═╬╣╓╥╖╒╤╕║╚╩╝╟╫╢╙╨╜╞╪╡╘╧╛"), - SymbolNode("填色", symbols:"_ˍ▁▂▃▄▅▆▇█▏▎▍▌▋▊▉◢◣◥◤"), - SymbolNode("線段", symbols:"﹣﹦≡|∣∥–︱—︳╴¯ ̄﹉﹊﹍﹎﹋﹌﹏︴∕﹨╱╲/\"), + SymbolNode(catCommonSymbols, symbols:",、。.?!;:‧‥﹐﹒˙·‘’“”〝〞‵′〃~$%@&#*"), + SymbolNode(catHoriBrackets, symbols:"()「」〔〕{}〈〉『』《》【】﹙﹚﹝﹞﹛﹜"), + SymbolNode(catVertBrackets, symbols:"︵︶﹁﹂︹︺︷︸︿﹀﹃﹄︽︾︻︼"), + SymbolNode(catGreekLetters, symbols:"αβγδεζηθικλμνξοπρστυφχψωΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ"), + SymbolNode(catMathSymbols, symbols:"+-×÷=≠≒∞±√<>﹤﹥≦≧∩∪ˇ⊥∠∟⊿㏒㏑∫∮∵∴╳﹢"), + SymbolNode(catCurrencyUnits, symbols:"$€¥¢£₽₨₩฿₺₮₱₭₴₦৲৳૱௹﷼₹₲₪₡₫៛₵₢₸₤₳₥₠₣₰₧₯₶₷"), + SymbolNode(catSpecialSymbols, symbols:"↑↓←→↖↗↙↘↺⇧⇩⇦⇨⇄⇆⇅⇵↻◎○●⊕⊙※△▲☆★◇◆□■▽▼§¥〒¢£♀♂↯"), + SymbolNode(catUnicodeSymbols, symbols:"♨☀☁☂☃♠♥♣♦♩♪♫♬☺☻"), + SymbolNode(catCircledKanjis, symbols:"㊟㊞㊚㊛㊊㊋㊌㊍㊎㊏㊐㊑㊒㊓㊔㊕㊖㊗︎㊘㊙︎㊜㊝㊠㊡㊢㊣㊤㊥㊦㊧㊨㊩㊪㊫㊬㊭㊮㊯㊰🈚︎🈯︎"), + SymbolNode(catCircledKataKana, symbols:"㋐㋑㋒㋓㋔㋕㋖㋗㋘㋙㋚㋛㋜㋝㋞㋟㋠㋡㋢㋣㋤㋥㋦㋧㋨㋩㋪㋫㋬㋭㋮㋯㋰㋱㋲㋳㋴㋵㋶㋷㋸㋹㋺㋻㋼㋾"), + SymbolNode(catBracketKanjis, symbols:"㈪㈫㈬㈭㈮㈯㈰㈱㈲㈳㈴㈵㈶㈷㈸㈹㈺㈻㈼㈽㈾㈿㉀㉁㉂㉃"), + SymbolNode(catSingleTableLines, symbols:"├─┼┴┬┤┌┐╞═╪╡│▕└┘╭╮╰╯"), + SymbolNode(catDoubleTableLines, symbols:"╔╦╗╠═╬╣╓╥╖╒╤╕║╚╩╝╟╫╢╙╨╜╞╪╡╘╧╛"), + SymbolNode(catFillingBlocks, symbols:"_ˍ▁▂▃▄▅▆▇█▏▎▍▌▋▊▉◢◣◥◤"), + SymbolNode(catLineSegments, symbols:"﹣﹦≡|∣∥–︱—︳╴¯ ̄﹉﹊﹍﹎﹋﹌﹏︴∕﹨╱╲/\"), ]) } diff --git a/Source/Modules/ControllerModules/KeyHandler.mm b/Source/Modules/ControllerModules/KeyHandler.mm index b7df4231..6adc3665 100644 --- a/Source/Modules/ControllerModules/KeyHandler.mm +++ b/Source/Modules/ControllerModules/KeyHandler.mm @@ -179,12 +179,15 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot"; case KeyboardLayoutEten26: _bpmfReadingBuffer->setKeyboardLayout(BopomofoKeyboardLayout::ETen26Layout()); break; - case KeyboardLayoutHanyuPinyin: - _bpmfReadingBuffer->setKeyboardLayout(BopomofoKeyboardLayout::HanyuPinyinLayout()); - break; case KeyboardLayoutIBM: _bpmfReadingBuffer->setKeyboardLayout(BopomofoKeyboardLayout::IBMLayout()); break; + case KeyboardLayoutMiTAC: + _bpmfReadingBuffer->setKeyboardLayout(BopomofoKeyboardLayout::MiTACLayout()); + break; + case KeyboardLayoutHanyuPinyin: + _bpmfReadingBuffer->setKeyboardLayout(BopomofoKeyboardLayout::HanyuPinyinLayout()); + break; default: _bpmfReadingBuffer->setKeyboardLayout(BopomofoKeyboardLayout::StandardLayout()); Preferences.keyboardLayout = KeyboardLayoutStandard; diff --git a/Source/Modules/IMEModules/PreferencesModule.swift b/Source/Modules/IMEModules/PreferencesModule.swift index 6f109c82..f81ddd3a 100644 --- a/Source/Modules/IMEModules/PreferencesModule.swift +++ b/Source/Modules/IMEModules/PreferencesModule.swift @@ -154,9 +154,10 @@ struct ComposingBufferSize { case eten = 1 case hsu = 2 case eten26 = 3 - case hanyuPinyin = 4 - case IBM = 5 - + case IBM = 4 + case MiTAC = 5 + case hanyuPinyin = 10 + var name: String { switch (self) { case .standard: @@ -167,10 +168,12 @@ struct ComposingBufferSize { return "Hsu" case .eten26: return "ETen26" - case .hanyuPinyin: - return "HanyuPinyin" case .IBM: return "IBM" + case .MiTAC: + return "MiTAC" + case .hanyuPinyin: + return "HanyuPinyin" } } } @@ -381,7 +384,7 @@ struct ComposingBufferSize { return useSCPCTypingMode } - @UserDefault(key: kMaxCandidateLength, defaultValue: 10) + @UserDefault(key: kMaxCandidateLength, defaultValue: kDefaultComposingBufferSize * 2) @objc static var maxCandidateLength: Int @UserDefault(key: kShouldNotFartInLieuOfBeep, defaultValue: true) diff --git a/Source/Resources/Base.lproj/Localizable.strings b/Source/Resources/Base.lproj/Localizable.strings index c90c43f8..30b77319 100644 --- a/Source/Resources/Base.lproj/Localizable.strings +++ b/Source/Resources/Base.lproj/Localizable.strings @@ -47,3 +47,20 @@ "zh-Hant" = "Traditional Chinese"; "ja" = "Japanese"; "Apple Zhuyin Bopomofo" = "Apple Zhuyin Bopomofo"; + +// The followings are the category names used in the Symbol menu. +"catCommonSymbols" = "CommonSymbols"; +"catHoriBrackets" = "HorizontalBrackets"; +"catVertBrackets" = "VerticalBrackets"; +"catGreekLetters" = "GreekLetters"; +"catMathSymbols" = "MathSymbols"; +"catCurrencyUnits" = "CurrencyUnits"; +"catSpecialSymbols" = "SpecialSymbols"; +"catUnicodeSymbols" = "UnicodeSymbols"; +"catCircledKanjis" = "CircledKanjis"; +"catCircledKataKana" = "CircledKataKana"; +"catBracketKanjis" = "BracketKanjis"; +"catSingleTableLines" = "SingleTableLines"; +"catDoubleTableLines" = "DoubleTableLines"; +"catFillingBlocks" = "FillingBlocks"; +"catLineSegments" = "LineSegments"; diff --git a/Source/Resources/en.lproj/Localizable.strings b/Source/Resources/en.lproj/Localizable.strings index c90c43f8..cbdb3f0e 100644 --- a/Source/Resources/en.lproj/Localizable.strings +++ b/Source/Resources/en.lproj/Localizable.strings @@ -47,3 +47,20 @@ "zh-Hant" = "Traditional Chinese"; "ja" = "Japanese"; "Apple Zhuyin Bopomofo" = "Apple Zhuyin Bopomofo"; + +// The followings are the category names used in the Symbol menu. +"catCommonSymbols" = "CommonSymbols"; +"catHoriBrackets" = "HoriBrackets"; +"catVertBrackets" = "VertBrackets"; +"catGreekLetters" = "GreekLetters"; +"catMathSymbols" = "MathSymbols"; +"catCurrencyUnits" = "CurrencyUnits"; +"catSpecialSymbols" = "SpecialSymbols"; +"catUnicodeSymbols" = "UnicodeSymbols"; +"catCircledKanjis" = "CircledKanjis"; +"catCircledKataKana" = "CircledKataKana"; +"catBracketKanjis" = "BracketKanjis"; +"catSingleTableLines" = "SingleTableLines"; +"catDoubleTableLines" = "DoubleTableLines"; +"catFillingBlocks" = "FillingBlocks"; +"catLineSegments" = "LineSegments"; diff --git a/Source/Resources/ja.lproj/Localizable.strings b/Source/Resources/ja.lproj/Localizable.strings index a7726e5d..0737caca 100644 --- a/Source/Resources/ja.lproj/Localizable.strings +++ b/Source/Resources/ja.lproj/Localizable.strings @@ -47,3 +47,20 @@ "zh-Hant" = "繁體中国語"; "ja" = "和語"; "Apple Zhuyin Bopomofo" = "Apple 注音ボポモフォ配列"; + +// The followings are the category names used in the Symbol menu. +"catCommonSymbols" = "常用"; +"catHoriBrackets" = "横括"; +"catVertBrackets" = "縦括"; +"catGreekLetters" = "ギリシャ"; +"catMathSymbols" = "数学"; +"catCurrencyUnits" = "貨幣"; +"catSpecialSymbols" = "特殊"; +"catUnicodeSymbols" = "Unicode"; +"catCircledKanjis" = "丸付漢字"; +"catCircledKataKana" = "丸付仮名"; +"catBracketKanjis" = "括付漢字"; +"catSingleTableLines" = "単線"; +"catDoubleTableLines" = "双線"; +"catFillingBlocks" = "ブロック"; +"catLineSegments" = "線分"; diff --git a/Source/Resources/zh-Hans.lproj/Localizable.strings b/Source/Resources/zh-Hans.lproj/Localizable.strings index d913aa74..99908093 100644 --- a/Source/Resources/zh-Hans.lproj/Localizable.strings +++ b/Source/Resources/zh-Hans.lproj/Localizable.strings @@ -47,3 +47,20 @@ "zh-Hant" = "繁体中文"; "ja" = "和文"; "Apple Zhuyin Bopomofo" = "Apple 注音键盘布局"; + +// The followings are the category names used in the Symbol menu. +"catCommonSymbols" = "常用"; +"catHoriBrackets" = "横括"; +"catVertBrackets" = "纵括"; +"catGreekLetters" = "希腊"; +"catMathSymbols" = "数学"; +"catCurrencyUnits" = "货币"; +"catSpecialSymbols" = "特殊"; +"catUnicodeSymbols" = "万国"; +"catCircledKanjis" = "圈字"; +"catCircledKataKana" = "圈假"; +"catBracketKanjis" = "括字"; +"catSingleTableLines" = "单线"; +"catDoubleTableLines" = "双线"; +"catFillingBlocks" = "填色"; +"catLineSegments" = "线段"; diff --git a/Source/Resources/zh-Hant.lproj/Localizable.strings b/Source/Resources/zh-Hant.lproj/Localizable.strings index 8041c5b7..de536115 100644 --- a/Source/Resources/zh-Hant.lproj/Localizable.strings +++ b/Source/Resources/zh-Hant.lproj/Localizable.strings @@ -47,3 +47,20 @@ "zh-Hant" = "繁體中文"; "ja" = "和文"; "Apple Zhuyin Bopomofo" = "Apple 注音鍵盤佈局"; + +// The followings are the category names used in the Symbol menu. +"catCommonSymbols" = "常用"; +"catHoriBrackets" = "橫括"; +"catVertBrackets" = "縱括"; +"catGreekLetters" = "希臘"; +"catMathSymbols" = "數學"; +"catCurrencyUnits" = "貨幣"; +"catSpecialSymbols" = "特殊"; +"catUnicodeSymbols" = "萬國"; +"catCircledKanjis" = "圈字"; +"catCircledKataKana" = "圈假"; +"catBracketKanjis" = "括字"; +"catSingleTableLines" = "單線"; +"catDoubleTableLines" = "雙線"; +"catFillingBlocks" = "填色"; +"catLineSegments" = "線段"; diff --git a/Source/WindowControllers/ctlPrefWindow.swift b/Source/WindowControllers/ctlPrefWindow.swift index 2efaceea..aa93d365 100644 --- a/Source/WindowControllers/ctlPrefWindow.swift +++ b/Source/WindowControllers/ctlPrefWindow.swift @@ -36,13 +36,12 @@ extension RangeReplaceableCollection where Element: Hashable { @IBOutlet weak var uiLanguageButton: NSPopUpButton! @IBOutlet weak var basisKeyboardLayoutButton: NSPopUpButton! @IBOutlet weak var selectionKeyComboBox: NSComboBox! - @IBOutlet weak var clickedWhetherIMEShouldNotFartToggle: NSButton! var currentLanguageSelectItem: NSMenuItem? = nil override func awakeFromNib() { let languages = ["auto", "en", "zh-Hans", "zh-Hant", "ja"] - var autoSelectItem: NSMenuItem? = nil + var autoMUISelectItem: NSMenuItem? = nil var chosenLanguageItem: NSMenuItem? = nil uiLanguageButton.menu?.removeAllItems() @@ -53,7 +52,7 @@ extension RangeReplaceableCollection where Element: Hashable { menuItem.representedObject = language if language == "auto" { - autoSelectItem = menuItem + autoMUISelectItem = menuItem } if !appleLanguages.isEmpty { @@ -64,12 +63,12 @@ extension RangeReplaceableCollection where Element: Hashable { uiLanguageButton.menu?.addItem(menuItem) } - currentLanguageSelectItem = chosenLanguageItem ?? autoSelectItem + currentLanguageSelectItem = chosenLanguageItem ?? autoMUISelectItem uiLanguageButton.select(currentLanguageSelectItem) let list = TISCreateInputSourceList(nil, true).takeRetainedValue() as! [TISInputSource] var usKeyboardLayoutItem: NSMenuItem? = nil - var chosenItem: NSMenuItem? = nil + var chosenBaseKeyboardLayoutItem: NSMenuItem? = nil basisKeyboardLayoutButton.menu?.removeAllItems() @@ -128,7 +127,7 @@ extension RangeReplaceableCollection where Element: Hashable { usKeyboardLayoutItem = menuItem } if basisKeyboardLayoutID == sourceID { - chosenItem = menuItem + chosenBaseKeyboardLayoutItem = menuItem } basisKeyboardLayoutButton.menu?.addItem(menuItem) } @@ -137,8 +136,8 @@ extension RangeReplaceableCollection where Element: Hashable { menuItem.title = String(format: NSLocalizedString("Apple Zhuyin Bopomofo", comment: "")) menuItem.representedObject = String("com.apple.keylayout.ZhuyinBopomofo") basisKeyboardLayoutButton.menu?.addItem(menuItem) + basisKeyboardLayoutButton.select(chosenBaseKeyboardLayoutItem ?? usKeyboardLayoutItem) - basisKeyboardLayoutButton.select(chosenItem ?? usKeyboardLayoutItem) selectionKeyComboBox.usesDataSource = false selectionKeyComboBox.removeAllItems() selectionKeyComboBox.addItems(withObjectValues: Preferences.suggestedCandidateKeys) diff --git a/Source/WindowNIBs/Source/WindowNIBs/Base.lproj/frmPrefWindow.xib b/Source/WindowNIBs/Source/WindowNIBs/Base.lproj/frmPrefWindow.xib index 1688b160..08218d8b 100644 --- a/Source/WindowNIBs/Source/WindowNIBs/Base.lproj/frmPrefWindow.xib +++ b/Source/WindowNIBs/Source/WindowNIBs/Base.lproj/frmPrefWindow.xib @@ -262,7 +262,7 @@ - + @@ -594,8 +594,9 @@ - - + + + diff --git a/Source/WindowNIBs/Source/WindowNIBs/en.lproj/frmPrefWindow.strings b/Source/WindowNIBs/Source/WindowNIBs/en.lproj/frmPrefWindow.strings index 07f5f6e1..0eebc9c6 100644 --- a/Source/WindowNIBs/Source/WindowNIBs/en.lproj/frmPrefWindow.strings +++ b/Source/WindowNIBs/Source/WindowNIBs/en.lproj/frmPrefWindow.strings @@ -89,6 +89,9 @@ /* Class = "NSMenuItem"; title = "IBM"; ObjectID = "137"; */ "137.title" = "IBM"; +/* Class = "NSMenuItem"; title = "MiTAC"; ObjectID = "7fV-x8-WHQ"; */ +"7fV-x8-WHQ.title" = "MiTAC"; + /* Class = "NSTabViewItem"; label = "Keyboard"; ObjectID = "1AW-xf-c2f"; */ "1AW-xf-c2f.label" = "Keyboard"; diff --git a/Source/WindowNIBs/Source/WindowNIBs/ja.lproj/frmPrefWindow.strings b/Source/WindowNIBs/Source/WindowNIBs/ja.lproj/frmPrefWindow.strings index 175fb309..1bc1ba72 100644 --- a/Source/WindowNIBs/Source/WindowNIBs/ja.lproj/frmPrefWindow.strings +++ b/Source/WindowNIBs/Source/WindowNIBs/ja.lproj/frmPrefWindow.strings @@ -89,6 +89,9 @@ /* Class = "NSMenuItem"; title = "IBM"; ObjectID = "137"; */ "137.title" = "IBM"; +/* Class = "NSMenuItem"; title = "MiTAC"; ObjectID = "7fV-x8-WHQ"; */ +"7fV-x8-WHQ.title" = "神通"; + /* Class = "NSTabViewItem"; label = "Keyboard"; ObjectID = "1AW-xf-c2f"; */ "1AW-xf-c2f.label" = "キーボード"; diff --git a/Source/WindowNIBs/Source/WindowNIBs/zh-Hans.lproj/frmPrefWindow.strings b/Source/WindowNIBs/Source/WindowNIBs/zh-Hans.lproj/frmPrefWindow.strings index 973c0919..72f334d4 100644 --- a/Source/WindowNIBs/Source/WindowNIBs/zh-Hans.lproj/frmPrefWindow.strings +++ b/Source/WindowNIBs/Source/WindowNIBs/zh-Hans.lproj/frmPrefWindow.strings @@ -89,6 +89,9 @@ /* Class = "NSMenuItem"; title = "IBM"; ObjectID = "137"; */ "137.title" = "IBM"; +/* Class = "NSMenuItem"; title = "MiTAC"; ObjectID = "7fV-x8-WHQ"; */ +"7fV-x8-WHQ.title" = "神通"; + /* Class = "NSTabViewItem"; label = "Keyboard"; ObjectID = "1AW-xf-c2f"; */ "1AW-xf-c2f.label" = "键盘"; diff --git a/Source/WindowNIBs/Source/WindowNIBs/zh-Hant.lproj/frmPrefWindow.strings b/Source/WindowNIBs/Source/WindowNIBs/zh-Hant.lproj/frmPrefWindow.strings index d15e9c36..fb104a04 100644 --- a/Source/WindowNIBs/Source/WindowNIBs/zh-Hant.lproj/frmPrefWindow.strings +++ b/Source/WindowNIBs/Source/WindowNIBs/zh-Hant.lproj/frmPrefWindow.strings @@ -89,6 +89,9 @@ /* Class = "NSMenuItem"; title = "IBM"; ObjectID = "137"; */ "137.title" = "IBM"; +/* Class = "NSMenuItem"; title = "MiTAC"; ObjectID = "7fV-x8-WHQ"; */ +"7fV-x8-WHQ.title" = "神通"; + /* Class = "NSTabViewItem"; label = "Keyboard"; ObjectID = "1AW-xf-c2f"; */ "1AW-xf-c2f.label" = "鍵盤"; diff --git a/vChewing.xcodeproj/project.pbxproj b/vChewing.xcodeproj/project.pbxproj index 6bf1586f..b751339c 100644 --- a/vChewing.xcodeproj/project.pbxproj +++ b/vChewing.xcodeproj/project.pbxproj @@ -780,7 +780,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 1320; - LastUpgradeCheck = 1310; + LastUpgradeCheck = 1320; TargetAttributes = { 5BD05BB727B2A429004C4F1D = { CreatedOnToolsVersion = 13.2; @@ -1136,6 +1136,7 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_ENTITLEMENTS = vChewingPhraseEditor/vChewingPhraseEditor.entitlements; + CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; @@ -1190,6 +1191,7 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_ENTITLEMENTS = vChewingPhraseEditor/vChewingPhraseEditor.entitlements; + CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO;