KeyHandler // Swiftify: day 4.
This commit is contained in:
parent
b17e3f45a4
commit
6139879d68
|
@ -47,11 +47,6 @@ extern InputMode imeModeNULL;
|
||||||
@interface KeyHandler : NSObject
|
@interface KeyHandler : NSObject
|
||||||
|
|
||||||
- (BOOL)isBuilderEmpty;
|
- (BOOL)isBuilderEmpty;
|
||||||
- (BOOL)handleInput:(keyParser *)input
|
|
||||||
state:(InputState *)state
|
|
||||||
stateCallback:(void (^)(InputState *))stateCallback
|
|
||||||
errorCallback:(void (^)(void))errorCallback
|
|
||||||
NS_SWIFT_NAME(handle(input:state:stateCallback:errorCallback:));
|
|
||||||
|
|
||||||
- (void)fixNodeWithValue:(NSString *)value NS_SWIFT_NAME(fixNode(value:));
|
- (void)fixNodeWithValue:(NSString *)value NS_SWIFT_NAME(fixNode(value:));
|
||||||
- (void)clear;
|
- (void)clear;
|
||||||
|
@ -63,34 +58,34 @@ extern InputMode imeModeNULL;
|
||||||
@property(weak, nonatomic) id<KeyHandlerDelegate> delegate;
|
@property(weak, nonatomic) id<KeyHandlerDelegate> delegate;
|
||||||
|
|
||||||
// The following items need to be exposed to Swift:
|
// The following items need to be exposed to Swift:
|
||||||
|
- (void)_walk;
|
||||||
- (NSString *)_popOverflowComposingTextAndWalk;
|
- (NSString *)_popOverflowComposingTextAndWalk;
|
||||||
|
- (NSArray<NSString *> *)_currentReadings;
|
||||||
- (BOOL)_handleCandidateState:(InputState *)state
|
|
||||||
input:(keyParser *)input
|
|
||||||
stateCallback:(void (^)(InputState *))stateCallback
|
|
||||||
errorCallback:(void (^)(void))errorCallback
|
|
||||||
NS_SWIFT_NAME(handleCandidate(state:input:stateCallback:errorCallback:));
|
|
||||||
|
|
||||||
- (BOOL)checkWhetherToneMarkerConfirmsPhoneticReadingBuffer;
|
- (BOOL)checkWhetherToneMarkerConfirmsPhoneticReadingBuffer;
|
||||||
- (BOOL)chkKeyValidity:(UniChar)value;
|
- (BOOL)chkKeyValidity:(UniChar)value;
|
||||||
|
- (BOOL)ifLangModelHasUnigramsForKey:(NSString *)reading;
|
||||||
- (BOOL)isPhoneticReadingBufferEmpty;
|
- (BOOL)isPhoneticReadingBufferEmpty;
|
||||||
|
- (BOOL)isPrintable:(UniChar)charCode;
|
||||||
|
- (NSArray<NSString *> *)getCandidatesArray;
|
||||||
|
- (NSInteger)getBuilderCursorIndex;
|
||||||
|
- (NSInteger)getBuilderLength;
|
||||||
|
- (NSString *)_currentMandarinParser;
|
||||||
- (NSString *)getCompositionFromPhoneticReadingBuffer;
|
- (NSString *)getCompositionFromPhoneticReadingBuffer;
|
||||||
- (NSString *)getSyllableCompositionFromPhoneticReadingBuffer;
|
- (NSString *)getSyllableCompositionFromPhoneticReadingBuffer;
|
||||||
- (void)clearPhoneticReadingBuffer;
|
- (void)clearPhoneticReadingBuffer;
|
||||||
- (void)combinePhoneticReadingBufferKey:(UniChar)charCode;
|
- (void)combinePhoneticReadingBufferKey:(UniChar)charCode;
|
||||||
- (void)doBackSpaceToPhoneticReadingBuffer;
|
|
||||||
- (void)removeBuilderAndReset:(BOOL)shouldReset;
|
|
||||||
- (void)createNewBuilder;
|
- (void)createNewBuilder;
|
||||||
|
- (void)dealWithOverrideModelSuggestions;
|
||||||
|
- (void)deleteBuilderReadingAfterCursor;
|
||||||
|
- (void)deleteBuilderReadingInFrontOfCursor;
|
||||||
|
- (void)doBackSpaceToPhoneticReadingBuffer;
|
||||||
|
- (void)ensurePhoneticParser;
|
||||||
|
- (void)insertReadingToBuilderAtCursor:(NSString *)reading;
|
||||||
|
- (void)removeBuilderAndReset:(BOOL)shouldReset;
|
||||||
|
- (void)setBuilderCursorIndex:(NSInteger)value;
|
||||||
- (void)setInputModesToLM:(BOOL)isCHS;
|
- (void)setInputModesToLM:(BOOL)isCHS;
|
||||||
- (void)syncBaseLMPrefs;
|
- (void)syncBaseLMPrefs;
|
||||||
- (void)ensurePhoneticParser;
|
|
||||||
- (BOOL)ifLangModelHasUnigramsForKey:(NSString *)reading;
|
|
||||||
- (void)insertReadingToBuilderAtCursor:(NSString *)reading;
|
|
||||||
- (BOOL)isPrintable:(UniChar)charCode;
|
|
||||||
- (void)dealWithOverrideModelSuggestions;
|
|
||||||
- (NSMutableArray *)getCandidatesArray;
|
|
||||||
- (NSInteger)getBuilderCursorIndex;
|
|
||||||
- (NSInteger)getBuilderLength;
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,33 @@
|
||||||
|
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License).
|
||||||
|
// Refactored from the ObjCpp-version of this class by:
|
||||||
|
// (c) 2011 and onwards The OpenVanilla Project (MIT License).
|
||||||
|
/*
|
||||||
|
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
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
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,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
1. The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
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
|
||||||
|
requirements above.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
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
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Cocoa
|
||||||
|
|
||||||
|
// MARK: - § Build Input State.
|
||||||
|
|
||||||
|
@objc extension KeyHandler {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,328 @@
|
||||||
|
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License).
|
||||||
|
// Refactored from the ObjCpp-version of this class by:
|
||||||
|
// (c) 2011 and onwards The OpenVanilla Project (MIT License).
|
||||||
|
/*
|
||||||
|
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
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
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,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
1. The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
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
|
||||||
|
requirements above.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
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
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Cocoa
|
||||||
|
|
||||||
|
// MARK: - § Handle Candidate State.
|
||||||
|
@objc extension KeyHandler {
|
||||||
|
func _handleCandidateState(
|
||||||
|
_ state: InputState,
|
||||||
|
input: keyParser,
|
||||||
|
stateCallback: @escaping (InputState) -> Void,
|
||||||
|
errorCallback: @escaping () -> Void
|
||||||
|
) -> Bool {
|
||||||
|
let inputText = input.inputText
|
||||||
|
let charCode: UniChar = input.charCode
|
||||||
|
let ctlCandidateCurrent = delegate!.ctlCandidate(for: self) as! ctlCandidate
|
||||||
|
|
||||||
|
let cancelCandidateKey =
|
||||||
|
input.isBackSpace || input.isESC || input.isDelete
|
||||||
|
|| ((input.isCursorBackward || input.isCursorForward) && input.isShiftHold)
|
||||||
|
|
||||||
|
if cancelCandidateKey {
|
||||||
|
if state is InputState.AssociatedPhrases {
|
||||||
|
clear()
|
||||||
|
let empty = InputState.EmptyIgnoringPreviousState()
|
||||||
|
stateCallback(empty)
|
||||||
|
} else if mgrPrefs.useSCPCTypingMode {
|
||||||
|
clear()
|
||||||
|
let empty = InputState.EmptyIgnoringPreviousState()
|
||||||
|
stateCallback(empty)
|
||||||
|
} else if isBuilderEmpty() {
|
||||||
|
// 如果此時發現當前組字緩衝區為真空的情況的話,
|
||||||
|
// 就將當前的組字緩衝區析構處理、強制重設輸入狀態。
|
||||||
|
// 否則,一個本不該出現的真空組字緩衝區會使前後方向鍵與 BackSpace 鍵失靈。
|
||||||
|
clear()
|
||||||
|
let empty = InputState.EmptyIgnoringPreviousState()
|
||||||
|
stateCallback(empty)
|
||||||
|
} else {
|
||||||
|
let inputting = buildInputtingState() as! InputState.Inputting
|
||||||
|
stateCallback(inputting)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.isEnter {
|
||||||
|
if state is InputState.AssociatedPhrases {
|
||||||
|
clear()
|
||||||
|
let empty = InputState.EmptyIgnoringPreviousState()
|
||||||
|
stateCallback(empty)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
delegate!.keyHandler(
|
||||||
|
self,
|
||||||
|
didSelectCandidateAt: Int(ctlCandidateCurrent.selectedCandidateIndex),
|
||||||
|
ctlCandidate: ctlCandidateCurrent)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.isTab {
|
||||||
|
let updated: Bool =
|
||||||
|
mgrPrefs.specifyShiftTabKeyBehavior
|
||||||
|
? (input.isShiftHold ? ctlCandidateCurrent.showPreviousPage() : ctlCandidateCurrent.showNextPage())
|
||||||
|
: (input.isShiftHold
|
||||||
|
? ctlCandidateCurrent.highlightPreviousCandidate()
|
||||||
|
: ctlCandidateCurrent.highlightNextCandidate())
|
||||||
|
if !updated {
|
||||||
|
IME.prtDebugIntel("9B691919")
|
||||||
|
errorCallback()
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.isSpace {
|
||||||
|
let updated: Bool =
|
||||||
|
mgrPrefs.specifyShiftSpaceKeyBehavior
|
||||||
|
? (input.isShiftHold
|
||||||
|
? ctlCandidateCurrent.highlightNextCandidate()
|
||||||
|
: ctlCandidateCurrent.showNextPage())
|
||||||
|
: (input.isShiftHold
|
||||||
|
? ctlCandidateCurrent.showNextPage()
|
||||||
|
: ctlCandidateCurrent.highlightNextCandidate())
|
||||||
|
if !updated {
|
||||||
|
IME.prtDebugIntel("A11C781F")
|
||||||
|
errorCallback()
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.isPageDown || input.emacsKey == vChewingEmacsKey.nextPage {
|
||||||
|
let updated: Bool = ctlCandidateCurrent.showNextPage()
|
||||||
|
if !updated {
|
||||||
|
IME.prtDebugIntel("9B691919")
|
||||||
|
errorCallback()
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.isPageUp {
|
||||||
|
let updated: Bool = ctlCandidateCurrent.showPreviousPage()
|
||||||
|
if !updated {
|
||||||
|
IME.prtDebugIntel("9569955D")
|
||||||
|
errorCallback()
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.emacsKey == vChewingEmacsKey.backward {
|
||||||
|
let updated: Bool = ctlCandidateCurrent.highlightPreviousCandidate()
|
||||||
|
if !updated {
|
||||||
|
IME.prtDebugIntel("9B89308D")
|
||||||
|
errorCallback()
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.isRight {
|
||||||
|
if ctlCandidateCurrent is ctlCandidateHorizontal {
|
||||||
|
let updated: Bool = ctlCandidateCurrent.highlightNextCandidate()
|
||||||
|
if !updated {
|
||||||
|
IME.prtDebugIntel("9B65138D")
|
||||||
|
errorCallback()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let updated: Bool = ctlCandidateCurrent.showNextPage()
|
||||||
|
if !updated {
|
||||||
|
IME.prtDebugIntel("9244908D")
|
||||||
|
errorCallback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.emacsKey == vChewingEmacsKey.forward {
|
||||||
|
let updated: Bool = ctlCandidateCurrent.highlightNextCandidate()
|
||||||
|
if !updated {
|
||||||
|
IME.prtDebugIntel("9B2428D")
|
||||||
|
errorCallback()
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
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 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 input.isHome || input.emacsKey == vChewingEmacsKey.home {
|
||||||
|
if ctlCandidateCurrent.selectedCandidateIndex == 0 {
|
||||||
|
IME.prtDebugIntel("9B6EDE8D")
|
||||||
|
errorCallback()
|
||||||
|
} else {
|
||||||
|
ctlCandidateCurrent.selectedCandidateIndex = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
var candidates: [String]!
|
||||||
|
|
||||||
|
if state is InputState.ChoosingCandidate {
|
||||||
|
candidates = (state as! InputState.ChoosingCandidate).candidates
|
||||||
|
} else if state is InputState.AssociatedPhrases {
|
||||||
|
candidates = (state as! InputState.AssociatedPhrases).candidates
|
||||||
|
}
|
||||||
|
|
||||||
|
if candidates.isEmpty { return false }
|
||||||
|
|
||||||
|
if (input.isEnd || input.emacsKey == vChewingEmacsKey.end) && candidates.count > 0 {
|
||||||
|
if ctlCandidateCurrent.selectedCandidateIndex == UInt(candidates.count - 1) {
|
||||||
|
IME.prtDebugIntel("9B69AAAD")
|
||||||
|
errorCallback()
|
||||||
|
} else {
|
||||||
|
ctlCandidateCurrent.selectedCandidateIndex = UInt(candidates.count - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if state is InputState.AssociatedPhrases {
|
||||||
|
if !input.isShiftHold { return false }
|
||||||
|
}
|
||||||
|
|
||||||
|
var index: Int = NSNotFound
|
||||||
|
var match: String!
|
||||||
|
if state is InputState.AssociatedPhrases { match = input.inputTextIgnoringModifiers } else { match = inputText }
|
||||||
|
|
||||||
|
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 {
|
||||||
|
let candidateIndex: UInt = ctlCandidateCurrent.candidateIndexAtKeyLabelIndex(UInt(index))
|
||||||
|
if candidateIndex != UInt.max {
|
||||||
|
delegate!.keyHandler(self, didSelectCandidateAt: Int(candidateIndex), ctlCandidate: ctlCandidateCurrent)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if state is InputState.AssociatedPhrases { return false }
|
||||||
|
|
||||||
|
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: String! = _currentMandarinParser()
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IME.prtDebugIntel("172A0F81")
|
||||||
|
errorCallback()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,16 +26,17 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
import Cocoa
|
import Cocoa
|
||||||
|
|
||||||
// MARK: - § Handle Inputs (WIP).
|
// MARK: - § Handle Input with States.
|
||||||
|
|
||||||
@objc extension KeyHandler {
|
@objc extension KeyHandler {
|
||||||
func handleInputSwift(
|
func handle(
|
||||||
input: keyParser,
|
input: keyParser,
|
||||||
state inState: InputState,
|
state inState: InputState,
|
||||||
stateCallback: @escaping (InputState) -> Void,
|
stateCallback: @escaping (InputState) -> Void,
|
||||||
errorCallback: @escaping () -> Void
|
errorCallback: @escaping () -> Void
|
||||||
) -> Bool {
|
) -> Bool {
|
||||||
let charCode: UniChar = input.charCode
|
let charCode: UniChar = input.charCode
|
||||||
var state = inState // Turn this incoming constant to variable.
|
var state = inState // Turn this incoming constant into variable.
|
||||||
let inputText: String = input.inputText ?? ""
|
let inputText: String = input.inputText ?? ""
|
||||||
let emptyState = InputState.Empty()
|
let emptyState = InputState.Empty()
|
||||||
|
|
||||||
|
@ -102,14 +103,14 @@ import Cocoa
|
||||||
|
|
||||||
// MARK: Handle Candidates.
|
// MARK: Handle Candidates.
|
||||||
if state is InputState.ChoosingCandidate {
|
if state is InputState.ChoosingCandidate {
|
||||||
return handleCandidate(
|
return _handleCandidateState(
|
||||||
state: state, input: input, stateCallback: stateCallback, errorCallback: errorCallback)
|
state, input: input, stateCallback: stateCallback, errorCallback: errorCallback)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Handle Associated Phrases.
|
// MARK: Handle Associated Phrases.
|
||||||
if state is InputState.AssociatedPhrases {
|
if state is InputState.AssociatedPhrases {
|
||||||
let result = handleCandidate(
|
let result = _handleCandidateState(
|
||||||
state: state, input: input, stateCallback: stateCallback, errorCallback: errorCallback)
|
state, input: input, stateCallback: stateCallback, errorCallback: errorCallback)
|
||||||
if result {
|
if result {
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
|
@ -221,7 +222,7 @@ import Cocoa
|
||||||
|| (input.useVerticalMode && (input.isVerticalModeOnlyChooseCandidateKey)))
|
|| (input.useVerticalMode && (input.isVerticalModeOnlyChooseCandidateKey)))
|
||||||
{
|
{
|
||||||
if input.isSpace {
|
if input.isSpace {
|
||||||
// If the spacebar is NOT set to be a selection key
|
// If the Space key is NOT set to be a selection key
|
||||||
if input.isShiftHold || !mgrPrefs.chooseCandidateUsingSpace {
|
if input.isShiftHold || !mgrPrefs.chooseCandidateUsingSpace {
|
||||||
if getBuilderCursorIndex() >= getBuilderLength() {
|
if getBuilderCursorIndex() >= getBuilderLength() {
|
||||||
let composingBuffer = (state as! InputState.NotEmpty).composingBuffer
|
let composingBuffer = (state as! InputState.NotEmpty).composingBuffer
|
||||||
|
@ -251,11 +252,161 @@ import Cocoa
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Function Keys.
|
// MARK: -
|
||||||
|
|
||||||
// MARK: Esc
|
// MARK: Esc
|
||||||
|
if input.isESC { return _handleEscWithState(state, stateCallback: stateCallback, errorCallback: errorCallback) }
|
||||||
|
|
||||||
// MARK: Still Nothing.
|
// MARK: Cursor backward
|
||||||
|
if input.isCursorBackward || input.emacsKey == vChewingEmacsKey.backward {
|
||||||
|
return _handleBackwardWithState(
|
||||||
|
state,
|
||||||
|
input: input,
|
||||||
|
stateCallback: stateCallback,
|
||||||
|
errorCallback: errorCallback)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Cursor forward
|
||||||
|
if input.isCursorForward || input.emacsKey == vChewingEmacsKey.forward {
|
||||||
|
return _handleForwardWithState(
|
||||||
|
state, input: input, stateCallback: stateCallback, errorCallback: errorCallback)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Home
|
||||||
|
if input.isHome || input.emacsKey == vChewingEmacsKey.home {
|
||||||
|
return _handleHomeWithState(state, stateCallback: stateCallback, errorCallback: errorCallback)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: End
|
||||||
|
if input.isEnd || input.emacsKey == vChewingEmacsKey.end {
|
||||||
|
return _handleEndWithState(state, stateCallback: stateCallback, errorCallback: errorCallback)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Ctrl+PgLf or Shift+PgLf
|
||||||
|
if (input.isControlHold || input.isShiftHold) && (input.isOptionHold && input.isLeft) {
|
||||||
|
return _handleHomeWithState(state, stateCallback: stateCallback, errorCallback: errorCallback)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Ctrl+PgRt or Shift+PgRt
|
||||||
|
if (input.isControlHold || input.isShiftHold) && (input.isOptionHold && input.isRight) {
|
||||||
|
return _handleEndWithState(state, stateCallback: stateCallback, errorCallback: errorCallback)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: AbsorbedArrowKey
|
||||||
|
if input.isAbsorbedArrowKey || input.isExtraChooseCandidateKey || input.isExtraChooseCandidateKeyReverse {
|
||||||
|
return _handleAbsorbedArrowKeyWithState(state, stateCallback: stateCallback, errorCallback: errorCallback)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Backspace
|
||||||
|
if input.isBackSpace {
|
||||||
|
return _handleBackspaceWithState(state, stateCallback: stateCallback, errorCallback: errorCallback)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Delete
|
||||||
|
if input.isDelete || input.emacsKey == vChewingEmacsKey.delete {
|
||||||
|
return _handleDeleteWithState(state, stateCallback: stateCallback, errorCallback: errorCallback)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Enter
|
||||||
|
if input.isEnter {
|
||||||
|
return (input.isCommandHold)
|
||||||
|
? _handleCommandEnterWithState(state, stateCallback: stateCallback, errorCallback: errorCallback)
|
||||||
|
: _handleEnterWithState(state, stateCallback: stateCallback, errorCallback: errorCallback)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: -
|
||||||
|
|
||||||
|
// MARK: Punctuation list
|
||||||
|
if input.isSymbolMenuPhysicalKey && !input.isShiftHold {
|
||||||
|
if !input.isOptionHold {
|
||||||
|
if ifLangModelHasUnigrams(forKey: "_punctuation_list") {
|
||||||
|
if isPhoneticReadingBufferEmpty() {
|
||||||
|
insertReadingToBuilder(atCursor: "_punctuation_list")
|
||||||
|
let poppedText: String! = _popOverflowComposingTextAndWalk()
|
||||||
|
let inputting = buildInputtingState() as! InputState.Inputting
|
||||||
|
inputting.poppedText = poppedText
|
||||||
|
stateCallback(inputting)
|
||||||
|
let choosingCandidate =
|
||||||
|
_buildCandidateState(inputting, useVerticalMode: input.useVerticalMode)
|
||||||
|
stateCallback(choosingCandidate)
|
||||||
|
} else { // If there is still unfinished bpmf reading, ignore the punctuation
|
||||||
|
IME.prtDebugIntel("17446655")
|
||||||
|
errorCallback()
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 得在這裡先 commit buffer,不然會導致「在摁 ESC 離開符號選單時會重複輸入上一次的組字區的內容」的不當行為。
|
||||||
|
// 於是這裡用「模擬一次 Enter 鍵的操作」使其代為執行這個 commit buffer 的動作。
|
||||||
|
// 這裡不需要該函數所傳回的 bool 結果,所以用「_ =」解消掉。
|
||||||
|
_ = _handleEnterWithState(state, stateCallback: stateCallback, errorCallback: errorCallback)
|
||||||
|
let root: SymbolNode! = SymbolNode.root
|
||||||
|
let symbolState =
|
||||||
|
InputState.SymbolTable(node: root, useVerticalMode: input.useVerticalMode)
|
||||||
|
stateCallback(symbolState)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Punctuation
|
||||||
|
// if nothing is matched, see if it's a punctuation key for current layout.
|
||||||
|
|
||||||
|
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: String! = _currentMandarinParser()
|
||||||
|
let arrCustomPunctuations: [String] = [
|
||||||
|
punctuationNamePrefix, parser, String(format: "%c", CChar(charCode)),
|
||||||
|
]
|
||||||
|
let customPunctuation: String = arrCustomPunctuations.joined(separator: "")
|
||||||
|
if _handlePunctuation(
|
||||||
|
customPunctuation,
|
||||||
|
state: state,
|
||||||
|
usingVerticalMode: input.useVerticalMode,
|
||||||
|
stateCallback: stateCallback,
|
||||||
|
errorCallback: errorCallback)
|
||||||
|
{
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// if nothing is matched, see if it's a punctuation key.
|
||||||
|
let arrPunctuations: [String] = [punctuationNamePrefix, String(format: "%c", CChar(charCode))]
|
||||||
|
let punctuation: String = arrPunctuations.joined(separator: "")
|
||||||
|
|
||||||
|
if _handlePunctuation(
|
||||||
|
punctuation,
|
||||||
|
state: state,
|
||||||
|
usingVerticalMode: input.useVerticalMode,
|
||||||
|
stateCallback: stateCallback,
|
||||||
|
errorCallback: errorCallback)
|
||||||
|
{
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 這裡不使用小麥注音 2.2 版的組字區處理方式,而是直接由詞庫負責。
|
||||||
|
if input.isUpperCaseASCIILetterKey {
|
||||||
|
let letter: String! = String(format: "%@%c", "_letter_", CChar(charCode))
|
||||||
|
if _handlePunctuation(
|
||||||
|
letter,
|
||||||
|
state: state,
|
||||||
|
usingVerticalMode: input.useVerticalMode,
|
||||||
|
stateCallback: stateCallback,
|
||||||
|
errorCallback: errorCallback)
|
||||||
|
{
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Still Nothing.
|
||||||
// Still nothing? Then we update the composing buffer.
|
// Still nothing? Then we update the composing buffer.
|
||||||
// Note that some app has strange behavior if we don't do this,
|
// Note that some app has strange behavior if we don't do this,
|
||||||
// "thinking" that the key is not actually consumed.
|
// "thinking" that the key is not actually consumed.
|
|
@ -0,0 +1,43 @@
|
||||||
|
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License).
|
||||||
|
// Refactored from the ObjCpp-version of this class by:
|
||||||
|
// (c) 2011 and onwards The OpenVanilla Project (MIT License).
|
||||||
|
/*
|
||||||
|
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
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
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,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
1. The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
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
|
||||||
|
requirements above.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
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
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Cocoa
|
||||||
|
|
||||||
|
// MARK: - § Misc functions.
|
||||||
|
@objc extension KeyHandler {
|
||||||
|
func _actualCandidateCursorIndex() -> Int {
|
||||||
|
var cursorIndex = getBuilderCursorIndex()
|
||||||
|
// MS Phonetics IME style, phrase is *after* the cursor.
|
||||||
|
// (i.e. the cursor is always *before* the phrase.)
|
||||||
|
if (mgrPrefs.selectPhraseAfterCursorAsCandidate
|
||||||
|
&& (cursorIndex < getBuilderLength()))
|
||||||
|
|| cursorIndex == 0
|
||||||
|
{
|
||||||
|
cursorIndex += 1
|
||||||
|
}
|
||||||
|
return cursorIndex
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,7 +29,7 @@ import Cocoa
|
||||||
// MARK: - § State managements.
|
// MARK: - § State managements.
|
||||||
@objc extension KeyHandler {
|
@objc extension KeyHandler {
|
||||||
|
|
||||||
// MARK: 用以生成候選詞數組
|
// MARK: - 用以生成候選詞數組
|
||||||
func _buildCandidateState(
|
func _buildCandidateState(
|
||||||
_ currentState: InputState.NotEmpty,
|
_ currentState: InputState.NotEmpty,
|
||||||
useVerticalMode: Bool
|
useVerticalMode: Bool
|
||||||
|
@ -39,12 +39,12 @@ import Cocoa
|
||||||
let state = InputState.ChoosingCandidate(
|
let state = InputState.ChoosingCandidate(
|
||||||
composingBuffer: currentState.composingBuffer,
|
composingBuffer: currentState.composingBuffer,
|
||||||
cursorIndex: currentState.cursorIndex,
|
cursorIndex: currentState.cursorIndex,
|
||||||
candidates: candidatesArray as! [String],
|
candidates: candidatesArray,
|
||||||
useVerticalMode: useVerticalMode)
|
useVerticalMode: useVerticalMode)
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: 用以處理就地新增自訂語彙時的行為
|
// MARK: - 用以處理就地新增自訂語彙時的行為
|
||||||
func _handleMarkingState(
|
func _handleMarkingState(
|
||||||
_ state: InputState.Marking,
|
_ state: InputState.Marking,
|
||||||
input: keyParser,
|
input: keyParser,
|
||||||
|
@ -127,4 +127,378 @@ import Cocoa
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - 標點輸入處理
|
||||||
|
func _handlePunctuation(
|
||||||
|
_ customPunctuation: String,
|
||||||
|
state: InputState,
|
||||||
|
usingVerticalMode useVerticalMode: Bool,
|
||||||
|
stateCallback: @escaping (InputState) -> Void,
|
||||||
|
errorCallback: @escaping () -> Void
|
||||||
|
) -> Bool {
|
||||||
|
if !ifLangModelHasUnigrams(forKey: customPunctuation) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if isPhoneticReadingBufferEmpty() {
|
||||||
|
insertReadingToBuilder(atCursor: customPunctuation)
|
||||||
|
let poppedText = _popOverflowComposingTextAndWalk()
|
||||||
|
let inputting = buildInputtingState() as! InputState.Inputting
|
||||||
|
inputting.poppedText = poppedText
|
||||||
|
stateCallback(inputting)
|
||||||
|
|
||||||
|
if mgrPrefs.useSCPCTypingMode && isPhoneticReadingBufferEmpty() {
|
||||||
|
let candidateState = _buildCandidateState(
|
||||||
|
inputting, useVerticalMode: useVerticalMode)
|
||||||
|
if candidateState.candidates.count == 1 {
|
||||||
|
clear()
|
||||||
|
if let strPoppedText: String = candidateState.candidates.first {
|
||||||
|
let committing =
|
||||||
|
InputState.Committing(poppedText: strPoppedText) as InputState.Committing
|
||||||
|
stateCallback(committing)
|
||||||
|
let empty = InputState.Empty()
|
||||||
|
stateCallback(empty)
|
||||||
|
} else {
|
||||||
|
stateCallback(candidateState)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
stateCallback(candidateState)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
// If there is still unfinished bpmf reading, ignore the punctuation
|
||||||
|
IME.prtDebugIntel("A9B69908D")
|
||||||
|
errorCallback()
|
||||||
|
stateCallback(state)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Enter 鍵處理
|
||||||
|
@discardableResult func _handleEnterWithState(
|
||||||
|
_ state: InputState,
|
||||||
|
stateCallback: @escaping (InputState) -> Void,
|
||||||
|
errorCallback: @escaping () -> Void
|
||||||
|
) -> Bool {
|
||||||
|
if !(state is InputState.Inputting) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
clear()
|
||||||
|
|
||||||
|
let current = state as! InputState.Inputting
|
||||||
|
let composingBuffer = current.composingBuffer
|
||||||
|
|
||||||
|
let committing = InputState.Committing(poppedText: composingBuffer)
|
||||||
|
stateCallback(committing)
|
||||||
|
let empty = InputState.Empty()
|
||||||
|
stateCallback(empty)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - CMD+Enter 鍵處理
|
||||||
|
func _handleCommandEnterWithState(
|
||||||
|
_ state: InputState,
|
||||||
|
stateCallback: @escaping (InputState) -> Void,
|
||||||
|
errorCallback: @escaping () -> Void
|
||||||
|
) -> Bool {
|
||||||
|
if !(state is InputState.Inputting) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
let readings: [String] = _currentReadings()
|
||||||
|
let composingBuffer =
|
||||||
|
(IME.areWeUsingOurOwnPhraseEditor)
|
||||||
|
? readings.joined(separator: "-")
|
||||||
|
: readings.joined(separator: " ")
|
||||||
|
|
||||||
|
clear()
|
||||||
|
|
||||||
|
let committing = InputState.Committing(poppedText: composingBuffer)
|
||||||
|
stateCallback(committing)
|
||||||
|
let empty = InputState.Empty()
|
||||||
|
stateCallback(empty)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - 處理 Backspace (macOS Delete) 按鍵行為
|
||||||
|
func _handleBackspaceWithState(
|
||||||
|
_ state: InputState,
|
||||||
|
stateCallback: @escaping (InputState) -> Void,
|
||||||
|
errorCallback: @escaping () -> Void
|
||||||
|
) -> Bool {
|
||||||
|
if !(state is InputState.Inputting) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if isPhoneticReadingBufferEmpty() {
|
||||||
|
if getBuilderCursorIndex() >= 0 {
|
||||||
|
deleteBuilderReadingInFrontOfCursor()
|
||||||
|
_walk()
|
||||||
|
} else {
|
||||||
|
IME.prtDebugIntel("9D69908D")
|
||||||
|
errorCallback()
|
||||||
|
stateCallback(state)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
doBackSpaceToPhoneticReadingBuffer()
|
||||||
|
}
|
||||||
|
|
||||||
|
if isPhoneticReadingBufferEmpty() && (getBuilderLength() == 0) {
|
||||||
|
let empty = InputState.EmptyIgnoringPreviousState()
|
||||||
|
stateCallback(empty)
|
||||||
|
} else {
|
||||||
|
let inputting = buildInputtingState() as! InputState.Inputting
|
||||||
|
stateCallback(inputting)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - 處理 PC Delete (macOS Fn+BackSpace) 按鍵行為
|
||||||
|
func _handleDeleteWithState(
|
||||||
|
_ state: InputState,
|
||||||
|
stateCallback: @escaping (InputState) -> Void,
|
||||||
|
errorCallback: @escaping () -> Void
|
||||||
|
) -> Bool {
|
||||||
|
if !(state is InputState.Inputting) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if isPhoneticReadingBufferEmpty() {
|
||||||
|
if getBuilderCursorIndex() != getBuilderLength() {
|
||||||
|
deleteBuilderReadingAfterCursor()
|
||||||
|
_walk()
|
||||||
|
let inputting = buildInputtingState() as! InputState.Inputting
|
||||||
|
if inputting.composingBuffer.count == 0 {
|
||||||
|
let empty = InputState.EmptyIgnoringPreviousState()
|
||||||
|
stateCallback(empty)
|
||||||
|
} else {
|
||||||
|
stateCallback(inputting)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
IME.prtDebugIntel("9B69938D")
|
||||||
|
errorCallback()
|
||||||
|
stateCallback(state)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
IME.prtDebugIntel("9C69908D")
|
||||||
|
errorCallback()
|
||||||
|
stateCallback(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - 處理與當前文字輸入排版前後方向呈 90 度的那兩個方向鍵的按鍵行為
|
||||||
|
func _handleAbsorbedArrowKeyWithState(
|
||||||
|
_ state: InputState,
|
||||||
|
stateCallback: @escaping (InputState) -> Void,
|
||||||
|
errorCallback: @escaping () -> Void
|
||||||
|
) -> Bool {
|
||||||
|
if !(state is InputState.Inputting) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !isPhoneticReadingBufferEmpty() {
|
||||||
|
IME.prtDebugIntel("9B6F908D")
|
||||||
|
errorCallback()
|
||||||
|
}
|
||||||
|
stateCallback(state)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - 處理 Home 鍵行為
|
||||||
|
func _handleHomeWithState(
|
||||||
|
_ state: InputState,
|
||||||
|
stateCallback: @escaping (InputState) -> Void,
|
||||||
|
errorCallback: @escaping () -> Void
|
||||||
|
) -> Bool {
|
||||||
|
if !(state is InputState.Inputting) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if !isPhoneticReadingBufferEmpty() {
|
||||||
|
IME.prtDebugIntel("ABC44080")
|
||||||
|
errorCallback()
|
||||||
|
stateCallback(state)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if getBuilderCursorIndex() != 0 {
|
||||||
|
setBuilderCursorIndex(0)
|
||||||
|
let inputting = buildInputtingState() as! InputState.Inputting
|
||||||
|
stateCallback(inputting)
|
||||||
|
} else {
|
||||||
|
IME.prtDebugIntel("66D97F90")
|
||||||
|
errorCallback()
|
||||||
|
stateCallback(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - 處理 End 鍵行為
|
||||||
|
func _handleEndWithState(
|
||||||
|
_ state: InputState,
|
||||||
|
stateCallback: @escaping (InputState) -> Void,
|
||||||
|
errorCallback: @escaping () -> Void
|
||||||
|
) -> Bool {
|
||||||
|
if !(state is InputState.Inputting) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if !isPhoneticReadingBufferEmpty() {
|
||||||
|
IME.prtDebugIntel("9B69908D")
|
||||||
|
errorCallback()
|
||||||
|
stateCallback(state)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if getBuilderCursorIndex() != getBuilderLength() {
|
||||||
|
setBuilderCursorIndex(getBuilderLength())
|
||||||
|
let inputting = buildInputtingState() as! InputState.Inputting
|
||||||
|
stateCallback(inputting)
|
||||||
|
} else {
|
||||||
|
IME.prtDebugIntel("9B69908E")
|
||||||
|
errorCallback()
|
||||||
|
stateCallback(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - 處理 Esc 鍵行為
|
||||||
|
func _handleEscWithState(
|
||||||
|
_ state: InputState,
|
||||||
|
stateCallback: @escaping (InputState) -> Void,
|
||||||
|
errorCallback: @escaping () -> Void
|
||||||
|
) -> Bool {
|
||||||
|
if !(state is InputState.Inputting) { return false }
|
||||||
|
|
||||||
|
let escToClearInputBufferEnabled: Bool = mgrPrefs.escToCleanInputBuffer
|
||||||
|
|
||||||
|
if escToClearInputBufferEnabled {
|
||||||
|
// If the option is enabled, we clear everything in the buffer.
|
||||||
|
// This includes walked nodes and the reading. Note that this convention
|
||||||
|
// is by default in macOS 10.0-10.5 built-in Panasonic Hanin and later macOS Zhuyin.
|
||||||
|
// Some Windows users hate this design, hence the option here to disable it.
|
||||||
|
clear()
|
||||||
|
let empty = InputState.EmptyIgnoringPreviousState()
|
||||||
|
stateCallback(empty)
|
||||||
|
} else {
|
||||||
|
// If reading is not empty, we cancel the reading.
|
||||||
|
if !isPhoneticReadingBufferEmpty() {
|
||||||
|
clearPhoneticReadingBuffer()
|
||||||
|
if getBuilderLength() == 0 {
|
||||||
|
let empty = InputState.Empty()
|
||||||
|
stateCallback(empty)
|
||||||
|
} else {
|
||||||
|
let inputting = buildInputtingState()
|
||||||
|
stateCallback(inputting)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// MARK: - 處理向前方向鍵的行為
|
||||||
|
func _handleForwardWithState(
|
||||||
|
_ state: InputState,
|
||||||
|
input: keyParser,
|
||||||
|
stateCallback: @escaping (InputState) -> Void,
|
||||||
|
errorCallback: @escaping () -> Void
|
||||||
|
) -> Bool {
|
||||||
|
|
||||||
|
if !(state is InputState.Inputting) { return false }
|
||||||
|
|
||||||
|
if !isPhoneticReadingBufferEmpty() {
|
||||||
|
IME.prtDebugIntel("B3BA5257")
|
||||||
|
errorCallback()
|
||||||
|
stateCallback(state)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
let currentState = state as! InputState.Inputting
|
||||||
|
|
||||||
|
if input.isShiftHold {
|
||||||
|
// Shift + Right
|
||||||
|
if currentState.cursorIndex < (currentState.composingBuffer as NSString).length {
|
||||||
|
let nextPosition = (currentState.composingBuffer as NSString).nextUtf16Position(
|
||||||
|
for: Int(currentState.cursorIndex))
|
||||||
|
let marking: InputState.Marking! = InputState.Marking(
|
||||||
|
composingBuffer: currentState.composingBuffer,
|
||||||
|
cursorIndex: currentState.cursorIndex,
|
||||||
|
markerIndex: UInt(nextPosition),
|
||||||
|
readings: _currentReadings())
|
||||||
|
marking.tooltipForInputting = currentState.tooltip
|
||||||
|
stateCallback(marking)
|
||||||
|
} else {
|
||||||
|
IME.prtDebugIntel("BB7F6DB9")
|
||||||
|
errorCallback()
|
||||||
|
stateCallback(state)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if getBuilderCursorIndex() < getBuilderLength() {
|
||||||
|
setBuilderCursorIndex(getBuilderCursorIndex() + 1)
|
||||||
|
let inputting = buildInputtingState() as! InputState.Inputting
|
||||||
|
stateCallback(inputting)
|
||||||
|
} else {
|
||||||
|
IME.prtDebugIntel("A96AAD58")
|
||||||
|
errorCallback()
|
||||||
|
stateCallback(state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - 處理向後方向鍵的行為
|
||||||
|
func _handleBackwardWithState(
|
||||||
|
_ state: InputState,
|
||||||
|
input: keyParser,
|
||||||
|
stateCallback: @escaping (InputState) -> Void,
|
||||||
|
errorCallback: @escaping () -> Void
|
||||||
|
) -> Bool {
|
||||||
|
|
||||||
|
if !(state is InputState.Inputting) { return false }
|
||||||
|
|
||||||
|
if !isPhoneticReadingBufferEmpty() {
|
||||||
|
IME.prtDebugIntel("6ED95318")
|
||||||
|
errorCallback()
|
||||||
|
stateCallback(state)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
let currentState = state as! InputState.Inputting
|
||||||
|
|
||||||
|
if input.isShiftHold {
|
||||||
|
// Shift + left
|
||||||
|
if currentState.cursorIndex > 0 {
|
||||||
|
let previousPosition = (currentState.composingBuffer as NSString).previousUtf16Position(
|
||||||
|
for: Int(currentState.cursorIndex))
|
||||||
|
let marking: InputState.Marking! = InputState.Marking(
|
||||||
|
composingBuffer: currentState.composingBuffer,
|
||||||
|
cursorIndex: currentState.cursorIndex,
|
||||||
|
markerIndex: UInt(previousPosition),
|
||||||
|
readings: _currentReadings())
|
||||||
|
marking.tooltipForInputting = currentState.tooltip
|
||||||
|
stateCallback(marking)
|
||||||
|
} else {
|
||||||
|
IME.prtDebugIntel("D326DEA3")
|
||||||
|
errorCallback()
|
||||||
|
stateCallback(state)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if getBuilderCursorIndex() > 0 {
|
||||||
|
setBuilderCursorIndex(getBuilderCursorIndex() - 1)
|
||||||
|
let inputting = buildInputtingState() as! InputState.Inputting
|
||||||
|
stateCallback(inputting)
|
||||||
|
} else {
|
||||||
|
IME.prtDebugIntel("7045E6F3")
|
||||||
|
errorCallback()
|
||||||
|
stateCallback(state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
5B2DB17027AF6891006D874E /* data-cht.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5B2DB16E27AF6891006D874E /* data-cht.txt */; };
|
5B2DB17027AF6891006D874E /* data-cht.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5B2DB16E27AF6891006D874E /* data-cht.txt */; };
|
||||||
5B3133BF280B229700A4A505 /* KeyHandler_States.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B3133BE280B229700A4A505 /* KeyHandler_States.swift */; };
|
5B3133BF280B229700A4A505 /* KeyHandler_States.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B3133BE280B229700A4A505 /* KeyHandler_States.swift */; };
|
||||||
5B5E535227EF261400C6AA1E /* IME.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B5E535127EF261400C6AA1E /* IME.swift */; };
|
5B5E535227EF261400C6AA1E /* IME.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B5E535127EF261400C6AA1E /* IME.swift */; };
|
||||||
|
5B61B0CA280BEFD4002E3CFA /* KeyHandler_Misc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B61B0C9280BEFD4002E3CFA /* KeyHandler_Misc.swift */; };
|
||||||
5B62A32927AE77D100A19448 /* FSEventStreamHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A32827AE77D100A19448 /* FSEventStreamHelper.swift */; };
|
5B62A32927AE77D100A19448 /* FSEventStreamHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A32827AE77D100A19448 /* FSEventStreamHelper.swift */; };
|
||||||
5B62A32F27AE78B000A19448 /* CoreLM.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A32D27AE78B000A19448 /* CoreLM.mm */; };
|
5B62A32F27AE78B000A19448 /* CoreLM.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A32D27AE78B000A19448 /* CoreLM.mm */; };
|
||||||
5B62A33227AE792F00A19448 /* InputSourceHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A33127AE792F00A19448 /* InputSourceHelper.swift */; };
|
5B62A33227AE792F00A19448 /* InputSourceHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A33127AE792F00A19448 /* InputSourceHelper.swift */; };
|
||||||
|
@ -30,8 +31,10 @@
|
||||||
5B707CE827D9F4590099EF99 /* OpenCCBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B707CE727D9F4590099EF99 /* OpenCCBridge.swift */; };
|
5B707CE827D9F4590099EF99 /* OpenCCBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B707CE727D9F4590099EF99 /* OpenCCBridge.swift */; };
|
||||||
5B707CEC27D9F4870099EF99 /* OpenCC in Frameworks */ = {isa = PBXBuildFile; productRef = 5B707CEB27D9F4870099EF99 /* OpenCC */; };
|
5B707CEC27D9F4870099EF99 /* OpenCC in Frameworks */ = {isa = PBXBuildFile; productRef = 5B707CEB27D9F4870099EF99 /* OpenCC */; };
|
||||||
5B73FB5E27B2BE1300E9BF49 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5B73FB6027B2BE1300E9BF49 /* InfoPlist.strings */; };
|
5B73FB5E27B2BE1300E9BF49 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5B73FB6027B2BE1300E9BF49 /* InfoPlist.strings */; };
|
||||||
|
5B782EC4280C243C007276DE /* KeyHandler_HandleCandidate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B782EC3280C243C007276DE /* KeyHandler_HandleCandidate.swift */; };
|
||||||
|
5B782EC6280C2F4B007276DE /* KeyHandler_BuildInput.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B782EC5280C2F4B007276DE /* KeyHandler_BuildInput.swift */; };
|
||||||
5B7BC4B027AFFBE800F66C24 /* frmPrefWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5B7BC4AE27AFFBE800F66C24 /* frmPrefWindow.xib */; };
|
5B7BC4B027AFFBE800F66C24 /* frmPrefWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5B7BC4AE27AFFBE800F66C24 /* frmPrefWindow.xib */; };
|
||||||
5B7F225D2808501000DDD3CB /* KeyHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B7F225C2808501000DDD3CB /* KeyHandler.swift */; };
|
5B7F225D2808501000DDD3CB /* KeyHandler_HandleInput.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B7F225C2808501000DDD3CB /* KeyHandler_HandleInput.swift */; };
|
||||||
5BA9FD0F27FEDB6B002DE248 /* suiPrefPaneGeneral.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA9FD0A27FEDB6B002DE248 /* suiPrefPaneGeneral.swift */; };
|
5BA9FD0F27FEDB6B002DE248 /* suiPrefPaneGeneral.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA9FD0A27FEDB6B002DE248 /* suiPrefPaneGeneral.swift */; };
|
||||||
5BA9FD1027FEDB6B002DE248 /* suiPrefPaneKeyboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA9FD0B27FEDB6B002DE248 /* suiPrefPaneKeyboard.swift */; };
|
5BA9FD1027FEDB6B002DE248 /* suiPrefPaneKeyboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA9FD0B27FEDB6B002DE248 /* suiPrefPaneKeyboard.swift */; };
|
||||||
5BA9FD1127FEDB6B002DE248 /* ctlPrefUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA9FD0C27FEDB6B002DE248 /* ctlPrefUI.swift */; };
|
5BA9FD1127FEDB6B002DE248 /* ctlPrefUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA9FD0C27FEDB6B002DE248 /* ctlPrefUI.swift */; };
|
||||||
|
@ -189,6 +192,7 @@
|
||||||
5B30F11227BA568800484E24 /* vChewingKeyLayout.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = vChewingKeyLayout.bundle; sourceTree = "<group>"; };
|
5B30F11227BA568800484E24 /* vChewingKeyLayout.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = vChewingKeyLayout.bundle; sourceTree = "<group>"; };
|
||||||
5B3133BE280B229700A4A505 /* KeyHandler_States.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyHandler_States.swift; sourceTree = "<group>"; };
|
5B3133BE280B229700A4A505 /* KeyHandler_States.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyHandler_States.swift; sourceTree = "<group>"; };
|
||||||
5B5E535127EF261400C6AA1E /* IME.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IME.swift; sourceTree = "<group>"; };
|
5B5E535127EF261400C6AA1E /* IME.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IME.swift; sourceTree = "<group>"; };
|
||||||
|
5B61B0C9280BEFD4002E3CFA /* KeyHandler_Misc.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyHandler_Misc.swift; sourceTree = "<group>"; };
|
||||||
5B62A32627AE77BB00A19448 /* LMConsolidator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LMConsolidator.h; sourceTree = "<group>"; };
|
5B62A32627AE77BB00A19448 /* LMConsolidator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LMConsolidator.h; sourceTree = "<group>"; };
|
||||||
5B62A32727AE77BB00A19448 /* LMConsolidator.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = LMConsolidator.mm; sourceTree = "<group>"; };
|
5B62A32727AE77BB00A19448 /* LMConsolidator.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = LMConsolidator.mm; sourceTree = "<group>"; };
|
||||||
5B62A32827AE77D100A19448 /* FSEventStreamHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FSEventStreamHelper.swift; sourceTree = "<group>"; };
|
5B62A32827AE77D100A19448 /* FSEventStreamHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FSEventStreamHelper.swift; sourceTree = "<group>"; };
|
||||||
|
@ -209,9 +213,11 @@
|
||||||
5B7111C727DEF9FF00444310 /* UserSymbolLM.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UserSymbolLM.h; sourceTree = "<group>"; };
|
5B7111C727DEF9FF00444310 /* UserSymbolLM.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UserSymbolLM.h; sourceTree = "<group>"; };
|
||||||
5B73FB5427B2BD6900E9BF49 /* PhraseEditor-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "PhraseEditor-Info.plist"; path = "UserPhraseEditor/PhraseEditor-Info.plist"; sourceTree = SOURCE_ROOT; };
|
5B73FB5427B2BD6900E9BF49 /* PhraseEditor-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "PhraseEditor-Info.plist"; path = "UserPhraseEditor/PhraseEditor-Info.plist"; sourceTree = SOURCE_ROOT; };
|
||||||
5B73FB5F27B2BE1300E9BF49 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
5B73FB5F27B2BE1300E9BF49 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||||
|
5B782EC3280C243C007276DE /* KeyHandler_HandleCandidate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyHandler_HandleCandidate.swift; sourceTree = "<group>"; };
|
||||||
|
5B782EC5280C2F4B007276DE /* KeyHandler_BuildInput.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyHandler_BuildInput.swift; sourceTree = "<group>"; };
|
||||||
5B7BC4AF27AFFBE800F66C24 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/frmPrefWindow.xib; sourceTree = "<group>"; };
|
5B7BC4AF27AFFBE800F66C24 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/frmPrefWindow.xib; sourceTree = "<group>"; };
|
||||||
5B7BC4B227AFFC0B00F66C24 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/frmPrefWindow.strings; sourceTree = "<group>"; };
|
5B7BC4B227AFFC0B00F66C24 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/frmPrefWindow.strings; sourceTree = "<group>"; };
|
||||||
5B7F225C2808501000DDD3CB /* KeyHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyHandler.swift; sourceTree = "<group>"; };
|
5B7F225C2808501000DDD3CB /* KeyHandler_HandleInput.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyHandler_HandleInput.swift; sourceTree = "<group>"; };
|
||||||
5B8F43ED27C9BC220069AC27 /* SymbolLM.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SymbolLM.h; sourceTree = "<group>"; };
|
5B8F43ED27C9BC220069AC27 /* SymbolLM.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SymbolLM.h; sourceTree = "<group>"; };
|
||||||
5BA9FD0A27FEDB6B002DE248 /* suiPrefPaneGeneral.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = suiPrefPaneGeneral.swift; sourceTree = "<group>"; };
|
5BA9FD0A27FEDB6B002DE248 /* suiPrefPaneGeneral.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = suiPrefPaneGeneral.swift; sourceTree = "<group>"; };
|
||||||
5BA9FD0B27FEDB6B002DE248 /* suiPrefPaneKeyboard.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = suiPrefPaneKeyboard.swift; sourceTree = "<group>"; };
|
5BA9FD0B27FEDB6B002DE248 /* suiPrefPaneKeyboard.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = suiPrefPaneKeyboard.swift; sourceTree = "<group>"; };
|
||||||
|
@ -427,7 +433,10 @@
|
||||||
D461B791279DAC010070E734 /* InputState.swift */,
|
D461B791279DAC010070E734 /* InputState.swift */,
|
||||||
D4E569DA27A34CC100AC2CEF /* KeyHandler.h */,
|
D4E569DA27A34CC100AC2CEF /* KeyHandler.h */,
|
||||||
D4E569DB27A34CC100AC2CEF /* KeyHandler.mm */,
|
D4E569DB27A34CC100AC2CEF /* KeyHandler.mm */,
|
||||||
5B7F225C2808501000DDD3CB /* KeyHandler.swift */,
|
5B782EC5280C2F4B007276DE /* KeyHandler_BuildInput.swift */,
|
||||||
|
5B7F225C2808501000DDD3CB /* KeyHandler_HandleInput.swift */,
|
||||||
|
5B782EC3280C243C007276DE /* KeyHandler_HandleCandidate.swift */,
|
||||||
|
5B61B0C9280BEFD4002E3CFA /* KeyHandler_Misc.swift */,
|
||||||
5B3133BE280B229700A4A505 /* KeyHandler_States.swift */,
|
5B3133BE280B229700A4A505 /* KeyHandler_States.swift */,
|
||||||
D456576D279E4F7B00DF6BC9 /* KeyParser.swift */,
|
D456576D279E4F7B00DF6BC9 /* KeyParser.swift */,
|
||||||
6ACC3D3E27914F2400F1B140 /* KeyValueBlobReader.cpp */,
|
6ACC3D3E27914F2400F1B140 /* KeyValueBlobReader.cpp */,
|
||||||
|
@ -1067,7 +1076,7 @@
|
||||||
D427F76C278CA2B0004A2160 /* AppDelegate.swift in Sources */,
|
D427F76C278CA2B0004A2160 /* AppDelegate.swift in Sources */,
|
||||||
5BA9FD4527FEF3C9002DE248 /* ToolbarItemStyleViewController.swift in Sources */,
|
5BA9FD4527FEF3C9002DE248 /* ToolbarItemStyleViewController.swift in Sources */,
|
||||||
5BA9FD4127FEF3C8002DE248 /* PreferencesStyle.swift in Sources */,
|
5BA9FD4127FEF3C8002DE248 /* PreferencesStyle.swift in Sources */,
|
||||||
5B7F225D2808501000DDD3CB /* KeyHandler.swift in Sources */,
|
5B7F225D2808501000DDD3CB /* KeyHandler_HandleInput.swift in Sources */,
|
||||||
5BA9FD1227FEDB6B002DE248 /* suiPrefPaneExperience.swift in Sources */,
|
5BA9FD1227FEDB6B002DE248 /* suiPrefPaneExperience.swift in Sources */,
|
||||||
6ACC3D442793701600F1B140 /* ParselessPhraseDB.cpp in Sources */,
|
6ACC3D442793701600F1B140 /* ParselessPhraseDB.cpp in Sources */,
|
||||||
D461B792279DAC010070E734 /* InputState.swift in Sources */,
|
D461B792279DAC010070E734 /* InputState.swift in Sources */,
|
||||||
|
@ -1082,6 +1091,7 @@
|
||||||
5B62A32F27AE78B000A19448 /* CoreLM.mm in Sources */,
|
5B62A32F27AE78B000A19448 /* CoreLM.mm in Sources */,
|
||||||
5BE78BE027B38804005EA1BE /* LMConsolidator.mm in Sources */,
|
5BE78BE027B38804005EA1BE /* LMConsolidator.mm in Sources */,
|
||||||
D456576E279E4F7B00DF6BC9 /* KeyParser.swift in Sources */,
|
D456576E279E4F7B00DF6BC9 /* KeyParser.swift in Sources */,
|
||||||
|
5B782EC6280C2F4B007276DE /* KeyHandler_BuildInput.swift in Sources */,
|
||||||
5BA9FD1027FEDB6B002DE248 /* suiPrefPaneKeyboard.swift in Sources */,
|
5BA9FD1027FEDB6B002DE248 /* suiPrefPaneKeyboard.swift in Sources */,
|
||||||
5B3133BF280B229700A4A505 /* KeyHandler_States.swift in Sources */,
|
5B3133BF280B229700A4A505 /* KeyHandler_States.swift in Sources */,
|
||||||
5BA9FD4327FEF3C8002DE248 /* Preferences.swift in Sources */,
|
5BA9FD4327FEF3C8002DE248 /* Preferences.swift in Sources */,
|
||||||
|
@ -1098,6 +1108,7 @@
|
||||||
D47F7DD3278C1263002F9DD7 /* UserOverrideModel.cpp in Sources */,
|
D47F7DD3278C1263002F9DD7 /* UserOverrideModel.cpp in Sources */,
|
||||||
5B62A33627AE795800A19448 /* mgrPrefs.swift in Sources */,
|
5B62A33627AE795800A19448 /* mgrPrefs.swift in Sources */,
|
||||||
5BAEFAD028012565001F42C9 /* mgrLangModel.swift in Sources */,
|
5BAEFAD028012565001F42C9 /* mgrLangModel.swift in Sources */,
|
||||||
|
5B782EC4280C243C007276DE /* KeyHandler_HandleCandidate.swift in Sources */,
|
||||||
5B62A33827AE79CD00A19448 /* NSStringUtils.swift in Sources */,
|
5B62A33827AE79CD00A19448 /* NSStringUtils.swift in Sources */,
|
||||||
5BA9FD0F27FEDB6B002DE248 /* suiPrefPaneGeneral.swift in Sources */,
|
5BA9FD0F27FEDB6B002DE248 /* suiPrefPaneGeneral.swift in Sources */,
|
||||||
5BA9FD4927FEF3C9002DE248 /* Section.swift in Sources */,
|
5BA9FD4927FEF3C9002DE248 /* Section.swift in Sources */,
|
||||||
|
@ -1107,6 +1118,7 @@
|
||||||
5B5E535227EF261400C6AA1E /* IME.swift in Sources */,
|
5B5E535227EF261400C6AA1E /* IME.swift in Sources */,
|
||||||
5B62A34927AE7CD900A19448 /* TooltipController.swift in Sources */,
|
5B62A34927AE7CD900A19448 /* TooltipController.swift in Sources */,
|
||||||
6A0D4F4515FC0EB100ABF4B3 /* Mandarin.cpp in Sources */,
|
6A0D4F4515FC0EB100ABF4B3 /* Mandarin.cpp in Sources */,
|
||||||
|
5B61B0CA280BEFD4002E3CFA /* KeyHandler_Misc.swift in Sources */,
|
||||||
5B62A34827AE7CD900A19448 /* ctlCandidateVertical.swift in Sources */,
|
5B62A34827AE7CD900A19448 /* ctlCandidateVertical.swift in Sources */,
|
||||||
5BA9FD4027FEF3C8002DE248 /* Localization.swift in Sources */,
|
5BA9FD4027FEF3C8002DE248 /* Localization.swift in Sources */,
|
||||||
5BA9FD1327FEDB6B002DE248 /* suiPrefPaneDictionary.swift in Sources */,
|
5BA9FD1327FEDB6B002DE248 /* suiPrefPaneDictionary.swift in Sources */,
|
||||||
|
|
Loading…
Reference in New Issue