KeyHandler // Reducing the usage of "as!", etc.
This commit is contained in:
parent
cf1caf635c
commit
eafb41aa0c
|
@ -2,27 +2,27 @@
|
||||||
// Refactored from the ObjCpp-version of this class by:
|
// Refactored from the ObjCpp-version of this class by:
|
||||||
// (c) 2011 and onwards The OpenVanilla Project (MIT License).
|
// (c) 2011 and onwards The OpenVanilla Project (MIT License).
|
||||||
/*
|
/*
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
this software and associated documentation files (the "Software"), to deal in
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
the Software without restriction, including without limitation the rights to
|
the Software without restriction, including without limitation the rights to
|
||||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
subject to the following conditions:
|
subject to the following conditions:
|
||||||
|
|
||||||
1. The above copyright notice and this permission notice shall be included in
|
1. The above copyright notice and this permission notice shall be included in
|
||||||
all copies or substantial portions of the Software.
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
2. No trademark license is granted to use the trade names, trademarks, service
|
2. No trademark license is granted to use the trade names, trademarks, service
|
||||||
marks, or product names of Contributor, except as required to fulfill notice
|
marks, or product names of Contributor, except as required to fulfill notice
|
||||||
requirements above.
|
requirements above.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import Cocoa
|
import Cocoa
|
||||||
|
|
||||||
|
@ -37,322 +37,327 @@ import Cocoa
|
||||||
) -> Bool {
|
) -> Bool {
|
||||||
let inputText = input.inputText
|
let inputText = input.inputText
|
||||||
let charCode: UniChar = input.charCode
|
let charCode: UniChar = input.charCode
|
||||||
let ctlCandidateCurrent = delegate!.ctlCandidate(for: self) as! ctlCandidate
|
if let ctlCandidateCurrent = delegate!.ctlCandidate(for: self) as? ctlCandidate {
|
||||||
|
// MARK: Cancel Candidate
|
||||||
|
|
||||||
// MARK: Cancel Candidate
|
let cancelCandidateKey =
|
||||||
|
input.isBackSpace || input.isESC || input.isDelete
|
||||||
|
|| ((input.isCursorBackward || input.isCursorForward) && input.isShiftHold)
|
||||||
|
|
||||||
let cancelCandidateKey =
|
if cancelCandidateKey {
|
||||||
input.isBackSpace || input.isESC || input.isDelete
|
if (state is InputState.AssociatedPhrases)
|
||||||
|| ((input.isCursorBackward || input.isCursorForward) && input.isShiftHold)
|
|| mgrPrefs.useSCPCTypingMode
|
||||||
|
|| isBuilderEmpty()
|
||||||
if cancelCandidateKey {
|
{
|
||||||
if (state is InputState.AssociatedPhrases)
|
// 如果此時發現當前組字緩衝區為真空的情況的話,
|
||||||
|| mgrPrefs.useSCPCTypingMode
|
// 就將當前的組字緩衝區析構處理、強制重設輸入狀態。
|
||||||
|| isBuilderEmpty()
|
// 否則,一個本不該出現的真空組字緩衝區會使前後方向鍵與 BackSpace 鍵失靈。
|
||||||
{
|
// 所以這裡需要對 isBuilderEmpty() 做判定。
|
||||||
// 如果此時發現當前組字緩衝區為真空的情況的話,
|
clear()
|
||||||
// 就將當前的組字緩衝區析構處理、強制重設輸入狀態。
|
stateCallback(InputState.EmptyIgnoringPreviousState())
|
||||||
// 否則,一個本不該出現的真空組字緩衝區會使前後方向鍵與 BackSpace 鍵失靈。
|
} else {
|
||||||
// 所以這裡需要對 isBuilderEmpty() 做判定。
|
stateCallback(buildInputtingState())
|
||||||
clear()
|
}
|
||||||
stateCallback(InputState.EmptyIgnoringPreviousState())
|
|
||||||
} else {
|
|
||||||
stateCallback(buildInputtingState())
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: Enter
|
|
||||||
|
|
||||||
if input.isEnter {
|
|
||||||
if state is InputState.AssociatedPhrases {
|
|
||||||
clear()
|
|
||||||
stateCallback(InputState.EmptyIgnoringPreviousState())
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
delegate!.keyHandler(
|
|
||||||
self,
|
|
||||||
didSelectCandidateAt: Int(ctlCandidateCurrent.selectedCandidateIndex),
|
|
||||||
ctlCandidate: ctlCandidateCurrent
|
|
||||||
)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: Tab
|
// MARK: Enter
|
||||||
|
|
||||||
if input.isTab {
|
if input.isEnter {
|
||||||
let updated: Bool =
|
if state is InputState.AssociatedPhrases {
|
||||||
mgrPrefs.specifyShiftTabKeyBehavior
|
clear()
|
||||||
? (input.isShiftHold
|
stateCallback(InputState.EmptyIgnoringPreviousState())
|
||||||
? ctlCandidateCurrent.showPreviousPage()
|
return true
|
||||||
: ctlCandidateCurrent.showNextPage())
|
}
|
||||||
: (input.isShiftHold
|
delegate!.keyHandler(
|
||||||
? ctlCandidateCurrent.highlightPreviousCandidate()
|
self,
|
||||||
: ctlCandidateCurrent.highlightNextCandidate())
|
didSelectCandidateAt: Int(ctlCandidateCurrent.selectedCandidateIndex),
|
||||||
if !updated {
|
ctlCandidate: ctlCandidateCurrent
|
||||||
IME.prtDebugIntel("9B691919")
|
)
|
||||||
errorCallback()
|
return true
|
||||||
}
|
}
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: Space
|
// MARK: Tab
|
||||||
|
|
||||||
if input.isSpace {
|
if input.isTab {
|
||||||
let updated: Bool =
|
let updated: Bool =
|
||||||
mgrPrefs.specifyShiftSpaceKeyBehavior
|
mgrPrefs.specifyShiftTabKeyBehavior
|
||||||
? (input.isShiftHold
|
? (input.isShiftHold
|
||||||
? ctlCandidateCurrent.highlightNextCandidate()
|
? ctlCandidateCurrent.showPreviousPage()
|
||||||
: ctlCandidateCurrent.showNextPage())
|
: ctlCandidateCurrent.showNextPage())
|
||||||
: (input.isShiftHold
|
: (input.isShiftHold
|
||||||
? ctlCandidateCurrent.showNextPage()
|
? ctlCandidateCurrent.highlightPreviousCandidate()
|
||||||
: ctlCandidateCurrent.highlightNextCandidate())
|
: ctlCandidateCurrent.highlightNextCandidate())
|
||||||
if !updated {
|
|
||||||
IME.prtDebugIntel("A11C781F")
|
|
||||||
errorCallback()
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: PgDn
|
|
||||||
|
|
||||||
if input.isPageDown || input.emacsKey == vChewingEmacsKey.nextPage {
|
|
||||||
let updated: Bool = ctlCandidateCurrent.showNextPage()
|
|
||||||
if !updated {
|
|
||||||
IME.prtDebugIntel("9B691919")
|
|
||||||
errorCallback()
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: PgUp
|
|
||||||
|
|
||||||
if input.isPageUp {
|
|
||||||
let updated: Bool = ctlCandidateCurrent.showPreviousPage()
|
|
||||||
if !updated {
|
|
||||||
IME.prtDebugIntel("9569955D")
|
|
||||||
errorCallback()
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: Left Arrow
|
|
||||||
|
|
||||||
if input.isLeft {
|
|
||||||
if ctlCandidateCurrent is ctlCandidateHorizontal {
|
|
||||||
let updated: Bool = ctlCandidateCurrent.highlightPreviousCandidate()
|
|
||||||
if !updated {
|
if !updated {
|
||||||
IME.prtDebugIntel("1145148D")
|
IME.prtDebugIntel("9B691919")
|
||||||
errorCallback()
|
errorCallback()
|
||||||
}
|
}
|
||||||
} else {
|
return true
|
||||||
let updated: Bool = ctlCandidateCurrent.showPreviousPage()
|
}
|
||||||
|
|
||||||
|
// MARK: Space
|
||||||
|
|
||||||
|
if input.isSpace {
|
||||||
|
let updated: Bool =
|
||||||
|
mgrPrefs.specifyShiftSpaceKeyBehavior
|
||||||
|
? (input.isShiftHold
|
||||||
|
? ctlCandidateCurrent.highlightNextCandidate()
|
||||||
|
: ctlCandidateCurrent.showNextPage())
|
||||||
|
: (input.isShiftHold
|
||||||
|
? ctlCandidateCurrent.showNextPage()
|
||||||
|
: ctlCandidateCurrent.highlightNextCandidate())
|
||||||
if !updated {
|
if !updated {
|
||||||
IME.prtDebugIntel("1919810D")
|
IME.prtDebugIntel("A11C781F")
|
||||||
errorCallback()
|
errorCallback()
|
||||||
}
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: EmacsKey Backward
|
// MARK: PgDn
|
||||||
|
|
||||||
if input.emacsKey == vChewingEmacsKey.backward {
|
if input.isPageDown || input.emacsKey == vChewingEmacsKey.nextPage {
|
||||||
let updated: Bool = ctlCandidateCurrent.highlightPreviousCandidate()
|
|
||||||
if !updated {
|
|
||||||
IME.prtDebugIntel("9B89308D")
|
|
||||||
errorCallback()
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: Right Arrow
|
|
||||||
|
|
||||||
if input.isRight {
|
|
||||||
if ctlCandidateCurrent is ctlCandidateHorizontal {
|
|
||||||
let updated: Bool = ctlCandidateCurrent.highlightNextCandidate()
|
|
||||||
if !updated {
|
|
||||||
IME.prtDebugIntel("9B65138D")
|
|
||||||
errorCallback()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let updated: Bool = ctlCandidateCurrent.showNextPage()
|
let updated: Bool = ctlCandidateCurrent.showNextPage()
|
||||||
if !updated {
|
if !updated {
|
||||||
IME.prtDebugIntel("9244908D")
|
IME.prtDebugIntel("9B691919")
|
||||||
errorCallback()
|
errorCallback()
|
||||||
}
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: EmacsKey Forward
|
// MARK: PgUp
|
||||||
|
|
||||||
if input.emacsKey == vChewingEmacsKey.forward {
|
if input.isPageUp {
|
||||||
let updated: Bool = ctlCandidateCurrent.highlightNextCandidate()
|
|
||||||
if !updated {
|
|
||||||
IME.prtDebugIntel("9B2428D")
|
|
||||||
errorCallback()
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: Up Arrow
|
|
||||||
|
|
||||||
if input.isUp {
|
|
||||||
if ctlCandidateCurrent is ctlCandidateHorizontal {
|
|
||||||
let updated: Bool = ctlCandidateCurrent.showPreviousPage()
|
let updated: Bool = ctlCandidateCurrent.showPreviousPage()
|
||||||
if !updated {
|
if !updated {
|
||||||
IME.prtDebugIntel("9B614524")
|
IME.prtDebugIntel("9569955D")
|
||||||
errorCallback()
|
errorCallback()
|
||||||
}
|
}
|
||||||
} else {
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Left Arrow
|
||||||
|
|
||||||
|
if input.isLeft {
|
||||||
|
if ctlCandidateCurrent is ctlCandidateHorizontal {
|
||||||
|
let updated: Bool = ctlCandidateCurrent.highlightPreviousCandidate()
|
||||||
|
if !updated {
|
||||||
|
IME.prtDebugIntel("1145148D")
|
||||||
|
errorCallback()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let updated: Bool = ctlCandidateCurrent.showPreviousPage()
|
||||||
|
if !updated {
|
||||||
|
IME.prtDebugIntel("1919810D")
|
||||||
|
errorCallback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: EmacsKey Backward
|
||||||
|
|
||||||
|
if input.emacsKey == vChewingEmacsKey.backward {
|
||||||
let updated: Bool = ctlCandidateCurrent.highlightPreviousCandidate()
|
let updated: Bool = ctlCandidateCurrent.highlightPreviousCandidate()
|
||||||
if !updated {
|
if !updated {
|
||||||
IME.prtDebugIntel("ASD9908D")
|
IME.prtDebugIntel("9B89308D")
|
||||||
errorCallback()
|
errorCallback()
|
||||||
}
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: Down Arrow
|
// MARK: Right Arrow
|
||||||
|
|
||||||
if input.isDown {
|
if input.isRight {
|
||||||
if ctlCandidateCurrent is ctlCandidateHorizontal {
|
if ctlCandidateCurrent is ctlCandidateHorizontal {
|
||||||
let updated: Bool = ctlCandidateCurrent.showNextPage()
|
let updated: Bool = ctlCandidateCurrent.highlightNextCandidate()
|
||||||
if !updated {
|
if !updated {
|
||||||
IME.prtDebugIntel("92B990DD")
|
IME.prtDebugIntel("9B65138D")
|
||||||
errorCallback()
|
errorCallback()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let updated: Bool = ctlCandidateCurrent.showNextPage()
|
||||||
|
if !updated {
|
||||||
|
IME.prtDebugIntel("9244908D")
|
||||||
|
errorCallback()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: EmacsKey Forward
|
||||||
|
|
||||||
|
if input.emacsKey == vChewingEmacsKey.forward {
|
||||||
let updated: Bool = ctlCandidateCurrent.highlightNextCandidate()
|
let updated: Bool = ctlCandidateCurrent.highlightNextCandidate()
|
||||||
if !updated {
|
if !updated {
|
||||||
IME.prtDebugIntel("6B99908D")
|
IME.prtDebugIntel("9B2428D")
|
||||||
errorCallback()
|
errorCallback()
|
||||||
}
|
}
|
||||||
}
|
return true
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: Home Key
|
|
||||||
|
|
||||||
if input.isHome || input.emacsKey == vChewingEmacsKey.home {
|
|
||||||
if ctlCandidateCurrent.selectedCandidateIndex == 0 {
|
|
||||||
IME.prtDebugIntel("9B6EDE8D")
|
|
||||||
errorCallback()
|
|
||||||
} else {
|
|
||||||
ctlCandidateCurrent.selectedCandidateIndex = 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
// MARK: Up Arrow
|
||||||
}
|
|
||||||
|
|
||||||
var candidates: [String]!
|
if input.isUp {
|
||||||
|
if ctlCandidateCurrent is ctlCandidateHorizontal {
|
||||||
|
let updated: Bool = ctlCandidateCurrent.showPreviousPage()
|
||||||
|
if !updated {
|
||||||
|
IME.prtDebugIntel("9B614524")
|
||||||
|
errorCallback()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let updated: Bool = ctlCandidateCurrent.highlightPreviousCandidate()
|
||||||
|
if !updated {
|
||||||
|
IME.prtDebugIntel("ASD9908D")
|
||||||
|
errorCallback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
if state is InputState.ChoosingCandidate {
|
// MARK: Down Arrow
|
||||||
candidates = (state as! InputState.ChoosingCandidate).candidates
|
|
||||||
} else if state is InputState.AssociatedPhrases {
|
|
||||||
candidates = (state as! InputState.AssociatedPhrases).candidates
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: End Key
|
if input.isDown {
|
||||||
|
if ctlCandidateCurrent is ctlCandidateHorizontal {
|
||||||
|
let updated: Bool = ctlCandidateCurrent.showNextPage()
|
||||||
|
if !updated {
|
||||||
|
IME.prtDebugIntel("92B990DD")
|
||||||
|
errorCallback()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let updated: Bool = ctlCandidateCurrent.highlightNextCandidate()
|
||||||
|
if !updated {
|
||||||
|
IME.prtDebugIntel("6B99908D")
|
||||||
|
errorCallback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
if candidates.isEmpty {
|
// MARK: Home Key
|
||||||
return false
|
|
||||||
} else { // 這裡不用「count > 0」,因為該整數變數只要「!isEmpty」那就必定滿足這個條件。
|
if input.isHome || input.emacsKey == vChewingEmacsKey.home {
|
||||||
if input.isEnd || input.emacsKey == vChewingEmacsKey.end {
|
if ctlCandidateCurrent.selectedCandidateIndex == 0 {
|
||||||
if ctlCandidateCurrent.selectedCandidateIndex == UInt(candidates.count - 1) {
|
IME.prtDebugIntel("9B6EDE8D")
|
||||||
IME.prtDebugIntel("9B69AAAD")
|
|
||||||
errorCallback()
|
errorCallback()
|
||||||
} else {
|
} else {
|
||||||
ctlCandidateCurrent.selectedCandidateIndex = UInt(candidates.count - 1)
|
ctlCandidateCurrent.selectedCandidateIndex = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Associated Phrases
|
// MARK: End Key
|
||||||
|
|
||||||
if state is InputState.AssociatedPhrases {
|
var candidates: [String]!
|
||||||
if !input.isShiftHold { return false }
|
|
||||||
}
|
|
||||||
|
|
||||||
var index: Int = NSNotFound
|
if let state = state as? InputState.ChoosingCandidate {
|
||||||
var match: String!
|
candidates = state.candidates
|
||||||
if state is InputState.AssociatedPhrases { match = input.inputTextIgnoringModifiers } else { match = inputText }
|
} else if let state = state as? InputState.AssociatedPhrases {
|
||||||
|
candidates = state.candidates
|
||||||
var j = 0
|
|
||||||
while j < ctlCandidateCurrent.keyLabels.count {
|
|
||||||
let label: CandidateKeyLabel = ctlCandidateCurrent.keyLabels[j]
|
|
||||||
if match.compare(label.key, options: .caseInsensitive, range: nil, locale: .current) == .orderedSame {
|
|
||||||
index = j
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
j += 1
|
|
||||||
}
|
|
||||||
|
|
||||||
if index != NSNotFound {
|
if candidates.isEmpty {
|
||||||
let candidateIndex: UInt = ctlCandidateCurrent.candidateIndexAtKeyLabelIndex(UInt(index))
|
return false
|
||||||
if candidateIndex != UInt.max {
|
} else { // 這裡不用「count > 0」,因為該整數變數只要「!isEmpty」那就必定滿足這個條件。
|
||||||
delegate!.keyHandler(self, didSelectCandidateAt: Int(candidateIndex), ctlCandidate: ctlCandidateCurrent)
|
if input.isEnd || input.emacsKey == vChewingEmacsKey.end {
|
||||||
return true
|
if ctlCandidateCurrent.selectedCandidateIndex == UInt(candidates.count - 1) {
|
||||||
|
IME.prtDebugIntel("9B69AAAD")
|
||||||
|
errorCallback()
|
||||||
|
} else {
|
||||||
|
ctlCandidateCurrent.selectedCandidateIndex = UInt(candidates.count - 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if state is InputState.AssociatedPhrases { return false }
|
// MARK: - Associated Phrases
|
||||||
|
|
||||||
// MARK: SCPC Mode Processing
|
if state is InputState.AssociatedPhrases {
|
||||||
|
if !input.isShiftHold { return false }
|
||||||
|
}
|
||||||
|
|
||||||
if mgrPrefs.useSCPCTypingMode {
|
var index: Int = NSNotFound
|
||||||
var punctuationNamePrefix = ""
|
var match: String!
|
||||||
|
if state is InputState.AssociatedPhrases {
|
||||||
if input.isOptionHold {
|
match = input.inputTextIgnoringModifiers
|
||||||
punctuationNamePrefix = "_alt_punctuation_"
|
|
||||||
} else if input.isControlHold {
|
|
||||||
punctuationNamePrefix = "_ctrl_punctuation_"
|
|
||||||
} else if mgrPrefs.halfWidthPunctuationEnabled {
|
|
||||||
punctuationNamePrefix = "_half_punctuation_"
|
|
||||||
} else {
|
} else {
|
||||||
punctuationNamePrefix = "_punctuation_"
|
match = inputText
|
||||||
}
|
}
|
||||||
|
|
||||||
let parser = getCurrentMandarinParser()
|
var j = 0
|
||||||
|
while j < ctlCandidateCurrent.keyLabels.count {
|
||||||
let arrCustomPunctuations: [String] = [
|
let label: CandidateKeyLabel = ctlCandidateCurrent.keyLabels[j]
|
||||||
punctuationNamePrefix, parser, String(format: "%c", CChar(charCode)),
|
if match.compare(label.key, options: .caseInsensitive, range: nil, locale: .current) == .orderedSame {
|
||||||
]
|
index = j
|
||||||
let customPunctuation: String = arrCustomPunctuations.joined(separator: "")
|
break
|
||||||
|
}
|
||||||
let arrPunctuations: [String] = [punctuationNamePrefix, String(format: "%c", CChar(charCode))]
|
j += 1
|
||||||
let punctuation: String = arrPunctuations.joined(separator: "")
|
|
||||||
|
|
||||||
var shouldAutoSelectCandidate: Bool =
|
|
||||||
chkKeyValidity(charCode) || ifLangModelHasUnigrams(forKey: customPunctuation)
|
|
||||||
|| ifLangModelHasUnigrams(forKey: punctuation)
|
|
||||||
|
|
||||||
if !shouldAutoSelectCandidate, input.isUpperCaseASCIILetterKey {
|
|
||||||
let letter: String! = String(format: "%@%c", "_letter_", CChar(charCode))
|
|
||||||
if ifLangModelHasUnigrams(forKey: letter) { shouldAutoSelectCandidate = true }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if shouldAutoSelectCandidate {
|
if index != NSNotFound {
|
||||||
let candidateIndex: UInt = ctlCandidateCurrent.candidateIndexAtKeyLabelIndex(0)
|
let candidateIndex: UInt = ctlCandidateCurrent.candidateIndexAtKeyLabelIndex(UInt(index))
|
||||||
if candidateIndex != UInt.max {
|
if candidateIndex != UInt.max {
|
||||||
delegate!.keyHandler(
|
delegate!.keyHandler(
|
||||||
self,
|
self, didSelectCandidateAt: Int(candidateIndex), ctlCandidate: ctlCandidateCurrent
|
||||||
didSelectCandidateAt: Int(candidateIndex),
|
|
||||||
ctlCandidate: ctlCandidateCurrent
|
|
||||||
)
|
|
||||||
clear()
|
|
||||||
let empty = InputState.EmptyIgnoringPreviousState()
|
|
||||||
stateCallback(empty)
|
|
||||||
return handle(
|
|
||||||
input: input, state: empty, stateCallback: stateCallback, errorCallback: errorCallback
|
|
||||||
)
|
)
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
if state is InputState.AssociatedPhrases { return false }
|
||||||
|
|
||||||
|
// MARK: SCPC Mode Processing
|
||||||
|
|
||||||
|
if mgrPrefs.useSCPCTypingMode {
|
||||||
|
var punctuationNamePrefix = ""
|
||||||
|
|
||||||
|
if input.isOptionHold {
|
||||||
|
punctuationNamePrefix = "_alt_punctuation_"
|
||||||
|
} else if input.isControlHold {
|
||||||
|
punctuationNamePrefix = "_ctrl_punctuation_"
|
||||||
|
} else if mgrPrefs.halfWidthPunctuationEnabled {
|
||||||
|
punctuationNamePrefix = "_half_punctuation_"
|
||||||
|
} else {
|
||||||
|
punctuationNamePrefix = "_punctuation_"
|
||||||
|
}
|
||||||
|
|
||||||
|
let parser = getCurrentMandarinParser()
|
||||||
|
|
||||||
|
let arrCustomPunctuations: [String] = [
|
||||||
|
punctuationNamePrefix, parser, String(format: "%c", CChar(charCode)),
|
||||||
|
]
|
||||||
|
let customPunctuation: String = arrCustomPunctuations.joined(separator: "")
|
||||||
|
|
||||||
|
let arrPunctuations: [String] = [punctuationNamePrefix, String(format: "%c", CChar(charCode))]
|
||||||
|
let punctuation: String = arrPunctuations.joined(separator: "")
|
||||||
|
|
||||||
|
var shouldAutoSelectCandidate: Bool =
|
||||||
|
chkKeyValidity(charCode) || ifLangModelHasUnigrams(forKey: customPunctuation)
|
||||||
|
|| ifLangModelHasUnigrams(forKey: punctuation)
|
||||||
|
|
||||||
|
if !shouldAutoSelectCandidate, input.isUpperCaseASCIILetterKey {
|
||||||
|
let letter: String! = String(format: "%@%c", "_letter_", CChar(charCode))
|
||||||
|
if ifLangModelHasUnigrams(forKey: letter) { shouldAutoSelectCandidate = true }
|
||||||
|
}
|
||||||
|
|
||||||
|
if shouldAutoSelectCandidate {
|
||||||
|
let candidateIndex: UInt = ctlCandidateCurrent.candidateIndexAtKeyLabelIndex(0)
|
||||||
|
if candidateIndex != UInt.max {
|
||||||
|
delegate!.keyHandler(
|
||||||
|
self,
|
||||||
|
didSelectCandidateAt: Int(candidateIndex),
|
||||||
|
ctlCandidate: ctlCandidateCurrent
|
||||||
|
)
|
||||||
|
clear()
|
||||||
|
let empty = InputState.EmptyIgnoringPreviousState()
|
||||||
|
stateCallback(empty)
|
||||||
|
return handle(
|
||||||
|
input: input, state: empty, stateCallback: stateCallback, errorCallback: errorCallback
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // END: "if let ctlCandidateCurrent"
|
||||||
|
|
||||||
IME.prtDebugIntel("172A0F81")
|
IME.prtDebugIntel("172A0F81")
|
||||||
errorCallback()
|
errorCallback()
|
||||||
|
|
|
@ -125,16 +125,13 @@ import Cocoa
|
||||||
|
|
||||||
// MARK: Handle Marking.
|
// MARK: Handle Marking.
|
||||||
|
|
||||||
if state is InputState.Marking {
|
if let marking = state as? InputState.Marking {
|
||||||
let marking = state as! InputState.Marking
|
|
||||||
|
|
||||||
if _handleMarkingState(
|
if _handleMarkingState(
|
||||||
state as! InputState.Marking, input: input, stateCallback: stateCallback,
|
marking, input: input, stateCallback: stateCallback,
|
||||||
errorCallback: errorCallback
|
errorCallback: errorCallback
|
||||||
) {
|
) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
state = marking.convertToInputting()
|
state = marking.convertToInputting()
|
||||||
stateCallback(state)
|
stateCallback(state)
|
||||||
}
|
}
|
||||||
|
@ -224,41 +221,43 @@ import Cocoa
|
||||||
|
|
||||||
// MARK: Calling candidate window using Space or Down or PageUp / PageDn.
|
// MARK: Calling candidate window using Space or Down or PageUp / PageDn.
|
||||||
|
|
||||||
if isPhoneticReadingBufferEmpty() && (state is InputState.NotEmpty)
|
if let currentState = state as? InputState.NotEmpty {
|
||||||
&& (input.isExtraChooseCandidateKey || input.isExtraChooseCandidateKeyReverse || input.isSpace
|
if isPhoneticReadingBufferEmpty(),
|
||||||
|| input.isPageDown || input.isPageUp || input.isTab
|
input.isExtraChooseCandidateKey || input.isExtraChooseCandidateKeyReverse || input.isSpace
|
||||||
|| (input.useVerticalMode && (input.isVerticalModeOnlyChooseCandidateKey)))
|
|| input.isPageDown || input.isPageUp || input.isTab
|
||||||
{
|
|| (input.useVerticalMode && (input.isVerticalModeOnlyChooseCandidateKey))
|
||||||
if input.isSpace {
|
{
|
||||||
// If the Space key is NOT set to be a selection key
|
if input.isSpace {
|
||||||
if input.isShiftHold || !mgrPrefs.chooseCandidateUsingSpace {
|
// If the Space key is NOT set to be a selection key
|
||||||
if getBuilderCursorIndex() >= getBuilderLength() {
|
if input.isShiftHold || !mgrPrefs.chooseCandidateUsingSpace {
|
||||||
let composingBuffer = (state as! InputState.NotEmpty).composingBuffer
|
if getBuilderCursorIndex() >= getBuilderLength() {
|
||||||
if (composingBuffer.count) != 0 {
|
let composingBuffer = currentState.composingBuffer
|
||||||
let committing = InputState.Committing(poppedText: composingBuffer)
|
if (composingBuffer.count) != 0 {
|
||||||
|
let committing = InputState.Committing(poppedText: composingBuffer)
|
||||||
|
stateCallback(committing)
|
||||||
|
}
|
||||||
|
clear()
|
||||||
|
let committing = InputState.Committing(poppedText: " ")
|
||||||
stateCallback(committing)
|
stateCallback(committing)
|
||||||
|
let empty = InputState.Empty()
|
||||||
|
stateCallback(empty)
|
||||||
|
} else if ifLangModelHasUnigrams(forKey: " ") {
|
||||||
|
insertReadingToBuilder(atCursor: " ")
|
||||||
|
let poppedText = _popOverflowComposingTextAndWalk()
|
||||||
|
let inputting = buildInputtingState()
|
||||||
|
inputting.poppedText = poppedText
|
||||||
|
stateCallback(inputting)
|
||||||
}
|
}
|
||||||
clear()
|
return true
|
||||||
let committing = InputState.Committing(poppedText: " ")
|
|
||||||
stateCallback(committing)
|
|
||||||
let empty = InputState.Empty()
|
|
||||||
stateCallback(empty)
|
|
||||||
} else if ifLangModelHasUnigrams(forKey: " ") {
|
|
||||||
insertReadingToBuilder(atCursor: " ")
|
|
||||||
let poppedText = _popOverflowComposingTextAndWalk()
|
|
||||||
let inputting = buildInputtingState()
|
|
||||||
inputting.poppedText = poppedText
|
|
||||||
stateCallback(inputting)
|
|
||||||
}
|
}
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
let choosingCandidates = _buildCandidateState(
|
||||||
|
currentState,
|
||||||
|
useVerticalMode: input.useVerticalMode
|
||||||
|
)
|
||||||
|
stateCallback(choosingCandidates)
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
let choosingCandidates = _buildCandidateState(
|
|
||||||
state as! InputState.NotEmpty,
|
|
||||||
useVerticalMode: input.useVerticalMode
|
|
||||||
)
|
|
||||||
stateCallback(choosingCandidates)
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: -
|
// MARK: -
|
||||||
|
|
|
@ -228,11 +228,13 @@ import Cocoa
|
||||||
|
|
||||||
clear()
|
clear()
|
||||||
|
|
||||||
let current = state as! InputState.Inputting
|
if let current = state as? InputState.Inputting {
|
||||||
let composingBuffer = current.composingBuffer
|
let composingBuffer = current.composingBuffer
|
||||||
|
|
||||||
|
let committing = InputState.Committing(poppedText: composingBuffer)
|
||||||
|
stateCallback(committing)
|
||||||
|
}
|
||||||
|
|
||||||
let committing = InputState.Committing(poppedText: composingBuffer)
|
|
||||||
stateCallback(committing)
|
|
||||||
let empty = InputState.Empty()
|
let empty = InputState.Empty()
|
||||||
stateCallback(empty)
|
stateCallback(empty)
|
||||||
return true
|
return true
|
||||||
|
@ -468,37 +470,38 @@ import Cocoa
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
let currentState = state as! InputState.Inputting
|
if let currentState = state as? InputState.Inputting {
|
||||||
|
if input.isShiftHold {
|
||||||
if input.isShiftHold {
|
// Shift + Right
|
||||||
// Shift + Right
|
if currentState.cursorIndex < (currentState.composingBuffer as NSString).length {
|
||||||
if currentState.cursorIndex < (currentState.composingBuffer as NSString).length {
|
let nextPosition = (currentState.composingBuffer as NSString).nextUtf16Position(
|
||||||
let nextPosition = (currentState.composingBuffer as NSString).nextUtf16Position(
|
for: Int(currentState.cursorIndex))
|
||||||
for: Int(currentState.cursorIndex))
|
let marking: InputState.Marking! = InputState.Marking(
|
||||||
let marking: InputState.Marking! = InputState.Marking(
|
composingBuffer: currentState.composingBuffer,
|
||||||
composingBuffer: currentState.composingBuffer,
|
cursorIndex: currentState.cursorIndex,
|
||||||
cursorIndex: currentState.cursorIndex,
|
markerIndex: UInt(nextPosition),
|
||||||
markerIndex: UInt(nextPosition),
|
readings: _currentReadings()
|
||||||
readings: _currentReadings()
|
)
|
||||||
)
|
marking.tooltipForInputting = currentState.tooltip
|
||||||
marking.tooltipForInputting = currentState.tooltip
|
stateCallback(marking)
|
||||||
stateCallback(marking)
|
} else {
|
||||||
|
IME.prtDebugIntel("BB7F6DB9")
|
||||||
|
errorCallback()
|
||||||
|
stateCallback(state)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
IME.prtDebugIntel("BB7F6DB9")
|
if getBuilderCursorIndex() < getBuilderLength() {
|
||||||
errorCallback()
|
setBuilderCursorIndex(getBuilderCursorIndex() + 1)
|
||||||
stateCallback(state)
|
let inputting = buildInputtingState()
|
||||||
}
|
stateCallback(inputting)
|
||||||
} else {
|
} else {
|
||||||
if getBuilderCursorIndex() < getBuilderLength() {
|
IME.prtDebugIntel("A96AAD58")
|
||||||
setBuilderCursorIndex(getBuilderCursorIndex() + 1)
|
errorCallback()
|
||||||
let inputting = buildInputtingState()
|
stateCallback(state)
|
||||||
stateCallback(inputting)
|
}
|
||||||
} else {
|
|
||||||
IME.prtDebugIntel("A96AAD58")
|
|
||||||
errorCallback()
|
|
||||||
stateCallback(state)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -519,37 +522,38 @@ import Cocoa
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
let currentState = state as! InputState.Inputting
|
if let currentState = state as? InputState.Inputting {
|
||||||
|
if input.isShiftHold {
|
||||||
if input.isShiftHold {
|
// Shift + left
|
||||||
// Shift + left
|
if currentState.cursorIndex > 0 {
|
||||||
if currentState.cursorIndex > 0 {
|
let previousPosition = (currentState.composingBuffer as NSString).previousUtf16Position(
|
||||||
let previousPosition = (currentState.composingBuffer as NSString).previousUtf16Position(
|
for: Int(currentState.cursorIndex))
|
||||||
for: Int(currentState.cursorIndex))
|
let marking: InputState.Marking! = InputState.Marking(
|
||||||
let marking: InputState.Marking! = InputState.Marking(
|
composingBuffer: currentState.composingBuffer,
|
||||||
composingBuffer: currentState.composingBuffer,
|
cursorIndex: currentState.cursorIndex,
|
||||||
cursorIndex: currentState.cursorIndex,
|
markerIndex: UInt(previousPosition),
|
||||||
markerIndex: UInt(previousPosition),
|
readings: _currentReadings()
|
||||||
readings: _currentReadings()
|
)
|
||||||
)
|
marking.tooltipForInputting = currentState.tooltip
|
||||||
marking.tooltipForInputting = currentState.tooltip
|
stateCallback(marking)
|
||||||
stateCallback(marking)
|
} else {
|
||||||
|
IME.prtDebugIntel("D326DEA3")
|
||||||
|
errorCallback()
|
||||||
|
stateCallback(state)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
IME.prtDebugIntel("D326DEA3")
|
if getBuilderCursorIndex() > 0 {
|
||||||
errorCallback()
|
setBuilderCursorIndex(getBuilderCursorIndex() - 1)
|
||||||
stateCallback(state)
|
let inputting = buildInputtingState()
|
||||||
}
|
stateCallback(inputting)
|
||||||
} else {
|
} else {
|
||||||
if getBuilderCursorIndex() > 0 {
|
IME.prtDebugIntel("7045E6F3")
|
||||||
setBuilderCursorIndex(getBuilderCursorIndex() - 1)
|
errorCallback()
|
||||||
let inputting = buildInputtingState()
|
stateCallback(state)
|
||||||
stateCallback(inputting)
|
}
|
||||||
} else {
|
|
||||||
IME.prtDebugIntel("7045E6F3")
|
|
||||||
errorCallback()
|
|
||||||
stateCallback(state)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue