@@ -1718,6 +1718,13 @@ class Composer {
17181718 // / 是否對錯誤的注音讀音組合做出自動糾正處理。
17191719 bool phonabetCombinationCorrectionEnabled;
17201720
1721+ // / 是否嚴格要求按照聲介韻調(consonant→semivowel→vowel→intonation)順序輸入。
1722+ // / 啟用後,若 phonabet 要填入的 slot 比目前已填的最大 slot 更早(例如 vowel
1723+ // / 已填而 semivowel 後到), 則該 phonabet
1724+ // / 會被拒絕。聲調(intonation)永遠允許。
1725+ // / 此特性僅供部分特殊場合使用,等同於停用並擊特性。
1726+ bool enforceCSVTOrdering = false ;
1727+
17211728 // MARK: Private
17221729
17231730 // / 追蹤 romajiBuffer 是否需要從聲介韻重建。
@@ -1937,10 +1944,10 @@ class Composer {
19371944 // / 如果是諸如複合型注音排列的話,翻譯結果有可能為空,但翻譯過程已經處理好聲介韻調分配了。
19381945 // /
19391946 // / @param input 傳入的 String 內容。
1940- void receiveKey (std::string input) {
1947+ // / @return 若按鍵被接受則為 true,被拒絕則為 false。
1948+ bool receiveKey (std::string input) {
19411949 if (!isPinyinMode ()) {
1942- receiveKeyFromPhonabet (translate (input));
1943- return ;
1950+ return receiveKeyFromPhonabet (translate (input));
19441951 }
19451952 int maxCount;
19461953 if (mapArayuruPinyinIntonation.count (input)) {
@@ -1959,6 +1966,7 @@ class Composer {
19591966 romajiBuffer = romajiBufferBackup;
19601967 _needsRomajiUpdate = false ;
19611968 }
1969+ return true ;
19621970 }
19631971
19641972 // / 接受傳入的按鍵訊號時的處理,處理對象為 UniChar。
@@ -1967,7 +1975,8 @@ class Composer {
19671975 // / 如果是諸如複合型注音排列的話,翻譯結果有可能為空,但翻譯過程已經處理好聲介韻調分配了。
19681976 // /
19691977 // / @param input 傳入的 UniChar 內容。
1970- void receiveKey (char input) { receiveKey ((charToString (input))); };
1978+ // / @return 若按鍵被接受則為 true,被拒絕則為 false。
1979+ bool receiveKey (char input) { return receiveKey ((charToString (input))); };
19711980
19721981 // / 接受傳入的按鍵訊號時的處理,處理對象為單個注音符號。
19731982 // / 主要就是將注音符號拆分辨識且分配到正確的貯存位置而已。
@@ -1977,7 +1986,8 @@ class Composer {
19771986 // / 主要就是將注音符號拆分辨識且分配到正確的貯存位置而已。
19781987 // /
19791988 // / @param phonabet 傳入的單個注音符號 Unicode scalar。
1980- void receiveKeyFromPhonabet (char32_t phonabet) {
1989+ // / @return 若按鍵被接受則為 true,被拒絕則為 false。
1990+ bool receiveKeyFromPhonabet (char32_t phonabet) {
19811991 Phonabet thePhone = Phonabet (phonabet);
19821992 if (phonabetCombinationCorrectionEnabled) {
19831993 switch (phonabet) {
@@ -2056,6 +2066,21 @@ class Composer {
20562066 }
20572067 }
20582068
2069+ // 個別情形需強制聲介韻調的輸入順序。
2070+ if (enforceCSVTOrdering) {
2071+ int newSlot = static_cast <int >(
2072+ thePhone.type ); // 1=consonant, 2=semivowel, 3=vowel, 4=intonation
2073+ int maxFilledSlot = std::max ({
2074+ intonation.isEmpty () ? 0 : static_cast <int >(PhoneType::intonation),
2075+ vowel.isEmpty () ? 0 : static_cast <int >(PhoneType::vowel),
2076+ semivowel.isEmpty () ? 0 : static_cast <int >(PhoneType::semivowel),
2077+ consonant.isEmpty () ? 0 : static_cast <int >(PhoneType::consonant),
2078+ });
2079+ if (newSlot != static_cast <int >(PhoneType::intonation) &&
2080+ newSlot < maxFilledSlot)
2081+ return false ;
2082+ }
2083+
20592084 switch (thePhone.type ) {
20602085 case PhoneType::consonant:
20612086 consonant = thePhone;
@@ -2073,14 +2098,16 @@ class Composer {
20732098 break ;
20742099 }
20752100 updateRomajiBuffer ();
2101+ return true ;
20762102 }
20772103
20782104 // / 接受傳入的按鍵訊號時的處理,處理對象為單個注音符號(字串版本,為了向後兼容)。
20792105 // / 主要就是將注音符號拆分辨識且分配到正確的貯存位置而已。
20802106 // /
20812107 // / @param phonabet 傳入的單個注音符號字串。
2082- void receiveKeyFromPhonabet (std::string phonabet = " " ) {
2083- if (phonabet.empty ()) return ;
2108+ // / @return 若按鍵被接受則為 true,被拒絕則為 false。
2109+ bool receiveKeyFromPhonabet (std::string phonabet = " " ) {
2110+ if (phonabet.empty ()) return true ;
20842111 // Convert first character to char32_t and call the scalar version
20852112 auto chars = splitByCodepoint (phonabet);
20862113 if (!chars.empty ()) {
@@ -2101,10 +2128,11 @@ class Composer {
21012128 ((bytes[2 ] & 0x3F ) << 6 ) | (bytes[3 ] & 0x3F );
21022129 }
21032130 if (scalar != 0 ) {
2104- receiveKeyFromPhonabet (scalar);
2131+ return receiveKeyFromPhonabet (scalar);
21052132 }
21062133 }
21072134 }
2135+ return false ;
21082136 }
21092137
21102138 // / 處理一連串的按鍵輸入、且返回被處理之後的注音(陰平為空格)。
@@ -2115,8 +2143,9 @@ class Composer {
21152143 bool isRomaji = false ) {
21162144 clear ();
21172145 if (!isRomaji) {
2146+ // 使用 for 迴圈,以利 enforceCSVTOrdering 拒絕時提前終止。
21182147 for (char key : givenSequence) {
2119- receiveKey (key);
2148+ if (! receiveKey (key)) break ;
21202149 }
21212150 return value ();
21222151 }
0 commit comments