InputHandler // +Enum: TypingMethod.
This commit is contained in:
parent
28e53c27ad
commit
e1b7a4df9f
|
@ -22,7 +22,6 @@ public protocol InputHandlerProtocol {
|
|||
var currentLM: vChewingLM.LMInstantiator { get set }
|
||||
var currentUOM: vChewingLM.LMUserOverride { get set }
|
||||
var delegate: InputHandlerDelegate? { get set }
|
||||
var composer: Tekkon.Composer { get set }
|
||||
var keySeparator: String { get }
|
||||
static var keySeparator: String { get }
|
||||
var isCompositorEmpty: Bool { get }
|
||||
|
@ -89,13 +88,17 @@ public class InputHandler: InputHandlerProtocol {
|
|||
|
||||
/// 用來記錄「叫出選字窗前」的游標位置的變數。
|
||||
var backupCursor: Int?
|
||||
/// 當前的打字模式。
|
||||
var currentTypingMethod: TypingMethod = .vChewingFactory
|
||||
|
||||
/// 半衰模組的衰減指數
|
||||
let kEpsilon: Double = 0.000_001
|
||||
|
||||
public var calligrapher = "" // 磁帶專用組筆區
|
||||
public var composer: Tekkon.Composer = .init() // 注拼槽
|
||||
public var compositor: Megrez.Compositor // 組字器
|
||||
var strCodePointBuffer = "" // 內碼輸入專用組碼區
|
||||
var calligrapher = "" // 磁帶專用組筆區
|
||||
var composer: Tekkon.Composer = .init() // 注拼槽
|
||||
var compositor: Megrez.Compositor // 組字器
|
||||
|
||||
public var currentUOM: vChewingLM.LMUserOverride
|
||||
public var currentLM: vChewingLM.LMInstantiator {
|
||||
didSet {
|
||||
|
@ -120,43 +123,13 @@ public class InputHandler: InputHandlerProtocol {
|
|||
public func clear() {
|
||||
clearComposerAndCalligrapher()
|
||||
compositor.clear()
|
||||
isCodePointInputMode = false
|
||||
isHaninKeyboardSymbolMode = false
|
||||
currentTypingMethod = .vChewingFactory
|
||||
backupCursor = nil
|
||||
}
|
||||
|
||||
/// 警告:該參數僅代指組音區/組筆區域與組字區在目前狀態下被視為「空」。
|
||||
var isConsideredEmptyForNow: Bool {
|
||||
compositor.isEmpty && isComposerOrCalligrapherEmpty && !isCodePointInputMode && !isHaninKeyboardSymbolMode
|
||||
}
|
||||
|
||||
// MARK: - Hanin Keyboard Symbol Mode.
|
||||
|
||||
var isHaninKeyboardSymbolMode = false
|
||||
|
||||
static let tooltipHaninKeyboardSymbolMode: String = "\("Hanin Keyboard Symbol Input.".localized)"
|
||||
|
||||
// MARK: - Codepoint Input Buffer.
|
||||
|
||||
var isCodePointInputMode = false {
|
||||
willSet {
|
||||
strCodePointBuffer.removeAll()
|
||||
}
|
||||
}
|
||||
|
||||
var strCodePointBuffer = ""
|
||||
|
||||
var tooltipCodePointInputMode: String {
|
||||
let commonTerm = NSMutableString()
|
||||
commonTerm.insert("Code Point Input.".localized, at: 0)
|
||||
if !(delegate?.isVerticalTyping ?? false) {
|
||||
switch IMEApp.currentInputMode {
|
||||
case .imeModeCHS: commonTerm.insert("[GB] ", at: 0)
|
||||
case .imeModeCHT: commonTerm.insert("[Big5] ", at: 0)
|
||||
default: break
|
||||
}
|
||||
}
|
||||
return commonTerm.description
|
||||
compositor.isEmpty && isComposerOrCalligrapherEmpty && currentTypingMethod == .vChewingFactory
|
||||
}
|
||||
|
||||
// MARK: - Functions dealing with Megrez.
|
||||
|
|
|
@ -311,7 +311,8 @@ extension InputHandler {
|
|||
if !updated { delegate.callError("66F3477B") }
|
||||
return true
|
||||
case .option where state.type == .ofSymbolTable:
|
||||
return handleHaninKeyboardSymbolModeToggle()
|
||||
// 繞過內碼輸入模式,直接進入漢音鍵盤符號模式。
|
||||
return revolveTypingMethod(to: .haninKeyboardSymbol)
|
||||
default: break
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,37 +17,29 @@ extension InputHandler {
|
|||
/// - Parameter input: 輸入訊號。
|
||||
/// - Returns: 告知 IMK「該按鍵是否已經被輸入法攔截處理」。
|
||||
func handleComposition(input: InputSignalProtocol) -> Bool? {
|
||||
guard let delegate = delegate else { return nil }
|
||||
// 不處理任何包含不可列印字元的訊號。
|
||||
guard !input.text.isEmpty, input.charCode.isPrintable else { return nil }
|
||||
if isCodePointInputMode { return handleCodePointComposition(input: input) }
|
||||
if prefs.cassetteEnabled {
|
||||
// 準備處理 `%quick` 選字行為。
|
||||
var handleQuickCandidate = true
|
||||
if currentLM.areCassetteCandidateKeysShiftHeld { handleQuickCandidate = input.isShiftHold }
|
||||
let hasQuickCandidates: Bool = delegate.state.type == .ofInputting && delegate.state.isCandidateContainer
|
||||
|
||||
// 處理 `%symboldef` 選字行為。
|
||||
if handleCassetteSymbolTable(input: input) {
|
||||
return true
|
||||
} else if hasQuickCandidates, input.text != currentLM.cassetteWildcardKey {
|
||||
// 處理 `%quick` 選字行為(當且僅當與 `%symboldef` 衝突的情況下)。
|
||||
guard !(handleQuickCandidate && handleCandidate(input: input, ignoringModifiers: true)) else { return true }
|
||||
} else {
|
||||
// 處理 `%quick` 選字行為。
|
||||
guard !(hasQuickCandidates && handleQuickCandidate && handleCandidate(input: input)) else { return true }
|
||||
}
|
||||
let hardRequirementMet = !input.text.isEmpty && input.charCode.isPrintable
|
||||
switch currentTypingMethod {
|
||||
case .codePoint where hardRequirementMet:
|
||||
return handleCodePointComposition(input: input)
|
||||
case .haninKeyboardSymbol where [[], .shift].contains(input.keyModifierFlags):
|
||||
return handleHaninKeyboardSymbolModeInput(input: input)
|
||||
case .vChewingFactory where hardRequirementMet && prefs.cassetteEnabled:
|
||||
return handleCassetteComposition(input: input)
|
||||
case .vChewingFactory where hardRequirementMet && !prefs.cassetteEnabled:
|
||||
return handlePhonabetComposition(input: input)
|
||||
default: return nil
|
||||
}
|
||||
return handlePhonabetComposition(input: input)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: 注音按鍵輸入處理 (Handle BPMF Keys)
|
||||
// MARK: - 注音按鍵輸入處理 (Handle BPMF Keys)
|
||||
|
||||
private extension InputHandler {
|
||||
/// 用來處理 InputHandler.HandleInput() 當中的與注音输入有關的組字行為。
|
||||
/// - Parameter input: 輸入訊號。
|
||||
/// - Returns: 告知 IMK「該按鍵是否已經被輸入法攔截處理」。
|
||||
private func handlePhonabetComposition(input: InputSignalProtocol) -> Bool? {
|
||||
func handlePhonabetComposition(input: InputSignalProtocol) -> Bool? {
|
||||
guard let delegate = delegate else { return nil }
|
||||
var inputText = (input.inputTextIgnoringModifiers ?? input.text)
|
||||
inputText = inputText.lowercased().applyingTransformFW2HW(reverse: false)
|
||||
|
@ -241,13 +233,31 @@ extension InputHandler {
|
|||
|
||||
// MARK: - 磁帶模式的組字支援。
|
||||
|
||||
extension InputHandler {
|
||||
/// 用來處理 InputHandler.HandleInput() 當中的與磁帶模組有關的組字行為。
|
||||
private extension InputHandler {
|
||||
/// 用來處理 InputHandler.HandleInput() 當中的與磁帶模組有關的組字行為。(前置處理)
|
||||
/// - Parameter input: 輸入訊號。
|
||||
/// - Returns: 告知 IMK「該按鍵是否已經被輸入法攔截處理」。
|
||||
private func handleCassetteComposition(input: InputSignalProtocol) -> Bool? {
|
||||
func handleCassetteComposition(input: InputSignalProtocol) -> Bool? {
|
||||
guard let delegate = delegate else { return nil }
|
||||
let state = delegate.state
|
||||
|
||||
// 準備處理 `%quick` 選字行為。
|
||||
var handleQuickCandidate = true
|
||||
if currentLM.areCassetteCandidateKeysShiftHeld { handleQuickCandidate = input.isShiftHold }
|
||||
let hasQuickCandidates: Bool = state.type == .ofInputting && state.isCandidateContainer
|
||||
|
||||
// 處理 `%symboldef` 選字行為。
|
||||
if handleCassetteSymbolTable(input: input) {
|
||||
return true
|
||||
} else if hasQuickCandidates, input.text != currentLM.cassetteWildcardKey {
|
||||
// 處理 `%quick` 選字行為(當且僅當與 `%symboldef` 衝突的情況下)。
|
||||
guard !(handleQuickCandidate && handleCandidate(input: input, ignoringModifiers: true)) else { return true }
|
||||
} else {
|
||||
// 處理 `%quick` 選字行為。
|
||||
guard !(hasQuickCandidates && handleQuickCandidate && handleCandidate(input: input)) else { return true }
|
||||
}
|
||||
|
||||
// 正式處理。
|
||||
var wildcardKey: String { currentLM.cassetteWildcardKey } // 花牌鍵。
|
||||
let inputText = input.text
|
||||
let isWildcardKeyInput: Bool = (inputText == wildcardKey && !wildcardKey.isEmpty)
|
||||
|
@ -266,7 +276,7 @@ extension InputHandler {
|
|||
calligrapher.count >= currentLM.maxCassetteKeyLength || isLongestPossibleKeyFormed
|
||||
}
|
||||
|
||||
prehandling: if !skipStrokeHandling && currentLM.isThisCassetteKeyAllowed(key: inputText) {
|
||||
prehandling: if !skipStrokeHandling && currentLM.isThisCassetteKeyAllowed(key: inputText) {
|
||||
if calligrapher.isEmpty, isWildcardKeyInput {
|
||||
delegate.callError("3606B9C0")
|
||||
if input.beganWithLetter {
|
||||
|
@ -385,16 +395,17 @@ extension InputHandler {
|
|||
// 將「這個按鍵訊號已經被輸入法攔截處理了」的結果藉由 SessionCtl 回報給 IMK。
|
||||
return true
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: 內碼區位輸入處理 (Handle Code Point Input)
|
||||
// MARK: - 內碼區位輸入處理 (Handle Code Point Input)
|
||||
|
||||
private extension InputHandler {
|
||||
/// 用來處理 InputHandler.HandleInput() 當中的與內碼區位輸入有關的組字行為。
|
||||
/// - Parameter input: 輸入訊號。
|
||||
/// - Returns: 告知 IMK「該按鍵是否已經被輸入法攔截處理」。
|
||||
private func handleCodePointComposition(input: InputSignalProtocol) -> Bool? {
|
||||
func handleCodePointComposition(input: InputSignalProtocol) -> Bool? {
|
||||
guard !input.isReservedKey else { return nil }
|
||||
guard let delegate = delegate, input.text.count == 1 else { return nil }
|
||||
guard !input.text.compactMap(\.hexDigitValue).isEmpty else {
|
||||
|
@ -407,7 +418,7 @@ extension InputHandler {
|
|||
strCodePointBuffer.append(input.text)
|
||||
var updatedState = generateStateOfInputting(guarded: true)
|
||||
updatedState.tooltipDuration = 0
|
||||
updatedState.tooltip = tooltipCodePointInputMode
|
||||
updatedState.tooltip = TypingMethod.codePoint.getTooltip(vertical: delegate.isVerticalTyping)
|
||||
delegate.switchState(updatedState)
|
||||
return true
|
||||
}
|
||||
|
@ -427,7 +438,7 @@ extension InputHandler {
|
|||
updatedState.tooltipDuration = 0
|
||||
updatedState.tooltip = "Invalid Code Point.".localized
|
||||
delegate.switchState(updatedState)
|
||||
isCodePointInputMode = true
|
||||
currentTypingMethod = .codePoint
|
||||
return true
|
||||
}
|
||||
// 某些舊版 macOS 會在這裡生成的字元後面插入垃圾字元。這裡只保留起始字元。
|
||||
|
@ -435,14 +446,46 @@ extension InputHandler {
|
|||
delegate.switchState(IMEState.ofCommitting(textToCommit: char))
|
||||
var updatedState = generateStateOfInputting(guarded: true)
|
||||
updatedState.tooltipDuration = 0
|
||||
updatedState.tooltip = tooltipCodePointInputMode
|
||||
updatedState.tooltip = TypingMethod.codePoint.getTooltip(vertical: delegate.isVerticalTyping)
|
||||
delegate.switchState(updatedState)
|
||||
isCodePointInputMode = true
|
||||
currentTypingMethod = .codePoint
|
||||
return true
|
||||
default:
|
||||
delegate.switchState(generateStateOfInputting())
|
||||
isCodePointInputMode = true
|
||||
currentTypingMethod = .codePoint
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - 處理漢音鍵盤符號輸入狀態(Handle Hanin Keyboard Symbol Inputs)
|
||||
|
||||
private extension InputHandler {
|
||||
/// 處理漢音鍵盤符號輸入。
|
||||
/// - Parameters:
|
||||
/// - input: 輸入按鍵訊號。
|
||||
/// - Returns: 將按鍵行為「是否有處理掉」藉由 SessionCtl 回報給 IMK。
|
||||
func handleHaninKeyboardSymbolModeInput(input: InputSignalProtocol) -> Bool {
|
||||
guard let delegate = delegate, delegate.state.type != .ofDeactivated else { return false }
|
||||
let charText = input.text.lowercased().applyingTransformFW2HW(reverse: false)
|
||||
guard CandidateNode.mapHaninKeyboardSymbols.keys.contains(charText) else {
|
||||
return revolveTypingMethod(to: .vChewingFactory)
|
||||
}
|
||||
guard
|
||||
charText.count == 1, let symbols = CandidateNode.queryHaninKeyboardSymbols(char: charText)
|
||||
else {
|
||||
delegate.callError("C1A760C7")
|
||||
return true
|
||||
}
|
||||
// 得在這裡先 commit buffer,不然會導致「在摁 ESC 離開符號選單時會重複輸入上一次的組字區的內容」的不當行為。
|
||||
let textToCommit = generateStateOfInputting(sansReading: true).displayedText
|
||||
delegate.switchState(IMEState.ofCommitting(textToCommit: textToCommit))
|
||||
if symbols.members.count == 1 {
|
||||
delegate.switchState(IMEState.ofCommitting(textToCommit: symbols.members.map(\.name).joined()))
|
||||
} else {
|
||||
delegate.switchState(IMEState.ofSymbolTable(node: symbols))
|
||||
}
|
||||
currentTypingMethod = .vChewingFactory // 用完就關掉,但保持選字窗開啟,所以這裡不用呼叫 toggle 函式。
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,17 +27,18 @@ extension InputHandler {
|
|||
if isConsideredEmptyForNow, !guarded { return IMEState.ofAbortion() }
|
||||
restoreBackupCursor() // 只要叫了 Inputting 狀態,就盡可能還原游標備份。
|
||||
var segHighlightedAt: Int?
|
||||
let cpInput = isCodePointInputMode && !sansReading
|
||||
let handleAsCodePointInput = currentTypingMethod == .codePoint && !sansReading
|
||||
/// 「更新內文組字區 (Update the composing buffer)」是指要求客體軟體將組字緩衝區的內容
|
||||
/// 換成由此處重新生成的原始資料在 IMEStateData 當中生成的 NSAttributeString。
|
||||
var displayTextSegments: [String] = cpInput
|
||||
var displayTextSegments: [String] = handleAsCodePointInput
|
||||
? [strCodePointBuffer]
|
||||
: compositor.walkedNodes.values
|
||||
var cursor = cpInput
|
||||
var cursor = handleAsCodePointInput
|
||||
? displayTextSegments.joined().count
|
||||
: convertCursorForDisplay(compositor.cursor)
|
||||
let cursorSansReading = cursor
|
||||
let reading: String = (sansReading || isCodePointInputMode) ? "" : readingForDisplay // 先提出來,減輕運算負擔。
|
||||
// 先提出來讀音資料,減輕運算負擔。
|
||||
let reading: String = (sansReading || currentTypingMethod == .codePoint) ? "" : readingForDisplay
|
||||
if !reading.isEmpty {
|
||||
var newDisplayTextSegments = [String]()
|
||||
var temporaryNode = ""
|
||||
|
@ -361,8 +362,9 @@ extension InputHandler {
|
|||
guard let delegate = delegate else { return false }
|
||||
let state = delegate.state
|
||||
|
||||
if isHaninKeyboardSymbolMode { return handleHaninKeyboardSymbolModeToggle() }
|
||||
if isCodePointInputMode { return handleCodePointInputToggle() }
|
||||
guard currentTypingMethod == .vChewingFactory else {
|
||||
return revolveTypingMethod(to: .vChewingFactory)
|
||||
}
|
||||
|
||||
guard state.type == .ofInputting else { return false }
|
||||
|
||||
|
@ -470,31 +472,28 @@ extension InputHandler {
|
|||
guard let delegate = delegate else { return false }
|
||||
let state = delegate.state
|
||||
guard state.type == .ofInputting else {
|
||||
isCodePointInputMode = false
|
||||
currentTypingMethod = .vChewingFactory
|
||||
return false
|
||||
}
|
||||
|
||||
if isCodePointInputMode {
|
||||
if currentTypingMethod == .codePoint {
|
||||
if !strCodePointBuffer.isEmpty {
|
||||
func refreshState() {
|
||||
var updatedState = generateStateOfInputting(guarded: true)
|
||||
updatedState.tooltipDuration = 0
|
||||
updatedState.tooltip = tooltipCodePointInputMode
|
||||
updatedState.tooltip = delegate.state.tooltip
|
||||
delegate.switchState(updatedState)
|
||||
}
|
||||
strCodePointBuffer = strCodePointBuffer.dropLast(1).description
|
||||
if input.commonKeyModifierFlags == .option {
|
||||
strCodePointBuffer.removeAll()
|
||||
refreshState()
|
||||
isCodePointInputMode = true
|
||||
return true
|
||||
return revolveTypingMethod(to: .codePoint)
|
||||
}
|
||||
if !strCodePointBuffer.isEmpty {
|
||||
refreshState()
|
||||
return true
|
||||
}
|
||||
}
|
||||
return handleCodePointInputToggle()
|
||||
return revolveTypingMethod(to: .vChewingFactory)
|
||||
}
|
||||
|
||||
// 引入 macOS 內建注音輸入法的行為,允許用 Shift+BackSpace 解構前一個漢字的讀音。
|
||||
|
@ -575,8 +574,9 @@ extension InputHandler {
|
|||
guard let delegate = delegate else { return false }
|
||||
let state = delegate.state
|
||||
|
||||
if isHaninKeyboardSymbolMode { return handleHaninKeyboardSymbolModeToggle() }
|
||||
if isCodePointInputMode { return handleCodePointInputToggle() }
|
||||
guard currentTypingMethod == .vChewingFactory else {
|
||||
return revolveTypingMethod(to: .vChewingFactory)
|
||||
}
|
||||
|
||||
guard state.type == .ofInputting else { return false }
|
||||
|
||||
|
@ -684,8 +684,9 @@ extension InputHandler {
|
|||
guard let delegate = delegate else { return false }
|
||||
let state = delegate.state
|
||||
|
||||
if isHaninKeyboardSymbolMode { return handleHaninKeyboardSymbolModeToggle() }
|
||||
if isCodePointInputMode { return handleCodePointInputToggle() }
|
||||
guard currentTypingMethod == .vChewingFactory else {
|
||||
return revolveTypingMethod(to: .vChewingFactory)
|
||||
}
|
||||
|
||||
guard state.type == .ofInputting else { return false }
|
||||
|
||||
|
@ -920,73 +921,6 @@ extension InputHandler {
|
|||
return true
|
||||
}
|
||||
|
||||
// MARK: - 處理內碼區位輸入狀態的啟動過程(CodePoint Input Toggle)
|
||||
|
||||
@discardableResult func handleCodePointInputToggle() -> Bool {
|
||||
guard let delegate = delegate, delegate.state.type != .ofDeactivated else { return false }
|
||||
if isCodePointInputMode {
|
||||
isCodePointInputMode = false
|
||||
delegate.switchState(IMEState.ofAbortion())
|
||||
return true
|
||||
}
|
||||
var updatedState = generateStateOfInputting(sansReading: true)
|
||||
delegate.switchState(IMEState.ofCommitting(textToCommit: updatedState.displayedText))
|
||||
updatedState = generateStateOfInputting(guarded: true)
|
||||
updatedState.tooltipDuration = 0
|
||||
updatedState.tooltip = tooltipCodePointInputMode
|
||||
delegate.switchState(updatedState)
|
||||
isCodePointInputMode = true
|
||||
return true
|
||||
}
|
||||
|
||||
// MARK: - 處理漢音鍵盤符號輸入狀態的啟動過程(Hanin Pallete)
|
||||
|
||||
@discardableResult func handleHaninKeyboardSymbolModeToggle() -> Bool {
|
||||
guard let delegate = delegate, delegate.state.type != .ofDeactivated else { return false }
|
||||
if isCodePointInputMode { isCodePointInputMode = false }
|
||||
if isHaninKeyboardSymbolMode {
|
||||
isHaninKeyboardSymbolMode = false
|
||||
delegate.switchState(IMEState.ofAbortion())
|
||||
return true
|
||||
}
|
||||
var updatedState = generateStateOfInputting(sansReading: true)
|
||||
delegate.switchState(IMEState.ofCommitting(textToCommit: updatedState.displayedText))
|
||||
updatedState = generateStateOfInputting(guarded: true)
|
||||
updatedState.tooltipDuration = 0
|
||||
updatedState.tooltip = Self.tooltipHaninKeyboardSymbolMode
|
||||
delegate.switchState(updatedState)
|
||||
isHaninKeyboardSymbolMode = true
|
||||
return true
|
||||
}
|
||||
|
||||
/// 處理漢音鍵盤符號輸入。
|
||||
/// - Parameters:
|
||||
/// - input: 輸入按鍵訊號。
|
||||
/// - Returns: 將按鍵行為「是否有處理掉」藉由 SessionCtl 回報給 IMK。
|
||||
func handleHaninKeyboardSymbolModeInput(input: InputSignalProtocol) -> Bool {
|
||||
guard let delegate = delegate, delegate.state.type != .ofDeactivated else { return false }
|
||||
let charText = input.text.lowercased().applyingTransformFW2HW(reverse: false)
|
||||
guard CandidateNode.mapHaninKeyboardSymbols.keys.contains(charText) else {
|
||||
return handleHaninKeyboardSymbolModeToggle()
|
||||
}
|
||||
guard
|
||||
charText.count == 1, let symbols = CandidateNode.queryHaninKeyboardSymbols(char: charText)
|
||||
else {
|
||||
delegate.callError("C1A760C7")
|
||||
return true
|
||||
}
|
||||
// 得在這裡先 commit buffer,不然會導致「在摁 ESC 離開符號選單時會重複輸入上一次的組字區的內容」的不當行為。
|
||||
let textToCommit = generateStateOfInputting(sansReading: true).displayedText
|
||||
delegate.switchState(IMEState.ofCommitting(textToCommit: textToCommit))
|
||||
if symbols.members.count == 1 {
|
||||
delegate.switchState(IMEState.ofCommitting(textToCommit: symbols.members.map(\.name).joined()))
|
||||
} else {
|
||||
delegate.switchState(IMEState.ofSymbolTable(node: symbols))
|
||||
}
|
||||
isHaninKeyboardSymbolMode = false // 用完就關掉,但保持選字窗開啟,所以這裡不用呼叫 toggle 函式。
|
||||
return true
|
||||
}
|
||||
|
||||
// MARK: - 處理符號選單(Symbol Menu Input)
|
||||
|
||||
/// 處理符號選單。
|
||||
|
|
|
@ -48,7 +48,7 @@ public extension InputHandler {
|
|||
case .kCarriageReturn, .kLineFeed:
|
||||
let frontNode = compositor.walkedNodes.last
|
||||
return handleEnter(input: input) {
|
||||
guard !self.isHaninKeyboardSymbolMode, !self.isCodePointInputMode else { return [] }
|
||||
guard self.currentTypingMethod == .vChewingFactory else { return [] }
|
||||
guard let frontNode = frontNode else { return [] }
|
||||
let pair = Megrez.KeyValuePaired(keyArray: frontNode.keyArray, value: frontNode.value)
|
||||
let associates = self.generateArrayOfAssociates(withPair: pair)
|
||||
|
@ -62,13 +62,7 @@ public extension InputHandler {
|
|||
case [.option, .shift]:
|
||||
return handlePunctuationList(alternative: true, isJIS: isJIS)
|
||||
case .option:
|
||||
switch (isCodePointInputMode, isHaninKeyboardSymbolMode) {
|
||||
case (false, false): return handleCodePointInputToggle()
|
||||
case (true, false), (false, true):
|
||||
return handleHaninKeyboardSymbolModeToggle()
|
||||
default: break
|
||||
}
|
||||
return true
|
||||
return revolveTypingMethod()
|
||||
default: break
|
||||
}
|
||||
case .kSpace:
|
||||
|
@ -85,7 +79,7 @@ public extension InputHandler {
|
|||
if input.isShiftHold, !input.isControlHold, !input.isOptionHold {
|
||||
return revolveCandidate(reverseOrder: input.isCommandHold)
|
||||
}
|
||||
if isCodePointInputMode {
|
||||
if currentTypingMethod == .codePoint {
|
||||
delegate.callError("FDD88EDB")
|
||||
delegate.switchState(IMEState.ofAbortion())
|
||||
return true
|
||||
|
@ -148,13 +142,11 @@ public extension InputHandler {
|
|||
guard let x = input.inputTextIgnoringModifiers,
|
||||
"¥\\".contains(x), input.keyModifierFlags.isEmpty
|
||||
else { break haninSymbolInput }
|
||||
return handleHaninKeyboardSymbolModeToggle()
|
||||
return revolveTypingMethod(to: .haninKeyboardSymbol)
|
||||
}
|
||||
|
||||
// 注音按鍵輸入與漢音鍵盤符號輸入處理。
|
||||
if isHaninKeyboardSymbolMode, [[], .shift].contains(input.keyModifierFlags) {
|
||||
return handleHaninKeyboardSymbolModeInput(input: input)
|
||||
} else if let compositionHandled = handleComposition(input: input) {
|
||||
// 注音/磁帶按鍵輸入與漢音鍵盤符號輸入處理。
|
||||
if let compositionHandled = handleComposition(input: input) {
|
||||
return compositionHandled
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
// (c) 2021 and onwards The vChewing Project (MIT-NTL License).
|
||||
// ====================
|
||||
// This code is released under the MIT license (SPDX-License-Identifier: MIT)
|
||||
// ... with NTL restriction stating that:
|
||||
// No trademark license is granted to use the trade names, trademarks, service
|
||||
// marks, or product names of Contributor, except as required to fulfill notice
|
||||
// requirements defined in MIT License.
|
||||
|
||||
import Foundation
|
||||
import SwiftExtension
|
||||
|
||||
// MARK: - Typing Method
|
||||
|
||||
public extension InputHandler {
|
||||
enum TypingMethod: Int, CaseIterable {
|
||||
case vChewingFactory // 自動指派: 0
|
||||
case codePoint // 自動指派: 1
|
||||
case haninKeyboardSymbol // 自動指派: 2
|
||||
|
||||
mutating func revolveNext() {
|
||||
var theInt = rawValue
|
||||
theInt.revolveAsIndex(with: Self.allCases)
|
||||
guard let nextMethod = TypingMethod(rawValue: theInt) else { return }
|
||||
self = nextMethod
|
||||
}
|
||||
|
||||
func getTooltip(vertical: Bool = false) -> String {
|
||||
switch self {
|
||||
case .vChewingFactory: return ""
|
||||
case .codePoint:
|
||||
let commonTerm = NSMutableString()
|
||||
commonTerm.insert("Code Point Input.".localized, at: 0)
|
||||
if !vertical {
|
||||
switch IMEApp.currentInputMode {
|
||||
case .imeModeCHS: commonTerm.insert("[GB] ", at: 0)
|
||||
case .imeModeCHT: commonTerm.insert("[Big5] ", at: 0)
|
||||
default: break
|
||||
}
|
||||
}
|
||||
return commonTerm.description
|
||||
case .haninKeyboardSymbol:
|
||||
return "\("Hanin Keyboard Symbol Input.".localized)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Handle Rotation Toggles
|
||||
|
||||
public extension InputHandler {
|
||||
@discardableResult func revolveTypingMethod(to specifiedMethod: TypingMethod? = nil) -> Bool {
|
||||
guard let delegate = delegate else { return false }
|
||||
var newMethod = currentTypingMethod
|
||||
if let specified = specifiedMethod {
|
||||
newMethod = specified
|
||||
} else {
|
||||
newMethod.revolveNext()
|
||||
}
|
||||
/// 接下來這行必須這樣 defer 處理,
|
||||
/// 因為再接下來的 switch newMethod 的過程會影響到 currentTypingMethod 參數。
|
||||
defer {
|
||||
currentTypingMethod = newMethod
|
||||
}
|
||||
switch newMethod {
|
||||
case .vChewingFactory:
|
||||
delegate.switchState(IMEState.ofAbortion())
|
||||
return true
|
||||
case .codePoint:
|
||||
strCodePointBuffer.removeAll()
|
||||
case .haninKeyboardSymbol: break
|
||||
}
|
||||
var updatedState = generateStateOfInputting(sansReading: true)
|
||||
delegate.switchState(IMEState.ofCommitting(textToCommit: updatedState.displayedText))
|
||||
updatedState = generateStateOfInputting(guarded: true)
|
||||
updatedState.tooltipDuration = 0
|
||||
updatedState.tooltip = newMethod.getTooltip(vertical: delegate.isVerticalTyping)
|
||||
delegate.switchState(updatedState)
|
||||
return true
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue