InputHandler // Remove stateCallback().

This commit is contained in:
ShikiSuen 2022-10-14 12:03:14 +08:00
parent 4522921a0f
commit 36a83f25a2
12 changed files with 223 additions and 233 deletions

View File

@ -174,7 +174,6 @@ extension InputHandler {
func handle(
input: InputHandler,
state: InputState,
stateCallback: @escaping (InputState) -> Void,
errorCallback: @escaping (String) -> Void
) -> Bool {
let charCode: UniChar = input.charCode
@ -217,7 +216,7 @@ if !skipPhoneticHandling && _composer.inputValidityCheck(key: charCode) {
// 有調號的話,則不需要這樣處理,轉而繼續在此之後的處理。
let composeReading = _composer.hasToneMarker()
if !composeReading {
stateCallback(generateStateOfInputting())
delegate.switchState(generateStateOfInputting())
return true
}
}
@ -246,7 +245,7 @@ if composeReading { // 符合按鍵組合條件
errorCallback("114514") // 向狀態管理引擎回呼一個錯誤狀態
_composer.clear() // 清空注拼槽的內容
// 根據「天權星引擎 (威注音) 或 Gramambular (小麥) 的組字器是否為空」來判定回呼哪一種狀態
stateCallback(
delegate.switchState(
(getCompositorLength() == 0) ? InputState.EmptyIgnoringPreviousState() : generateStateOfInputting())
return true // 向 IMK 報告說這個按鍵訊號已經被輸入法攔截處理了
}
@ -269,7 +268,7 @@ if composeReading { // 符合按鍵組合條件
// 再以回呼組字狀態的方式來執行updateClientComposingBuffer()
let inputting = generateStateOfInputting()
inputting.poppedText = poppedText
stateCallback(inputting)
delegate.switchState(inputting)
return true // 向 IMK 報告說這個按鍵訊號已經被輸入法攔截處理了
}

View File

@ -37,7 +37,7 @@ public protocol InputHandlerDelegate {
var selectionKeys: String { get }
var state: IMEStateProtocol { get set }
var clientBundleIdentifier: String { get }
func handle(state newState: IMEStateProtocol, replaceCurrent: Bool)
func switchState(_ newState: IMEStateProtocol)
func candidateController() -> CtlCandidateProtocol
func candidateSelectionCalledByInputHandler(at index: Int)
func performUserPhraseOperation(with state: IMEStateProtocol, addToFilter: Bool)

View File

@ -18,20 +18,20 @@ extension InputHandler {
/// - Parameters:
/// - input:
/// - state:
/// - stateCallback:
/// - errorCallback:
/// - Returns: IMK
func handleCandidate(
state: IMEStateProtocol,
input: InputSignalProtocol,
stateCallback: @escaping (IMEStateProtocol) -> Void,
errorCallback: @escaping (String) -> Void
) -> Bool {
guard var ctlCandidate = delegate?.candidateController() else {
guard let delegate = delegate else {
errorCallback("06661F6E")
return true
}
var ctlCandidate = delegate.candidateController()
// MARK: (Cancel Candidate)
let cancelCandidateKey =
@ -47,12 +47,12 @@ extension InputHandler {
//
// 使 BackSpace
// compositor.isEmpty
stateCallback(IMEState.ofAbortion())
delegate.switchState(IMEState.ofAbortion())
} else {
stateCallback(generateStateOfInputting())
delegate.switchState(generateStateOfInputting())
}
if state.type == .ofSymbolTable, let nodePrevious = state.node.previous, !nodePrevious.members.isEmpty {
stateCallback(IMEState.ofSymbolTable(node: nodePrevious))
delegate.switchState(IMEState.ofSymbolTable(node: nodePrevious))
}
return true
}
@ -61,10 +61,10 @@ extension InputHandler {
if input.isEnter {
if state.type == .ofAssociates, !prefs.alsoConfirmAssociatedCandidatesByEnter {
stateCallback(IMEState.ofAbortion())
delegate.switchState(IMEState.ofAbortion())
return true
}
delegate?.candidateSelectionCalledByInputHandler(at: ctlCandidate.selectedCandidateIndex)
delegate.candidateSelectionCalledByInputHandler(at: ctlCandidate.selectedCandidateIndex)
return true
}
@ -232,7 +232,7 @@ extension InputHandler {
let match: String =
(state.type == .ofAssociates) ? input.inputTextIgnoringModifiers ?? "" : input.text
let selectionKeys = delegate?.selectionKeys ?? PrefMgr.shared.candidateKeys
let selectionKeys = delegate.selectionKeys
for j in 0..<selectionKeys.count {
let label = selectionKeys.charComponents[j]
@ -245,7 +245,7 @@ extension InputHandler {
if index != NSNotFound {
let candidateIndex = ctlCandidate.candidateIndexAtKeyLabelIndex(index)
if candidateIndex != -114_514 {
delegate?.candidateSelectionCalledByInputHandler(at: candidateIndex)
delegate.candidateSelectionCalledByInputHandler(at: candidateIndex)
return true
}
}
@ -285,10 +285,10 @@ extension InputHandler {
if shouldAutoSelectCandidate {
let candidateIndex = ctlCandidate.candidateIndexAtKeyLabelIndex(0)
if candidateIndex != -114_514 {
delegate?.candidateSelectionCalledByInputHandler(at: candidateIndex)
stateCallback(IMEState.ofAbortion())
delegate.candidateSelectionCalledByInputHandler(at: candidateIndex)
delegate.switchState(IMEState.ofAbortion())
return handleInput(
event: input, state: IMEState.ofEmpty(), stateCallback: stateCallback, errorCallback: errorCallback
event: input, state: IMEState.ofEmpty(), errorCallback: errorCallback
)
}
return true

View File

@ -15,14 +15,14 @@ extension InputHandler {
/// InputHandler.HandleInput()
/// - Parameters:
/// - input:
/// - stateCallback:
/// - errorCallback:
/// - Returns: IMK
func handleComposition(
input: InputSignalProtocol,
stateCallback: @escaping (IMEStateProtocol) -> Void,
errorCallback: @escaping (String) -> Void
) -> Bool? {
guard let delegate = delegate else { return nil }
// MARK: (Handle BPMF Keys)
var keyConsumedByReading = false
@ -65,7 +65,7 @@ extension InputHandler {
// 調 setInlineDisplayWithCursor() return true
// 調
if !composer.hasToneMarker() {
stateCallback(generateStateOfInputting())
delegate.switchState(generateStateOfInputting())
return true
}
}
@ -90,16 +90,16 @@ extension InputHandler {
if prefs.keepReadingUponCompositionError {
composer.intonation.clear() // 調
stateCallback(generateStateOfInputting())
delegate.switchState(generateStateOfInputting())
return true
}
composer.clear()
//
switch compositor.isEmpty {
case false: stateCallback(generateStateOfInputting())
case false: delegate.switchState(generateStateOfInputting())
case true:
stateCallback(IMEState.ofAbortion())
delegate.switchState(IMEState.ofAbortion())
}
return true // IMK
}
@ -122,27 +122,27 @@ extension InputHandler {
// setInlineDisplayWithCursor()
var inputting = generateStateOfInputting()
inputting.textToCommit = textToCommit
stateCallback(inputting)
delegate.switchState(inputting)
///
if prefs.useSCPCTypingMode {
let candidateState: IMEStateProtocol = generateStateOfCandidates(state: inputting)
switch candidateState.candidates.count {
case 2...: stateCallback(candidateState)
case 2...: delegate.switchState(candidateState)
case 1:
let firstCandidate = candidateState.candidates.first! //
let reading: String = firstCandidate.0
let text: String = firstCandidate.1
stateCallback(IMEState.ofCommitting(textToCommit: text))
delegate.switchState(IMEState.ofCommitting(textToCommit: text))
if !prefs.associatedPhrasesEnabled {
stateCallback(IMEState.ofEmpty())
delegate.switchState(IMEState.ofEmpty())
} else {
let associatedPhrases =
generateStateOfAssociates(
withPair: .init(key: reading, value: text)
)
stateCallback(associatedPhrases.candidates.isEmpty ? IMEState.ofEmpty() : associatedPhrases)
delegate.switchState(associatedPhrases.candidates.isEmpty ? IMEState.ofEmpty() : associatedPhrases)
}
default: break
}
@ -154,7 +154,7 @@ extension InputHandler {
/// 調
if keyConsumedByReading {
// setInlineDisplayWithCursor()
stateCallback(generateStateOfInputting())
delegate.switchState(generateStateOfInputting())
return true
}
return nil

View File

@ -18,22 +18,18 @@ extension InputHandler {
/// - Parameter event: IMK
/// - Returns: `true` IMK`false`
public func handleEvent(_ event: NSEvent) -> Bool {
imkCandidatesEventPreHandler(event: event) ?? commonEventHandler(event)
imkCandidatesEventPreHandler(event: event) ?? doHandleInput(event)
}
/// 調
/// result bool IMK
/// handleCandidate()
private func commonEventHandler(_ event: NSEvent) -> Bool {
private func doHandleInput(_ event: NSEvent) -> Bool {
guard let delegate = delegate else { return false }
let result = handleInput(event: event, state: delegate.state) { newState in
delegate.handle(state: newState, replaceCurrent: true)
} errorCallback: { errorString in
return handleInput(event: event, state: delegate.state) { errorString in
vCLog(errorString)
IMEApp.buzz()
}
return result
}
/// IMK
@ -84,7 +80,7 @@ extension InputHandler {
let eventArray = [event]
guard let imkC = delegate.candidateController() as? CtlCandidateIMK else { return false }
if event.isEsc || event.isBackSpace || event.isDelete || (event.isShiftHold && !event.isSpace) {
return commonEventHandler(event)
return doHandleInput(event)
} else if event.isSymbolMenuPhysicalKey {
//
switch imkC.currentLayout {
@ -113,7 +109,7 @@ extension InputHandler {
if let newEvent = newEvent {
if prefs.useSCPCTypingMode, delegate.state.type == .ofAssociates {
// input.isShiftHold Self.handle()
return event.isShiftHold ? true : commonEventHandler(event)
return event.isShiftHold ? true : doHandleInput(event)
} else {
if #available(macOS 10.14, *) {
imkC.handleKeyboardEvent(newEvent)
@ -126,7 +122,7 @@ extension InputHandler {
}
if prefs.useSCPCTypingMode, !event.isReservedKey {
return commonEventHandler(event)
return doHandleInput(event)
}
if delegate.state.type == .ofAssociates,
@ -134,7 +130,7 @@ extension InputHandler {
!event.isCursorClockLeft, !event.isCursorClockRight, !event.isSpace,
!event.isEnter || !prefs.alsoConfirmAssociatedCandidatesByEnter
{
return commonEventHandler(event)
return doHandleInput(event)
}
imkC.interpretKeyEvents(eventArray)
return true

View File

@ -21,17 +21,17 @@ extension InputHandler {
/// - Parameters:
/// - input:
/// - state:
/// - stateCallback:
/// - errorCallback:
/// - Returns: IMK
func handleInput(
event input: InputSignalProtocol,
state: IMEStateProtocol,
stateCallback: @escaping (IMEStateProtocol) -> Void,
errorCallback: @escaping (String) -> Void
) -> Bool {
// inputTest
guard !input.text.isEmpty, input.charCode.isPrintable else { return false }
//
// delegate
guard !input.text.isEmpty, input.charCode.isPrintable, let delegate = delegate else { return false }
let inputText: String = input.text
var state = state //
@ -44,7 +44,7 @@ extension InputHandler {
return false
}
errorCallback("550BCF7B: InputHandler just refused an invalid input.")
stateCallback(state)
delegate.switchState(state)
return true
}
@ -66,7 +66,7 @@ extension InputHandler {
// BackSpace
} else if input.isCapsLockOn || state.isASCIIMode {
//
stateCallback(IMEState.ofEmpty())
delegate.switchState(IMEState.ofEmpty())
// Shift
if (input.isUpperCaseASCIILetterKey && state.isASCIIMode)
@ -82,8 +82,8 @@ extension InputHandler {
}
//
stateCallback(IMEState.ofCommitting(textToCommit: inputText.lowercased()))
stateCallback(IMEState.ofEmpty())
delegate.switchState(IMEState.ofCommitting(textToCommit: inputText.lowercased()))
delegate.switchState(IMEState.ofEmpty())
return true
}
@ -97,9 +97,9 @@ extension InputHandler {
if !(state.type == .ofCandidates || state.type == .ofAssociates
|| state.type == .ofSymbolTable)
{
stateCallback(IMEState.ofEmpty())
stateCallback(IMEState.ofCommitting(textToCommit: inputText.lowercased()))
stateCallback(IMEState.ofEmpty())
delegate.switchState(IMEState.ofEmpty())
delegate.switchState(IMEState.ofCommitting(textToCommit: inputText.lowercased()))
delegate.switchState(IMEState.ofEmpty())
return true
}
}
@ -108,7 +108,7 @@ extension InputHandler {
if [.ofCandidates, .ofSymbolTable].contains(state.type) {
return handleCandidate(
state: state, input: input, stateCallback: stateCallback, errorCallback: errorCallback
state: state, input: input, errorCallback: errorCallback
)
}
@ -116,11 +116,11 @@ extension InputHandler {
if state.type == .ofAssociates {
if handleCandidate(
state: state, input: input, stateCallback: stateCallback, errorCallback: errorCallback
state: state, input: input, errorCallback: errorCallback
) {
return true
} else {
stateCallback(IMEState.ofEmpty())
delegate.switchState(IMEState.ofEmpty())
}
}
@ -128,19 +128,19 @@ extension InputHandler {
if state.type == .ofMarking {
if handleMarkingState(
state, input: input, stateCallback: stateCallback,
state, input: input,
errorCallback: errorCallback
) {
return true
}
state = state.convertedToInputting
stateCallback(state)
delegate.switchState(state)
}
// MARK: (Handle BPMF Keys)
if let compositionHandled = handleComposition(
input: input, stateCallback: stateCallback, errorCallback: errorCallback
input: input, errorCallback: errorCallback
) {
return compositionHandled
}
@ -157,10 +157,10 @@ extension InputHandler {
if compositor.cursor >= compositor.length {
let displayedText = state.displayedText
if !displayedText.isEmpty {
stateCallback(IMEState.ofCommitting(textToCommit: displayedText))
delegate.switchState(IMEState.ofCommitting(textToCommit: displayedText))
}
stateCallback(IMEState.ofCommitting(textToCommit: " "))
stateCallback(IMEState.ofEmpty())
delegate.switchState(IMEState.ofCommitting(textToCommit: " "))
delegate.switchState(IMEState.ofEmpty())
} else if currentLM.hasUnigramsFor(key: " ") {
compositor.insertKey(" ")
walk()
@ -168,12 +168,12 @@ extension InputHandler {
let textToCommit = commitOverflownComposition
var inputting = generateStateOfInputting()
inputting.textToCommit = textToCommit
stateCallback(inputting)
delegate.switchState(inputting)
}
return true
} else if input.isShiftHold { // Tab Shift+Command+Space /
return handleInlineCandidateRotation(
state: state, reverseModifier: input.isCommandHold, stateCallback: stateCallback,
state: state, reverseModifier: input.isCommandHold,
errorCallback: errorCallback
)
}
@ -182,7 +182,7 @@ extension InputHandler {
if candidateState.candidates.isEmpty {
errorCallback("3572F238")
} else {
stateCallback(candidateState)
delegate.switchState(candidateState)
}
return true
}
@ -191,56 +191,56 @@ extension InputHandler {
if let keyCodeType = KeyCode(rawValue: input.keyCode) {
switch keyCodeType {
case .kEscape: return handleEsc(state: state, stateCallback: stateCallback)
case .kEscape: return handleEsc(state: state)
case .kTab:
return handleInlineCandidateRotation(
state: state, reverseModifier: input.isShiftHold, stateCallback: stateCallback, errorCallback: errorCallback
state: state, reverseModifier: input.isShiftHold, errorCallback: errorCallback
)
case .kUpArrow, .kDownArrow, .kLeftArrow, .kRightArrow:
if (input.isControlHold || input.isShiftHold) && (input.isOptionHold) {
if input.isLeft { // Ctrl+PgLf / Shift+PgLf
return handleHome(state: state, stateCallback: stateCallback, errorCallback: errorCallback)
return handleHome(state: state, errorCallback: errorCallback)
} else if input.isRight { // Ctrl+PgRt or Shift+PgRt
return handleEnd(state: state, stateCallback: stateCallback, errorCallback: errorCallback)
return handleEnd(state: state, errorCallback: errorCallback)
}
}
if input.isCursorBackward { // Forward
return handleBackward(
state: state, input: input, stateCallback: stateCallback, errorCallback: errorCallback
state: state, input: input, errorCallback: errorCallback
)
}
if input.isCursorForward { // Backward
return handleForward(
state: state, input: input, stateCallback: stateCallback, errorCallback: errorCallback
state: state, input: input, errorCallback: errorCallback
)
}
if input.isCursorClockLeft || input.isCursorClockRight { // Clock keys
if input.isOptionHold, state.type == .ofInputting {
if input.isCursorClockRight {
return handleInlineCandidateRotation(
state: state, reverseModifier: false, stateCallback: stateCallback, errorCallback: errorCallback
state: state, reverseModifier: false, errorCallback: errorCallback
)
}
if input.isCursorClockLeft {
return handleInlineCandidateRotation(
state: state, reverseModifier: true, stateCallback: stateCallback, errorCallback: errorCallback
state: state, reverseModifier: true, errorCallback: errorCallback
)
}
}
return handleClockKey(state: state, stateCallback: stateCallback, errorCallback: errorCallback)
return handleClockKey(state: state, errorCallback: errorCallback)
}
case .kHome: return handleHome(state: state, stateCallback: stateCallback, errorCallback: errorCallback)
case .kEnd: return handleEnd(state: state, stateCallback: stateCallback, errorCallback: errorCallback)
case .kHome: return handleHome(state: state, errorCallback: errorCallback)
case .kEnd: return handleEnd(state: state, errorCallback: errorCallback)
case .kBackSpace:
return handleBackSpace(state: state, input: input, stateCallback: stateCallback, errorCallback: errorCallback)
return handleBackSpace(state: state, input: input, errorCallback: errorCallback)
case .kWindowsDelete:
return handleDelete(state: state, input: input, stateCallback: stateCallback, errorCallback: errorCallback)
return handleDelete(state: state, input: input, errorCallback: errorCallback)
case .kCarriageReturn, .kLineFeed:
return (input.isCommandHold && input.isControlHold)
? (input.isOptionHold
? handleCtrlOptionCommandEnter(state: state, stateCallback: stateCallback)
: handleCtrlCommandEnter(state: state, stateCallback: stateCallback))
: handleEnter(state: state, stateCallback: stateCallback)
? handleCtrlOptionCommandEnter(state: state)
: handleCtrlCommandEnter(state: state))
: handleEnter(state: state)
default: break
}
}
@ -257,12 +257,12 @@ extension InputHandler {
let textToCommit = commitOverflownComposition
var inputting = generateStateOfInputting()
inputting.textToCommit = textToCommit
stateCallback(inputting)
delegate.switchState(inputting)
let candidateState = generateStateOfCandidates(state: inputting)
if candidateState.candidates.isEmpty {
errorCallback("B5127D8A")
} else {
stateCallback(candidateState)
delegate.switchState(candidateState)
}
} else { //
errorCallback("17446655")
@ -273,8 +273,8 @@ extension InputHandler {
// commit buffer ESC
// Enter 使 commit buffer
// bool _ =
_ = handleEnter(state: state, stateCallback: stateCallback)
stateCallback(IMEState.ofSymbolTable(node: CandidateNode.root))
_ = handleEnter(state: state)
delegate.switchState(IMEState.ofSymbolTable(node: CandidateNode.root))
return true
}
}
@ -286,10 +286,10 @@ extension InputHandler {
guard let stringRAW = input.mainAreaNumKeyChar else { return false }
let newStringFW = stringRAW.applyingTransform(.fullwidthToHalfwidth, reverse: true) ?? stringRAW
let newStringHW = stringRAW.applyingTransform(.fullwidthToHalfwidth, reverse: false) ?? stringRAW
stateCallback(
delegate.switchState(
IMEState.ofCommitting(textToCommit: prefs.halfWidthPunctuationEnabled ? newStringHW : newStringFW)
)
stateCallback(IMEState.ofEmpty())
delegate.switchState(IMEState.ofEmpty())
return true
}
}
@ -307,7 +307,6 @@ extension InputHandler {
if handlePunctuation(
customPunctuation,
state: state,
stateCallback: stateCallback,
errorCallback: errorCallback
) {
return true
@ -321,7 +320,6 @@ extension InputHandler {
if handlePunctuation(
punctuation,
state: state,
stateCallback: stateCallback,
errorCallback: errorCallback
) {
return true
@ -332,8 +330,8 @@ extension InputHandler {
/// 使
if state.type == .ofEmpty {
if input.isSpace, !input.isOptionHold, !input.isControlHold, !input.isCommandHold {
stateCallback(IMEState.ofCommitting(textToCommit: input.isShiftHold ? " " : " "))
stateCallback(IMEState.ofEmpty())
delegate.switchState(IMEState.ofCommitting(textToCommit: input.isShiftHold ? " " : " "))
delegate.switchState(IMEState.ofEmpty())
return true
}
}
@ -344,22 +342,21 @@ extension InputHandler {
if input.isShiftHold { // isOptionHold
switch prefs.upperCaseLetterKeyBehavior {
case 1:
stateCallback(IMEState.ofEmpty())
stateCallback(IMEState.ofCommitting(textToCommit: inputText.lowercased()))
stateCallback(IMEState.ofEmpty())
delegate.switchState(IMEState.ofEmpty())
delegate.switchState(IMEState.ofCommitting(textToCommit: inputText.lowercased()))
delegate.switchState(IMEState.ofEmpty())
return true
case 2:
stateCallback(IMEState.ofEmpty())
stateCallback(IMEState.ofCommitting(textToCommit: inputText.uppercased()))
stateCallback(IMEState.ofEmpty())
delegate.switchState(IMEState.ofEmpty())
delegate.switchState(IMEState.ofCommitting(textToCommit: inputText.uppercased()))
delegate.switchState(IMEState.ofEmpty())
return true
default: // case 0
let letter = "_letter_\(inputText)"
if handlePunctuation(
letter,
state: state,
stateCallback: stateCallback,
errorCallback: errorCallback
) {
return true
@ -378,7 +375,7 @@ extension InputHandler {
errorCallback(
"Blocked data: charCode: \(input.charCode), keyCode: \(input.keyCode)")
errorCallback("A9BFF20E")
stateCallback(state)
delegate.switchState(state)
return true
}

View File

@ -123,17 +123,17 @@ extension InputHandler {
/// - Parameters:
/// - state:
/// - input:
/// - stateCallback:
/// - errorCallback:
/// - Returns: SessionCtl IMK
func handleMarkingState(
_ state: IMEStateProtocol,
input: InputSignalProtocol,
stateCallback: @escaping (IMEStateProtocol) -> Void,
errorCallback: @escaping (String) -> Void
) -> Bool {
guard let delegate = delegate else { return false }
if input.isEsc {
stateCallback(generateStateOfInputting())
delegate.switchState(generateStateOfInputting())
return true
}
@ -145,38 +145,34 @@ extension InputHandler {
// Enter
if input.isEnter {
if let sessionCtl = delegate {
//
if input.isShiftHold, input.isCommandHold, !state.isFilterable {
errorCallback("2EAC1F7A")
return true
}
if !state.isMarkedLengthValid {
errorCallback("9AAFAC00")
return true
}
if !sessionCtl.performUserPhraseOperation(with: state, addToFilter: false) {
errorCallback("5B69CC8D")
return true
}
//
if input.isShiftHold, input.isCommandHold, !state.isFilterable {
errorCallback("2EAC1F7A")
return true
}
stateCallback(generateStateOfInputting())
if !state.isMarkedLengthValid {
errorCallback("9AAFAC00")
return true
}
if !delegate.performUserPhraseOperation(with: state, addToFilter: false) {
errorCallback("5B69CC8D")
return true
}
delegate.switchState(generateStateOfInputting())
return true
}
// BackSpace & Delete
if input.isBackSpace || input.isDelete {
if let inputHandlerDelegate = delegate {
if !state.isFilterable {
errorCallback("1F88B191")
return true
}
if !inputHandlerDelegate.performUserPhraseOperation(with: state, addToFilter: true) {
errorCallback("68D3C6C8")
return true
}
if !state.isFilterable {
errorCallback("1F88B191")
return true
}
stateCallback(generateStateOfInputting())
if !delegate.performUserPhraseOperation(with: state, addToFilter: true) {
errorCallback("68D3C6C8")
return true
}
delegate.switchState(generateStateOfInputting())
return true
}
@ -194,10 +190,10 @@ extension InputHandler {
marker: convertCursorForDisplay(compositor.marker)
)
marking.tooltipBackupForInputting = state.tooltipBackupForInputting
stateCallback(marking.markedRange.isEmpty ? marking.convertedToInputting : marking)
delegate.switchState(marking.markedRange.isEmpty ? marking.convertedToInputting : marking)
} else {
errorCallback("1149908D")
stateCallback(state)
delegate.switchState(state)
}
return true
}
@ -216,10 +212,10 @@ extension InputHandler {
marker: convertCursorForDisplay(compositor.marker)
)
marking.tooltipBackupForInputting = state.tooltipBackupForInputting
stateCallback(marking.markedRange.isEmpty ? marking.convertedToInputting : marking)
delegate.switchState(marking.markedRange.isEmpty ? marking.convertedToInputting : marking)
} else {
errorCallback("9B51408D")
stateCallback(state)
delegate.switchState(state)
}
return true
}
@ -231,15 +227,15 @@ extension InputHandler {
///
/// - Parameters:
/// - customPunctuation:
/// - stateCallback:
/// - errorCallback:
/// - Returns: SessionCtl IMK
func handlePunctuation(
_ customPunctuation: String,
state: IMEStateProtocol,
stateCallback: @escaping (IMEStateProtocol) -> Void,
errorCallback: @escaping (String) -> Void
) -> Bool {
guard let delegate = delegate else { return false }
if !currentLM.hasUnigramsFor(key: customPunctuation) {
return false
}
@ -247,7 +243,7 @@ extension InputHandler {
guard composer.isEmpty else {
//
errorCallback("A9B69908D")
stateCallback(state)
delegate.switchState(state)
return true
}
@ -257,21 +253,21 @@ extension InputHandler {
let textToCommit = commitOverflownComposition
var inputting = generateStateOfInputting()
inputting.textToCommit = textToCommit
stateCallback(inputting)
delegate.switchState(inputting)
//
guard prefs.useSCPCTypingMode, composer.isEmpty else { return true }
let candidateState = generateStateOfCandidates(state: inputting)
switch candidateState.candidates.count {
case 2...: stateCallback(candidateState)
case 2...: delegate.switchState(candidateState)
case 1:
clear() // candidateState
if let candidateToCommit: (String, String) = candidateState.candidates.first, !candidateToCommit.1.isEmpty {
stateCallback(IMEState.ofCommitting(textToCommit: candidateToCommit.1))
stateCallback(IMEState.ofEmpty())
delegate.switchState(IMEState.ofCommitting(textToCommit: candidateToCommit.1))
delegate.switchState(IMEState.ofEmpty())
} else {
stateCallback(candidateState)
delegate.switchState(candidateState)
}
default: errorCallback("8DA4096E")
}
@ -283,16 +279,15 @@ extension InputHandler {
/// Enter
/// - Parameters:
/// - state:
/// - stateCallback:
/// - Returns: SessionCtl IMK
func handleEnter(
state: IMEStateProtocol,
stateCallback: @escaping (IMEStateProtocol) -> Void
state: IMEStateProtocol
) -> Bool {
guard let delegate = delegate else { return false }
guard state.type == .ofInputting else { return false }
stateCallback(IMEState.ofCommitting(textToCommit: state.displayedText))
stateCallback(IMEState.ofEmpty())
delegate.switchState(IMEState.ofCommitting(textToCommit: state.displayedText))
delegate.switchState(IMEState.ofEmpty())
return true
}
@ -301,12 +296,11 @@ extension InputHandler {
/// Command+Enter
/// - Parameters:
/// - state:
/// - stateCallback:
/// - Returns: SessionCtl IMK
func handleCtrlCommandEnter(
state: IMEStateProtocol,
stateCallback: @escaping (IMEStateProtocol) -> Void
state: IMEStateProtocol
) -> Bool {
guard let delegate = delegate else { return false }
guard state.type == .ofInputting else { return false }
var displayedText = compositor.keys.joined(separator: "-")
@ -315,12 +309,12 @@ extension InputHandler {
displayedText = Tekkon.cnvPhonaToHanyuPinyin(target: displayedText) //
}
if let delegate = delegate, !delegate.clientBundleIdentifier.contains("vChewingPhraseEditor") {
if !delegate.clientBundleIdentifier.contains("vChewingPhraseEditor") {
displayedText = displayedText.replacingOccurrences(of: "-", with: " ")
}
stateCallback(IMEState.ofCommitting(textToCommit: displayedText))
stateCallback(IMEState.ofEmpty())
delegate.switchState(IMEState.ofCommitting(textToCommit: displayedText))
delegate.switchState(IMEState.ofEmpty())
return true
}
@ -329,12 +323,11 @@ extension InputHandler {
/// Command+Option+Enter Ruby
/// - Parameters:
/// - state:
/// - stateCallback:
/// - Returns: SessionCtl IMK
func handleCtrlOptionCommandEnter(
state: IMEStateProtocol,
stateCallback: @escaping (IMEStateProtocol) -> Void
state: IMEStateProtocol
) -> Bool {
guard let delegate = delegate else { return false }
guard state.type == .ofInputting else { return false }
var composed = ""
@ -355,8 +348,8 @@ extension InputHandler {
composed += key.contains("_") ? value : "<ruby>\(value)<rp>(</rp><rt>\(key)</rt><rp>)</rp></ruby>"
}
stateCallback(IMEState.ofCommitting(textToCommit: composed))
stateCallback(IMEState.ofEmpty())
delegate.switchState(IMEState.ofCommitting(textToCommit: composed))
delegate.switchState(IMEState.ofEmpty())
return true
}
@ -366,15 +359,14 @@ extension InputHandler {
/// - Parameters:
/// - state:
/// - input:
/// - stateCallback:
/// - errorCallback:
/// - Returns: SessionCtl IMK
func handleBackSpace(
state: IMEStateProtocol,
input: InputSignalProtocol,
stateCallback: @escaping (IMEStateProtocol) -> Void,
errorCallback: @escaping (String) -> Void
) -> Bool {
guard let delegate = delegate else { return false }
guard state.type == .ofInputting else { return false }
// macOS Shift+BackSpace
@ -386,16 +378,16 @@ extension InputHandler {
compositor.dropKey(direction: .rear)
walk() // Walk walk
prevReading.1.charComponents.forEach { composer.receiveKey(fromPhonabet: $0) }
stateCallback(generateStateOfInputting())
delegate.switchState(generateStateOfInputting())
return true
case 1:
stateCallback(IMEState.ofAbortion())
delegate.switchState(IMEState.ofAbortion())
return true
default: break
}
if input.isShiftHold, input.isOptionHold {
stateCallback(IMEState.ofAbortion())
delegate.switchState(IMEState.ofAbortion())
return true
}
@ -407,7 +399,7 @@ extension InputHandler {
walk()
} else {
errorCallback("9D69908D")
stateCallback(state)
delegate.switchState(state)
return true
}
} else {
@ -415,9 +407,9 @@ extension InputHandler {
}
switch composer.isEmpty && compositor.isEmpty {
case false: stateCallback(generateStateOfInputting())
case false: delegate.switchState(generateStateOfInputting())
case true:
stateCallback(IMEState.ofAbortion())
delegate.switchState(IMEState.ofAbortion())
}
return true
}
@ -428,25 +420,24 @@ extension InputHandler {
/// - Parameters:
/// - state:
/// - input:
/// - stateCallback:
/// - errorCallback:
/// - Returns: SessionCtl IMK
func handleDelete(
state: IMEStateProtocol,
input: InputSignalProtocol,
stateCallback: @escaping (IMEStateProtocol) -> Void,
errorCallback: @escaping (String) -> Void
) -> Bool {
guard let delegate = delegate else { return false }
guard state.type == .ofInputting else { return false }
if input.isShiftHold {
stateCallback(IMEState.ofAbortion())
delegate.switchState(IMEState.ofAbortion())
return true
}
if compositor.cursor == compositor.length, composer.isEmpty {
errorCallback("9B69938D")
stateCallback(state)
delegate.switchState(state)
return true
}
@ -460,9 +451,9 @@ extension InputHandler {
let inputting = generateStateOfInputting()
// count > 0!isEmpty滿
switch inputting.displayedText.isEmpty {
case false: stateCallback(inputting)
case false: delegate.switchState(inputting)
case true:
stateCallback(IMEState.ofAbortion())
delegate.switchState(IMEState.ofAbortion())
}
return true
}
@ -472,19 +463,18 @@ extension InputHandler {
/// 90
/// - Parameters:
/// - state:
/// - stateCallback:
/// - errorCallback:
/// - Returns: SessionCtl IMK
func handleClockKey(
state: IMEStateProtocol,
stateCallback: @escaping (IMEStateProtocol) -> Void,
errorCallback: @escaping (String) -> Void
) -> Bool {
guard let delegate = delegate else { return false }
guard state.type == .ofInputting else { return false }
if !composer.isEmpty {
errorCallback("9B6F908D")
}
stateCallback(state)
delegate.switchState(state)
return true
}
@ -493,28 +483,27 @@ extension InputHandler {
/// Home
/// - Parameters:
/// - state:
/// - stateCallback:
/// - errorCallback:
/// - Returns: SessionCtl IMK
func handleHome(
state: IMEStateProtocol,
stateCallback: @escaping (IMEStateProtocol) -> Void,
errorCallback: @escaping (String) -> Void
) -> Bool {
guard let delegate = delegate else { return false }
guard state.type == .ofInputting else { return false }
if !composer.isEmpty {
errorCallback("ABC44080")
stateCallback(state)
delegate.switchState(state)
return true
}
if compositor.cursor != 0 {
compositor.cursor = 0
stateCallback(generateStateOfInputting())
delegate.switchState(generateStateOfInputting())
} else {
errorCallback("66D97F90")
stateCallback(state)
delegate.switchState(state)
}
return true
@ -525,28 +514,27 @@ extension InputHandler {
/// End
/// - Parameters:
/// - state:
/// - stateCallback:
/// - errorCallback:
/// - Returns: SessionCtl IMK
func handleEnd(
state: IMEStateProtocol,
stateCallback: @escaping (IMEStateProtocol) -> Void,
errorCallback: @escaping (String) -> Void
) -> Bool {
guard let delegate = delegate else { return false }
guard state.type == .ofInputting else { return false }
if !composer.isEmpty {
errorCallback("9B69908D")
stateCallback(state)
delegate.switchState(state)
return true
}
if compositor.cursor != compositor.length {
compositor.cursor = compositor.length
stateCallback(generateStateOfInputting())
delegate.switchState(generateStateOfInputting())
} else {
errorCallback("9B69908E")
stateCallback(state)
delegate.switchState(state)
}
return true
@ -557,26 +545,25 @@ extension InputHandler {
/// Esc
/// - Parameters:
/// - state:
/// - stateCallback:
/// - Returns: SessionCtl IMK
func handleEsc(
state: IMEStateProtocol,
stateCallback: @escaping (IMEStateProtocol) -> Void
state: IMEStateProtocol
) -> Bool {
guard let delegate = delegate else { return false }
guard state.type == .ofInputting else { return false }
if prefs.escToCleanInputBuffer {
///
/// macOS Windows 使
stateCallback(IMEState.ofAbortion())
delegate.switchState(IMEState.ofAbortion())
} else {
if composer.isEmpty { return true }
///
composer.clear()
switch compositor.isEmpty {
case false: stateCallback(generateStateOfInputting())
case false: delegate.switchState(generateStateOfInputting())
case true:
stateCallback(IMEState.ofAbortion())
delegate.switchState(IMEState.ofAbortion())
}
}
return true
@ -588,20 +575,19 @@ extension InputHandler {
/// - Parameters:
/// - state:
/// - input:
/// - stateCallback:
/// - errorCallback:
/// - Returns: SessionCtl IMK
func handleForward(
state: IMEStateProtocol,
input: InputSignalProtocol,
stateCallback: @escaping (IMEStateProtocol) -> Void,
errorCallback: @escaping (String) -> Void
) -> Bool {
guard let delegate = delegate else { return false }
guard state.type == .ofInputting else { return false }
if !composer.isEmpty {
errorCallback("B3BA5257")
stateCallback(state)
delegate.switchState(state)
return true
}
@ -619,32 +605,32 @@ extension InputHandler {
marker: convertCursorForDisplay(compositor.marker)
)
marking.tooltipBackupForInputting = state.tooltip
stateCallback(marking)
delegate.switchState(marking)
} else {
errorCallback("BB7F6DB9")
stateCallback(state)
delegate.switchState(state)
}
} else if input.isOptionHold {
if input.isControlHold {
return handleEnd(state: state, stateCallback: stateCallback, errorCallback: errorCallback)
return handleEnd(state: state, errorCallback: errorCallback)
}
//
if !compositor.jumpCursorBySpan(to: .front) {
errorCallback("33C3B580")
stateCallback(state)
delegate.switchState(state)
return true
}
stateCallback(generateStateOfInputting())
delegate.switchState(generateStateOfInputting())
} else {
if compositor.cursor < compositor.length {
compositor.cursor += 1
if isCursorCuttingChar() {
compositor.jumpCursorBySpan(to: .front)
}
stateCallback(generateStateOfInputting())
delegate.switchState(generateStateOfInputting())
} else {
errorCallback("A96AAD58")
stateCallback(state)
delegate.switchState(state)
}
}
@ -657,20 +643,19 @@ extension InputHandler {
/// - Parameters:
/// - state:
/// - input:
/// - stateCallback:
/// - errorCallback:
/// - Returns: SessionCtl IMK
func handleBackward(
state: IMEStateProtocol,
input: InputSignalProtocol,
stateCallback: @escaping (IMEStateProtocol) -> Void,
errorCallback: @escaping (String) -> Void
) -> Bool {
guard let delegate = delegate else { return false }
guard state.type == .ofInputting else { return false }
if !composer.isEmpty {
errorCallback("6ED95318")
stateCallback(state)
delegate.switchState(state)
return true
}
@ -688,32 +673,32 @@ extension InputHandler {
marker: convertCursorForDisplay(compositor.marker)
)
marking.tooltipBackupForInputting = state.tooltip
stateCallback(marking)
delegate.switchState(marking)
} else {
errorCallback("D326DEA3")
stateCallback(state)
delegate.switchState(state)
}
} else if input.isOptionHold {
if input.isControlHold {
return handleHome(state: state, stateCallback: stateCallback, errorCallback: errorCallback)
return handleHome(state: state, errorCallback: errorCallback)
}
//
if !compositor.jumpCursorBySpan(to: .rear) {
errorCallback("8D50DD9E")
stateCallback(state)
delegate.switchState(state)
return true
}
stateCallback(generateStateOfInputting())
delegate.switchState(generateStateOfInputting())
} else {
if compositor.cursor > 0 {
compositor.cursor -= 1
if isCursorCuttingChar() {
compositor.jumpCursorBySpan(to: .rear)
}
stateCallback(generateStateOfInputting())
delegate.switchState(generateStateOfInputting())
} else {
errorCallback("7045E6F3")
stateCallback(state)
delegate.switchState(state)
}
}
@ -726,15 +711,14 @@ extension InputHandler {
/// - Parameters:
/// - state:
/// - reverseModifier:
/// - stateCallback:
/// - errorCallback:
/// - Returns: SessionCtl IMK
func handleInlineCandidateRotation(
state: IMEStateProtocol,
reverseModifier: Bool,
stateCallback: @escaping (IMEStateProtocol) -> Void,
errorCallback: @escaping (String) -> Void
) -> Bool {
guard let delegate = delegate else { return false }
if composer.isEmpty, compositor.isEmpty || compositor.walkedNodes.isEmpty { return false }
guard state.type == .ofInputting else {
guard state.type == .ofEmpty else {
@ -814,7 +798,7 @@ extension InputHandler {
consolidateNode(candidate: candidates[currentIndex], respectCursorPushing: false, preConsolidate: false)
stateCallback(generateStateOfInputting())
delegate.switchState(generateStateOfInputting())
return true
}
}

View File

@ -119,7 +119,7 @@ public class SessionCtl: IMKInputController {
// ----------------------------
Self.isVerticalTyping = isVerticalTyping
// 使
handle(state: IMEState.ofEmpty())
switchState(IMEState.ofEmpty())
}
}
}
@ -170,14 +170,14 @@ extension SessionCtl {
//
if state.type == .ofInputting, PrefMgr.shared.trimUnfinishedReadingsOnCommit {
inputHandler.composer.clear()
handle(state: inputHandler.generateStateOfInputting())
switchState(inputHandler.generateStateOfInputting())
}
let isSecureMode = PrefMgr.shared.clientsIMKTextInputIncapable.contains(clientBundleIdentifier)
if state.hasComposition, !isSecureMode {
/// 調
handle(state: IMEState.ofCommitting(textToCommit: state.displayedText))
switchState(IMEState.ofCommitting(textToCommit: state.displayedText))
}
handle(state: isSecureMode ? IMEState.ofAbortion() : IMEState.ofEmpty())
switchState(isSecureMode ? IMEState.ofAbortion() : IMEState.ofEmpty())
}
}
@ -208,7 +208,7 @@ extension SessionCtl {
UpdateSputnik.shared.checkForUpdate(forced: false, url: kUpdateInfoSourceURL)
}
handle(state: IMEState.ofEmpty())
switchState(IMEState.ofEmpty())
Self.allInstances.insert(self)
}
@ -217,7 +217,7 @@ extension SessionCtl {
public override func deactivateServer(_ sender: Any!) {
_ = sender //
resetInputHandler() // Empty
handle(state: IMEState.ofDeactivated())
switchState(IMEState.ofDeactivated())
Self.allInstances.remove(self)
}

View File

@ -75,11 +75,11 @@ extension SessionCtl: CtlCandidateDelegate {
if state.type == .ofSymbolTable, (0..<state.node.members.count).contains(index) {
let node = state.node.members[index]
if !node.members.isEmpty {
handle(state: IMEState.ofEmpty()) //
handle(state: IMEState.ofSymbolTable(node: node))
switchState(IMEState.ofEmpty()) //
switchState(IMEState.ofSymbolTable(node: node))
} else {
handle(state: IMEState.ofCommitting(textToCommit: node.name))
handle(state: IMEState.ofEmpty())
switchState(IMEState.ofCommitting(textToCommit: node.name))
switchState(IMEState.ofEmpty())
}
return
}
@ -94,29 +94,29 @@ extension SessionCtl: CtlCandidateDelegate {
let inputting = inputHandler.generateStateOfInputting()
if PrefMgr.shared.useSCPCTypingMode {
handle(state: IMEState.ofCommitting(textToCommit: inputting.displayedText))
switchState(IMEState.ofCommitting(textToCommit: inputting.displayedText))
// selectedValue.1
if PrefMgr.shared.associatedPhrasesEnabled {
let associates = inputHandler.generateStateOfAssociates(
withPair: .init(key: selectedValue.0, value: selectedValue.1)
)
handle(state: associates.candidates.isEmpty ? IMEState.ofEmpty() : associates)
switchState(associates.candidates.isEmpty ? IMEState.ofEmpty() : associates)
} else {
handle(state: IMEState.ofEmpty())
switchState(IMEState.ofEmpty())
}
} else {
handle(state: inputting)
switchState(inputting)
}
return
}
if state.type == .ofAssociates {
let selectedValue = state.candidates[index]
handle(state: IMEState.ofCommitting(textToCommit: selectedValue.1))
switchState(IMEState.ofCommitting(textToCommit: selectedValue.1))
// selectedValue.1
//
guard let valueKept = selectedValue.1.last else {
handle(state: IMEState.ofEmpty())
switchState(IMEState.ofEmpty())
return
}
if PrefMgr.shared.associatedPhrasesEnabled {
@ -124,11 +124,11 @@ extension SessionCtl: CtlCandidateDelegate {
withPair: .init(key: selectedValue.0, value: String(valueKept))
)
if !associates.candidates.isEmpty {
handle(state: associates)
switchState(associates)
return
}
}
handle(state: IMEState.ofEmpty())
switchState(IMEState.ofEmpty())
}
}
}

View File

@ -27,7 +27,7 @@ extension SessionCtl {
// deactivated empty()
if let client = client(), state.type == .ofDeactivated {
handle(state: IMEState.ofEmpty())
switchState(IMEState.ofEmpty())
return handle(event, client: client)
}

View File

@ -12,6 +12,20 @@ import Shared
// MARK: - 調 (State Handling)
extension SessionCtl {
/// 調
///
///
///
/// - Remark: (Static)
/// deactivateServer() 使
/// 使 SessionCtl
///
/// - Note: Swift Protocol
/// - Parameter newState:
public func switchState(_ newState: IMEStateProtocol) {
handle(state: newState, replace: true)
}
/// 調
///
///
@ -21,9 +35,9 @@ extension SessionCtl {
/// 使 SessionCtl
///
/// - Parameter newState:
public func handle(state newState: IMEStateProtocol, replaceCurrent: Bool = true) {
public func handle(state newState: IMEStateProtocol, replace: Bool) {
var previous = state
if replaceCurrent { state = newState }
if replace { state = newState }
switch newState.type {
case .ofDeactivated:
ctlCandidateCurrent.visible = false
@ -43,14 +57,14 @@ extension SessionCtl {
for instance in Self.allInstances {
guard let imkC = instance.ctlCandidateCurrent as? CtlCandidateIMK else { continue }
if instance.state.isCandidateContainer, !imkC.visible {
instance.handle(state: instance.state, replaceCurrent: false)
instance.handle(state: instance.state, replace: false)
}
}
}
case .ofEmpty, .ofAbortion:
if newState.type == .ofAbortion {
previous = IMEState.ofEmpty()
if replaceCurrent { state = previous }
if replace { state = previous }
}
ctlCandidateCurrent.visible = false
tooltipInstance.hide()

View File

@ -75,7 +75,7 @@ extension SessionCtl {
let candidateString: String = candidateString?.string ?? ""
if state.type == .ofAssociates {
if !PrefMgr.shared.alsoConfirmAssociatedCandidatesByEnter {
handle(state: IMEState.ofAbortion())
switchState(IMEState.ofAbortion())
return
}
}