commit
497c30a768
|
@ -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」。
|
||||
|
||||
## 应用授权
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -29,176 +29,176 @@ namespace Taiyan {
|
|||
namespace Mandarin {
|
||||
|
||||
class BopomofoSyllable {
|
||||
public:
|
||||
typedef uint16_t Component;
|
||||
public:
|
||||
typedef uint16_t Component;
|
||||
|
||||
explicit BopomofoSyllable(Component syllable = 0) : syllable_(syllable) {}
|
||||
explicit BopomofoSyllable(Component syllable = 0) : syllable_(syllable) {}
|
||||
|
||||
BopomofoSyllable(const BopomofoSyllable&) = default;
|
||||
BopomofoSyllable(BopomofoSyllable&& another) = default;
|
||||
BopomofoSyllable& operator=(const BopomofoSyllable&) = default;
|
||||
BopomofoSyllable& operator=(BopomofoSyllable&&) = default;
|
||||
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);
|
||||
// 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;
|
||||
// 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;
|
||||
// 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;
|
||||
static const BopomofoSyllable FromComposedString(const std::string& str);
|
||||
const std::string composedString() const;
|
||||
|
||||
void clear() { syllable_ = 0; }
|
||||
void clear() { syllable_ = 0; }
|
||||
|
||||
bool isEmpty() const { return !syllable_; }
|
||||
bool isEmpty() const { return !syllable_; }
|
||||
|
||||
bool hasConsonant() const { return !!(syllable_ & ConsonantMask); }
|
||||
bool hasConsonant() const { return !!(syllable_ & ConsonantMask); }
|
||||
|
||||
bool hasMiddleVowel() const { return !!(syllable_ & MiddleVowelMask); }
|
||||
bool hasVowel() const { return !!(syllable_ & VowelMask); }
|
||||
bool hasMiddleVowel() const { return !!(syllable_ & MiddleVowelMask); }
|
||||
bool hasVowel() const { return !!(syllable_ & VowelMask); }
|
||||
|
||||
bool hasToneMarker() const { return !!(syllable_ & ToneMarkerMask); }
|
||||
bool hasToneMarker() const { return !!(syllable_ & ToneMarkerMask); }
|
||||
|
||||
Component consonantComponent() const { return syllable_ & ConsonantMask; }
|
||||
Component consonantComponent() const { return syllable_ & ConsonantMask; }
|
||||
|
||||
Component middleVowelComponent() const {
|
||||
return syllable_ & MiddleVowelMask;
|
||||
}
|
||||
Component middleVowelComponent() const {
|
||||
return syllable_ & MiddleVowelMask;
|
||||
}
|
||||
|
||||
Component vowelComponent() const { return syllable_ & VowelMask; }
|
||||
Component vowelComponent() const { return syllable_ & VowelMask; }
|
||||
|
||||
Component toneMarkerComponent() const { return syllable_ & ToneMarkerMask; }
|
||||
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 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 {
|
||||
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);
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
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_;
|
||||
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);
|
||||
}
|
||||
return BopomofoSyllable(newSyllable);
|
||||
}
|
||||
|
||||
BopomofoSyllable& operator+=(const BopomofoSyllable& another) {
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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<char>(order % 79);
|
||||
char high = 48 + static_cast<char>(order / 79);
|
||||
std::string result(2, ' ');
|
||||
result[0] = low;
|
||||
result[1] = high;
|
||||
return result;
|
||||
}
|
||||
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<char>(order % 79);
|
||||
char high = 48 + static_cast<char>(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 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();
|
||||
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));
|
||||
}
|
||||
return FromAbsoluteOrder((uint16_t)(str[1] - 48) * 79 +
|
||||
(uint16_t)(str[0] - 48));
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& stream,
|
||||
const BopomofoSyllable& syllable);
|
||||
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;
|
||||
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_;
|
||||
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<char, std::vector<BPMF::Component> > BopomofoKeyToComponentMap;
|
|||
typedef std::map<BPMF::Component, char> 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();
|
||||
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 =
|
||||
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<BPMF::Component>::const_iterator viter =
|
||||
(*miter).second.begin();
|
||||
viter != (*miter).second.end(); ++viter)
|
||||
m_componentToKey[*viter] = (*miter).first;
|
||||
}
|
||||
miter != m_keyToComponent.end(); ++miter)
|
||||
for (std::vector<BPMF::Component>::const_iterator viter =
|
||||
(*miter).second.begin();
|
||||
viter != (*miter).second.end(); ++viter)
|
||||
m_componentToKey[*viter] = (*miter).first;
|
||||
}
|
||||
|
||||
const std::string name() const { return m_name; }
|
||||
const std::string name() const { return m_name; }
|
||||
|
||||
char componentToKey(BPMF::Component component) const {
|
||||
BopomofoComponentToKeyMap::const_iterator iter =
|
||||
char componentToKey(BPMF::Component component) const {
|
||||
BopomofoComponentToKeyMap::const_iterator iter =
|
||||
m_componentToKey.find(component);
|
||||
return (iter == m_componentToKey.end()) ? 0 : (*iter).second;
|
||||
}
|
||||
return (iter == m_componentToKey.end()) ? 0 : (*iter).second;
|
||||
}
|
||||
|
||||
const std::vector<BPMF::Component> keyToComponents(char key) const {
|
||||
BopomofoKeyToComponentMap::const_iterator iter = m_keyToComponent.find(key);
|
||||
return (iter == m_keyToComponent.end()) ? std::vector<BPMF::Component>()
|
||||
: (*iter).second;
|
||||
}
|
||||
const std::vector<BPMF::Component> keyToComponents(char key) const {
|
||||
BopomofoKeyToComponentMap::const_iterator iter = m_keyToComponent.find(key);
|
||||
return (iter == m_keyToComponent.end()) ? std::vector<BPMF::Component>()
|
||||
: (*iter).second;
|
||||
}
|
||||
|
||||
const std::string keySequenceFromSyllable(BPMF syllable) const {
|
||||
std::string sequence;
|
||||
const std::string keySequenceFromSyllable(BPMF syllable) const {
|
||||
std::string sequence;
|
||||
|
||||
BPMF::Component c;
|
||||
char k;
|
||||
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<BPMF::Component> 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<BPMF::Component> 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;
|
||||
|
||||
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);
|
||||
|
||||
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 (tone1)
|
||||
if (*ahead == tone1) return true;
|
||||
if (*ahead == tone2 || *ahead == tone3 || *ahead == tone4 ||
|
||||
*ahead == tone5)
|
||||
return true;
|
||||
|
||||
if (*ahead == tone2 || *ahead == tone3 || *ahead == tone4 ||
|
||||
*ahead == tone5)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
for (; start != end; ++start)
|
||||
if (*start == iChar || *start == ueChar) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string m_name;
|
||||
BopomofoKeyToComponentMap m_keyToComponent;
|
||||
BopomofoComponentToKeyMap m_componentToKey;
|
||||
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 isValidKey(char k) const {
|
||||
if (!pinyin_mode_) {
|
||||
return layout_ ? (layout_->keyToComponents(k)).size() > 0 : false;
|
||||
}
|
||||
|
||||
bool combineKey(char k) {
|
||||
if (!isValidKey(k)) return 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_mode_) {
|
||||
pinyin_sequence_ += std::string(1, tolower(k));
|
||||
syllable_ = BPMF::FromHanyuPinyin(pinyin_sequence_);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
bool isEmpty() const { return syllable_.isEmpty(); }
|
||||
|
||||
const std::string composedString() const {
|
||||
if (pinyin_mode_) {
|
||||
return pinyin_sequence_;
|
||||
void clear() {
|
||||
pinyin_sequence_.clear();
|
||||
syllable_.clear();
|
||||
}
|
||||
|
||||
return syllable_.composedString();
|
||||
}
|
||||
void backspace() {
|
||||
if (!layout_) return;
|
||||
|
||||
const BPMF syllable() const { return syllable_; }
|
||||
if (pinyin_mode_) {
|
||||
if (pinyin_sequence_.length()) {
|
||||
pinyin_sequence_ =
|
||||
pinyin_sequence_.substr(0, pinyin_sequence_.length() - 1);
|
||||
}
|
||||
|
||||
const std::string standardLayoutQueryString() const {
|
||||
return BopomofoKeyboardLayout::StandardLayout()->keySequenceFromSyllable(
|
||||
syllable_);
|
||||
}
|
||||
syllable_ = BPMF::FromHanyuPinyin(pinyin_sequence_);
|
||||
return;
|
||||
}
|
||||
|
||||
const std::string absoluteOrderQueryString() const {
|
||||
return syllable_.absoluteOrderString();
|
||||
}
|
||||
std::string sequence = layout_->keySequenceFromSyllable(syllable_);
|
||||
if (sequence.length()) {
|
||||
sequence = sequence.substr(0, sequence.length() - 1);
|
||||
syllable_ = layout_->syllableFromKeySequence(sequence);
|
||||
}
|
||||
}
|
||||
|
||||
bool hasToneMarker() const { return syllable_.hasToneMarker(); }
|
||||
bool isEmpty() const { return syllable_.isEmpty(); }
|
||||
|
||||
protected:
|
||||
const BopomofoKeyboardLayout* layout_;
|
||||
BPMF syllable_;
|
||||
const std::string composedString() const {
|
||||
if (pinyin_mode_) {
|
||||
return pinyin_sequence_;
|
||||
}
|
||||
|
||||
bool pinyin_mode_;
|
||||
std::string 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
|
||||
|
|
|
@ -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:"﹣﹦≡|∣∥–︱—︳╴¯ ̄﹉﹊﹍﹎﹋﹌﹏︴∕﹨╱╲/\"),
|
||||
])
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -154,8 +154,9 @@ 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) {
|
||||
|
@ -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)
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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" = "線分";
|
||||
|
|
|
@ -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" = "线段";
|
||||
|
|
|
@ -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" = "線段";
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -262,7 +262,7 @@
|
|||
<font key="font" metaFont="cellTitle"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="clickedWhetherIMEShouldNotFartToggleAction:" target="-1" id="bUl-EZ-USn"/>
|
||||
<action selector="clickedWhetherIMEShouldNotFartToggleAction:" target="-2" id="9h1-f6-SGF"/>
|
||||
<binding destination="32" name="value" keyPath="values.ShouldNotFartInLieuOfBeep" id="EOH-Pc-8Hk"/>
|
||||
</connections>
|
||||
</button>
|
||||
|
@ -594,8 +594,9 @@
|
|||
<menuItem title="ETen" tag="1" id="7"/>
|
||||
<menuItem title="Hsu" tag="2" id="8"/>
|
||||
<menuItem title="ETen26" tag="3" id="9"/>
|
||||
<menuItem title="IBM" tag="5" id="137"/>
|
||||
<menuItem title="Hanyu Pinyin" tag="4" id="10"/>
|
||||
<menuItem title="IBM" tag="4" id="137"/>
|
||||
<menuItem title="MiTAC" tag="5" id="7fV-x8-WHQ"/>
|
||||
<menuItem title="Hanyu Pinyin" tag="10" id="10"/>
|
||||
</items>
|
||||
</menu>
|
||||
<connections>
|
||||
|
|
|
@ -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";
|
||||
|
||||
|
|
|
@ -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" = "キーボード";
|
||||
|
||||
|
|
|
@ -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" = "键盘";
|
||||
|
||||
|
|
|
@ -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" = "鍵盤";
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue