KeyHandler // Swiftify: day 4.
This commit is contained in:
parent
b17e3f45a4
commit
6139879d68
|
@ -47,11 +47,6 @@ extern InputMode imeModeNULL;
|
|||
@interface KeyHandler : NSObject
|
||||
|
||||
- (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)clear;
|
||||
|
@ -63,34 +58,34 @@ extern InputMode imeModeNULL;
|
|||
@property(weak, nonatomic) id<KeyHandlerDelegate> delegate;
|
||||
|
||||
// The following items need to be exposed to Swift:
|
||||
- (void)_walk;
|
||||
- (NSString *)_popOverflowComposingTextAndWalk;
|
||||
|
||||
- (BOOL)_handleCandidateState:(InputState *)state
|
||||
input:(keyParser *)input
|
||||
stateCallback:(void (^)(InputState *))stateCallback
|
||||
errorCallback:(void (^)(void))errorCallback
|
||||
NS_SWIFT_NAME(handleCandidate(state:input:stateCallback:errorCallback:));
|
||||
- (NSArray<NSString *> *)_currentReadings;
|
||||
|
||||
- (BOOL)checkWhetherToneMarkerConfirmsPhoneticReadingBuffer;
|
||||
- (BOOL)chkKeyValidity:(UniChar)value;
|
||||
- (BOOL)ifLangModelHasUnigramsForKey:(NSString *)reading;
|
||||
- (BOOL)isPhoneticReadingBufferEmpty;
|
||||
- (BOOL)isPrintable:(UniChar)charCode;
|
||||
- (NSArray<NSString *> *)getCandidatesArray;
|
||||
- (NSInteger)getBuilderCursorIndex;
|
||||
- (NSInteger)getBuilderLength;
|
||||
- (NSString *)_currentMandarinParser;
|
||||
- (NSString *)getCompositionFromPhoneticReadingBuffer;
|
||||
- (NSString *)getSyllableCompositionFromPhoneticReadingBuffer;
|
||||
- (void)clearPhoneticReadingBuffer;
|
||||
- (void)combinePhoneticReadingBufferKey:(UniChar)charCode;
|
||||
- (void)doBackSpaceToPhoneticReadingBuffer;
|
||||
- (void)removeBuilderAndReset:(BOOL)shouldReset;
|
||||
- (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)syncBaseLMPrefs;
|
||||
- (void)ensurePhoneticParser;
|
||||
- (BOOL)ifLangModelHasUnigramsForKey:(NSString *)reading;
|
||||
- (void)insertReadingToBuilderAtCursor:(NSString *)reading;
|
||||
- (BOOL)isPrintable:(UniChar)charCode;
|
||||
- (void)dealWithOverrideModelSuggestions;
|
||||
- (NSMutableArray *)getCandidatesArray;
|
||||
- (NSInteger)getBuilderCursorIndex;
|
||||
- (NSInteger)getBuilderLength;
|
||||
|
||||
@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
|
||||
|
||||
// MARK: - § Handle Inputs (WIP).
|
||||
// MARK: - § Handle Input with States.
|
||||
|
||||
@objc extension KeyHandler {
|
||||
func handleInputSwift(
|
||||
func handle(
|
||||
input: keyParser,
|
||||
state inState: InputState,
|
||||
stateCallback: @escaping (InputState) -> Void,
|
||||
errorCallback: @escaping () -> Void
|
||||
) -> Bool {
|
||||
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 emptyState = InputState.Empty()
|
||||
|
||||
|
@ -102,14 +103,14 @@ import Cocoa
|
|||
|
||||
// MARK: Handle Candidates.
|
||||
if state is InputState.ChoosingCandidate {
|
||||
return handleCandidate(
|
||||
state: state, input: input, stateCallback: stateCallback, errorCallback: errorCallback)
|
||||
return _handleCandidateState(
|
||||
state, input: input, stateCallback: stateCallback, errorCallback: errorCallback)
|
||||
}
|
||||
|
||||
// MARK: Handle Associated Phrases.
|
||||
if state is InputState.AssociatedPhrases {
|
||||
let result = handleCandidate(
|
||||
state: state, input: input, stateCallback: stateCallback, errorCallback: errorCallback)
|
||||
let result = _handleCandidateState(
|
||||
state, input: input, stateCallback: stateCallback, errorCallback: errorCallback)
|
||||
if result {
|
||||
return true
|
||||
} else {
|
||||
|
@ -221,7 +222,7 @@ import Cocoa
|
|||
|| (input.useVerticalMode && (input.isVerticalModeOnlyChooseCandidateKey)))
|
||||
{
|
||||
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 getBuilderCursorIndex() >= getBuilderLength() {
|
||||
let composingBuffer = (state as! InputState.NotEmpty).composingBuffer
|
||||
|
@ -251,11 +252,161 @@ import Cocoa
|
|||
return true
|
||||
}
|
||||
|
||||
// MARK: Function Keys.
|
||||
// MARK: -
|
||||
|
||||
// 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.
|
||||
// Note that some app has strange behavior if we don't do this,
|
||||
// "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.
|
||||
@objc extension KeyHandler {
|
||||
|
||||
// MARK: 用以生成候選詞數組
|
||||
// MARK: - 用以生成候選詞數組
|
||||
func _buildCandidateState(
|
||||
_ currentState: InputState.NotEmpty,
|
||||
useVerticalMode: Bool
|
||||
|
@ -39,12 +39,12 @@ import Cocoa
|
|||
let state = InputState.ChoosingCandidate(
|
||||
composingBuffer: currentState.composingBuffer,
|
||||
cursorIndex: currentState.cursorIndex,
|
||||
candidates: candidatesArray as! [String],
|
||||
candidates: candidatesArray,
|
||||
useVerticalMode: useVerticalMode)
|
||||
return state
|
||||
}
|
||||
|
||||
// MARK: 用以處理就地新增自訂語彙時的行為
|
||||
// MARK: - 用以處理就地新增自訂語彙時的行為
|
||||
func _handleMarkingState(
|
||||
_ state: InputState.Marking,
|
||||
input: keyParser,
|
||||
|
@ -127,4 +127,378 @@ import Cocoa
|
|||
}
|
||||
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 */; };
|
||||
5B3133BF280B229700A4A505 /* KeyHandler_States.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B3133BE280B229700A4A505 /* KeyHandler_States.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 */; };
|
||||
5B62A32F27AE78B000A19448 /* CoreLM.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A32D27AE78B000A19448 /* CoreLM.mm */; };
|
||||
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 */; };
|
||||
5B707CEC27D9F4870099EF99 /* OpenCC in Frameworks */ = {isa = PBXBuildFile; productRef = 5B707CEB27D9F4870099EF99 /* OpenCC */; };
|
||||
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 */; };
|
||||
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 */; };
|
||||
5BA9FD1027FEDB6B002DE248 /* suiPrefPaneKeyboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA9FD0B27FEDB6B002DE248 /* suiPrefPaneKeyboard.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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
|
@ -209,9 +213,11 @@
|
|||
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; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
|
@ -427,7 +433,10 @@
|
|||
D461B791279DAC010070E734 /* InputState.swift */,
|
||||
D4E569DA27A34CC100AC2CEF /* KeyHandler.h */,
|
||||
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 */,
|
||||
D456576D279E4F7B00DF6BC9 /* KeyParser.swift */,
|
||||
6ACC3D3E27914F2400F1B140 /* KeyValueBlobReader.cpp */,
|
||||
|
@ -1067,7 +1076,7 @@
|
|||
D427F76C278CA2B0004A2160 /* AppDelegate.swift in Sources */,
|
||||
5BA9FD4527FEF3C9002DE248 /* ToolbarItemStyleViewController.swift in Sources */,
|
||||
5BA9FD4127FEF3C8002DE248 /* PreferencesStyle.swift in Sources */,
|
||||
5B7F225D2808501000DDD3CB /* KeyHandler.swift in Sources */,
|
||||
5B7F225D2808501000DDD3CB /* KeyHandler_HandleInput.swift in Sources */,
|
||||
5BA9FD1227FEDB6B002DE248 /* suiPrefPaneExperience.swift in Sources */,
|
||||
6ACC3D442793701600F1B140 /* ParselessPhraseDB.cpp in Sources */,
|
||||
D461B792279DAC010070E734 /* InputState.swift in Sources */,
|
||||
|
@ -1082,6 +1091,7 @@
|
|||
5B62A32F27AE78B000A19448 /* CoreLM.mm in Sources */,
|
||||
5BE78BE027B38804005EA1BE /* LMConsolidator.mm in Sources */,
|
||||
D456576E279E4F7B00DF6BC9 /* KeyParser.swift in Sources */,
|
||||
5B782EC6280C2F4B007276DE /* KeyHandler_BuildInput.swift in Sources */,
|
||||
5BA9FD1027FEDB6B002DE248 /* suiPrefPaneKeyboard.swift in Sources */,
|
||||
5B3133BF280B229700A4A505 /* KeyHandler_States.swift in Sources */,
|
||||
5BA9FD4327FEF3C8002DE248 /* Preferences.swift in Sources */,
|
||||
|
@ -1098,6 +1108,7 @@
|
|||
D47F7DD3278C1263002F9DD7 /* UserOverrideModel.cpp in Sources */,
|
||||
5B62A33627AE795800A19448 /* mgrPrefs.swift in Sources */,
|
||||
5BAEFAD028012565001F42C9 /* mgrLangModel.swift in Sources */,
|
||||
5B782EC4280C243C007276DE /* KeyHandler_HandleCandidate.swift in Sources */,
|
||||
5B62A33827AE79CD00A19448 /* NSStringUtils.swift in Sources */,
|
||||
5BA9FD0F27FEDB6B002DE248 /* suiPrefPaneGeneral.swift in Sources */,
|
||||
5BA9FD4927FEF3C9002DE248 /* Section.swift in Sources */,
|
||||
|
@ -1107,6 +1118,7 @@
|
|||
5B5E535227EF261400C6AA1E /* IME.swift in Sources */,
|
||||
5B62A34927AE7CD900A19448 /* TooltipController.swift in Sources */,
|
||||
6A0D4F4515FC0EB100ABF4B3 /* Mandarin.cpp in Sources */,
|
||||
5B61B0CA280BEFD4002E3CFA /* KeyHandler_Misc.swift in Sources */,
|
||||
5B62A34827AE7CD900A19448 /* ctlCandidateVertical.swift in Sources */,
|
||||
5BA9FD4027FEF3C8002DE248 /* Localization.swift in Sources */,
|
||||
5BA9FD1327FEDB6B002DE248 /* suiPrefPaneDictionary.swift in Sources */,
|
||||
|
|
Loading…
Reference in New Issue