1.5.x Beta // Merge GitHub PR #63 from dev/1.5.x

KeyHandler Swiftification.
This commit is contained in:
ShikiSuen 2022-04-18 01:46:26 +08:00 committed by GitHub
commit ed834623eb
11 changed files with 1722 additions and 1415 deletions

View File

@ -210,7 +210,7 @@ typedef BopomofoSyllable BPMF;
typedef std::map<char, std::vector<BPMF::Component>> BopomofoKeyToComponentMap;
typedef std::map<BPMF::Component, char> BopomofoComponentToKeyMap;
class BopomofoKeyboardLayout
extern "C" class BopomofoKeyboardLayout
{
public:
static const BopomofoKeyboardLayout *StandardLayout();
@ -438,7 +438,7 @@ class BopomofoKeyboardLayout
BopomofoComponentToKeyMap m_componentToKey;
};
class BopomofoReadingBuffer
extern "C" class BopomofoReadingBuffer
{
public:
explicit BopomofoReadingBuffer(const BopomofoKeyboardLayout *layout) : layout_(layout), pinyin_mode_(false)

View File

@ -36,6 +36,14 @@ extern InputMode imeModeCHT;
extern InputMode imeModeCHS;
extern InputMode imeModeNULL;
struct BufferStatePackage
{
NSString *composedText;
NSInteger cursorIndex;
NSString *resultOfBefore;
NSString *resultOfAfter;
};
@class KeyHandler;
@protocol KeyHandlerDelegate <NSObject>
@ -47,21 +55,48 @@ 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)syncWithPreferences;
- (void)fixNodeWithValue:(NSString *)value NS_SWIFT_NAME(fixNode(value:));
- (void)clear;
- (InputState *)buildInputtingState;
- (nullable InputState *)buildAssociatePhraseStateWithKey:(NSString *)key useVerticalMode:(BOOL)useVerticalMode;
@property(strong, nonatomic) InputMode inputMode;
@property(weak, nonatomic) id<KeyHandlerDelegate> delegate;
// The following items need to be exposed to Swift:
- (void)_walk;
- (NSString *)_popOverflowComposingTextAndWalk;
- (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;
- (NSInteger)getPackagedCursorIndex;
- (NSString *)getComposedText;
- (NSString *)getCompositionFromPhoneticReadingBuffer;
- (NSString *)getStrLocationResult:(BOOL)isAfter NS_SWIFT_NAME(getStrLocationResult(isAfter:));
- (NSString *)getSyllableCompositionFromPhoneticReadingBuffer;
- (void)clearPhoneticReadingBuffer;
- (void)combinePhoneticReadingBufferKey:(UniChar)charCode;
- (void)createNewBuilder;
- (void)dealWithOverrideModelSuggestions;
- (void)deleteBuilderReadingAfterCursor;
- (void)deleteBuilderReadingInFrontOfCursor;
- (void)doBackSpaceToPhoneticReadingBuffer;
- (void)ensurePhoneticParser;
- (void)insertReadingToBuilderAtCursor:(NSString *)reading;
- (void)packageBufferStateMaterials;
- (void)removeBuilderAndReset:(BOOL)shouldReset;
- (void)setBuilderCursorIndex:(NSInteger)value;
- (void)setInputModesToLM:(BOOL)isCHS;
- (void)syncBaseLMPrefs;
@end
NS_ASSUME_NONNULL_END

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,329 @@
// 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()
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 = getCurrentMandarinParser()
let arrCustomPunctuations: [String] = [
punctuationNamePrefix, parser, String(format: "%c", CChar(charCode)),
]
let customPunctuation: String = arrCustomPunctuations.joined(separator: "")
let arrPunctuations: [String] = [punctuationNamePrefix, String(format: "%c", CChar(charCode))]
let punctuation: String = arrPunctuations.joined(separator: "")
var shouldAutoSelectCandidate: Bool =
chkKeyValidity(charCode) || ifLangModelHasUnigrams(forKey: customPunctuation)
|| ifLangModelHasUnigrams(forKey: punctuation)
if !shouldAutoSelectCandidate && input.isUpperCaseASCIILetterKey {
let letter: String! = String(format: "%@%c", "_letter_", CChar(charCode))
if ifLangModelHasUnigrams(forKey: letter) { shouldAutoSelectCandidate = true }
}
if shouldAutoSelectCandidate {
let candidateIndex: UInt = ctlCandidateCurrent.candidateIndexAtKeyLabelIndex(0)
if candidateIndex != UInt.max {
delegate!.keyHandler(
self,
didSelectCandidateAt: Int(candidateIndex),
ctlCandidate: ctlCandidateCurrent)
clear()
let empty = InputState.EmptyIgnoringPreviousState()
stateCallback(empty)
return handle(
input: input, state: empty, stateCallback: stateCallback, errorCallback: errorCallback)
}
return true
}
}
IME.prtDebugIntel("172A0F81")
errorCallback()
return true
}
}

View File

@ -0,0 +1,426 @@
// 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 Input with States.
@objc extension KeyHandler {
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 into variable.
let inputText: String = input.inputText ?? ""
let emptyState = InputState.Empty()
// Ignore the input if its inputText is empty.
// Reason: such inputs may be functional key combinations.
if (inputText).isEmpty {
return false
}
// Ignore the input if the composing buffer is empty with no reading
// and there is some function key combination.
let isFunctionKey: Bool =
input.isControlHotKey || (input.isCommandHold || input.isOptionHotKey || input.isNumericPad)
if !(state is InputState.NotEmpty) && !(state is InputState.AssociatedPhrases) && isFunctionKey {
return false
}
// MARK: Caps Lock processing.
// If Caps Lock is ON, temporarily disable bopomofo.
// Note: Alphanumerical mode processing.
if input.isBackSpace || input.isEnter || input.isAbsorbedArrowKey || input.isExtraChooseCandidateKey
|| input.isExtraChooseCandidateKeyReverse || input.isCursorForward || input.isCursorBackward
{
// Do nothing if backspace is pressed -- we ignore the key
} else if input.isCapsLockOn {
// Process all possible combination, we hope.
clear()
stateCallback(emptyState)
// When shift is pressed, don't do further processing...
// ...since it outputs capital letter anyway.
if input.isShiftHold {
return false
}
// If ASCII but not printable, don't use insertText:replacementRange:
// Certain apps don't handle non-ASCII char insertions.
if charCode < 0x80 && !isPrintable(charCode) {
return false
}
// Commit the entire input buffer.
let committingState = InputState.Committing(poppedText: inputText.lowercased())
stateCallback(committingState)
stateCallback(emptyState)
return true
}
// MARK: Numeric Pad Processing.
if input.isNumericPad {
if !input.isLeft && !input.isRight && !input.isDown
&& !input.isUp && !input.isSpace && isPrintable(charCode)
{
clear()
stateCallback(emptyState)
let committing = InputState.Committing(poppedText: inputText.lowercased())
stateCallback(committing)
stateCallback(emptyState)
return true
}
}
// MARK: Handle Candidates.
if state is InputState.ChoosingCandidate {
return _handleCandidateState(
state, input: input, stateCallback: stateCallback, errorCallback: errorCallback)
}
// MARK: Handle Associated Phrases.
if state is InputState.AssociatedPhrases {
let result = _handleCandidateState(
state, input: input, stateCallback: stateCallback, errorCallback: errorCallback)
if result {
return true
} else {
stateCallback(emptyState)
}
}
// MARK: Handle Marking.
if state is InputState.Marking {
let marking = state as! InputState.Marking
if _handleMarkingState(
state as! InputState.Marking, input: input, stateCallback: stateCallback,
errorCallback: errorCallback)
{
return true
}
state = marking.convertToInputting()
stateCallback(state)
}
// MARK: Handle BPMF Keys.
var composeReading: Bool = false
let skipPhoneticHandling = input.isReservedKey || input.isControlHold || input.isOptionHold
// See if Phonetic reading is valid.
if !skipPhoneticHandling && chkKeyValidity(charCode) {
combinePhoneticReadingBufferKey(charCode)
// If we have a tone marker, we have to insert the reading to the
// builder in other words, if we don't have a tone marker, we just
// update the composing buffer.
composeReading = checkWhetherToneMarkerConfirmsPhoneticReadingBuffer()
if !composeReading {
let inputting = buildInputtingState()
stateCallback(inputting)
return true
}
}
// See if we have composition if Enter/Space is hit and buffer is not empty.
// We use "|=" conditioning so that the tone marker key is also taken into account.
// However, Swift does not support "|=".
composeReading = composeReading || (!isPhoneticReadingBufferEmpty() && (input.isSpace || input.isEnter))
if composeReading {
let reading = getSyllableCompositionFromPhoneticReadingBuffer()
if !ifLangModelHasUnigrams(forKey: reading) {
IME.prtDebugIntel("B49C0979")
errorCallback()
let inputting = buildInputtingState()
stateCallback(inputting)
return true
}
// ... and insert it into the lattice grid...
insertReadingToBuilder(atCursor: reading)
// ... then walk the lattice grid...
let poppedText = _popOverflowComposingTextAndWalk()
// ... get and tweak override model suggestion if possible...
dealWithOverrideModelSuggestions()
// ... then update the text.
clearPhoneticReadingBuffer()
let inputting = buildInputtingState()
inputting.poppedText = poppedText
stateCallback(inputting)
if mgrPrefs.useSCPCTypingMode {
let choosingCandidates: InputState.ChoosingCandidate = _buildCandidateState(
inputting,
useVerticalMode: input.useVerticalMode)
if choosingCandidates.candidates.count == 1 {
clear()
let text: String = choosingCandidates.candidates.first ?? ""
let committing = InputState.Committing(poppedText: text)
stateCallback(committing)
if !mgrPrefs.associatedPhrasesEnabled {
stateCallback(emptyState)
} else {
let associatedPhrases =
buildAssociatePhraseState(
withKey: text,
useVerticalMode: input.useVerticalMode) as? InputState.AssociatedPhrases
if let associatedPhrases = associatedPhrases {
stateCallback(associatedPhrases)
} else {
stateCallback(emptyState)
}
}
} else {
stateCallback(choosingCandidates)
}
}
return true
}
// MARK: Calling candidate window using Space or Down or PageUp / PageDn.
if isPhoneticReadingBufferEmpty() && (state is InputState.NotEmpty)
&& (input.isExtraChooseCandidateKey || input.isExtraChooseCandidateKeyReverse || input.isSpace
|| input.isPageDown || input.isPageUp || input.isTab
|| (input.useVerticalMode && (input.isVerticalModeOnlyChooseCandidateKey)))
{
if input.isSpace {
// If the Space key is NOT set to be a selection key
if input.isShiftHold || !mgrPrefs.chooseCandidateUsingSpace {
if getBuilderCursorIndex() >= getBuilderLength() {
let composingBuffer = (state as! InputState.NotEmpty).composingBuffer
if (composingBuffer.count) != 0 {
let committing = InputState.Committing(poppedText: composingBuffer)
stateCallback(committing)
}
clear()
let committing = InputState.Committing(poppedText: " ")
stateCallback(committing)
let empty = InputState.Empty()
stateCallback(empty)
} else if ifLangModelHasUnigrams(forKey: " ") {
insertReadingToBuilder(atCursor: " ")
let poppedText = _popOverflowComposingTextAndWalk()
let inputting = buildInputtingState()
inputting.poppedText = poppedText
stateCallback(inputting)
}
return true
}
}
let choosingCandidates = _buildCandidateState(
state as! InputState.NotEmpty,
useVerticalMode: input.useVerticalMode)
stateCallback(choosingCandidates)
return true
}
// MARK: -
// MARK: Esc
if input.isESC { return _handleEscWithState(state, stateCallback: stateCallback, errorCallback: errorCallback) }
// 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 && input.isControlHold)
? _handleCtrlCommandEnterWithState(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()
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 = getCurrentMandarinParser()
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.
// F1-F12
// 便
if (state is InputState.NotEmpty) || !isPhoneticReadingBufferEmpty() {
IME.prtDebugIntel(
"Blocked data: charCode: \(charCode), keyCode: \(input.keyCode)")
IME.prtDebugIntel("A9BFF20E")
errorCallback()
stateCallback(state)
return true
}
return false
}
}

View File

@ -0,0 +1,48 @@
// 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 getCurrentMandarinParser() -> String {
return (mgrPrefs.mandarinParserName + "_")
}
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
}
}

View File

@ -0,0 +1,535 @@
// 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: - § State managements.
@objc extension KeyHandler {
// MARK: - State Building
func buildInputtingState() -> InputState.Inputting {
//
packageBufferStateMaterials()
//
let composedText = getComposedText()
let packagedCursorIndex = UInt(getPackagedCursorIndex())
let resultOfBefore = getStrLocationResult(isAfter: false)
let resultOfAfter = getStrLocationResult(isAfter: true)
//
let newState = InputState.Inputting(composingBuffer: composedText, cursorIndex: packagedCursorIndex)
//
var tooltip = ""
if (resultOfBefore == "") && (resultOfAfter != "") {
tooltip = String(format: NSLocalizedString("Cursor is after \"%@\".", comment: ""), resultOfAfter)
}
if (resultOfBefore != "") && (resultOfAfter == "") {
tooltip = String(format: NSLocalizedString("Cursor is before \"%@\".", comment: ""), resultOfBefore)
}
if (resultOfBefore != "") && (resultOfAfter != "") {
tooltip = String(
format: NSLocalizedString("Cursor is between \"%@\" and \"%@\".", comment: ""),
resultOfAfter, resultOfBefore)
}
//
newState.tooltip = tooltip
return newState
}
// MARK: -
func _buildCandidateState(
_ currentState: InputState.NotEmpty,
useVerticalMode: Bool
) -> InputState.ChoosingCandidate {
let candidatesArray = getCandidatesArray()
let state = InputState.ChoosingCandidate(
composingBuffer: currentState.composingBuffer,
cursorIndex: currentState.cursorIndex,
candidates: candidatesArray,
useVerticalMode: useVerticalMode)
return state
}
// MARK: -
func _handleMarkingState(
_ state: InputState.Marking,
input: keyParser,
stateCallback: @escaping (InputState) -> Void,
errorCallback: @escaping () -> Void
) -> Bool {
if input.isESC {
let inputting = buildInputtingState()
stateCallback(inputting)
return true
}
// Enter
if input.isEnter {
if let keyHandlerDelegate = delegate {
if !keyHandlerDelegate.keyHandler(self, didRequestWriteUserPhraseWith: state) {
IME.prtDebugIntel("5B69CC8D")
errorCallback()
return true
}
}
let inputting = buildInputtingState()
stateCallback(inputting)
return true
}
// Shift + Left
if (input.isCursorBackward || input.emacsKey == vChewingEmacsKey.backward) && (input.isShiftHold) {
var index = state.markerIndex
if index > 0 {
index = UInt((state.composingBuffer as NSString).previousUtf16Position(for: Int(index)))
let marking = InputState.Marking(
composingBuffer: state.composingBuffer,
cursorIndex: state.cursorIndex,
markerIndex: index,
readings: state.readings)
marking.tooltipForInputting = state.tooltipForInputting
if marking.markedRange.length == 0 {
let inputting = marking.convertToInputting()
stateCallback(inputting)
} else {
stateCallback(marking)
}
} else {
IME.prtDebugIntel("1149908D")
errorCallback()
stateCallback(state)
}
return true
}
// Shift + Right
if (input.isCursorForward || input.emacsKey == vChewingEmacsKey.forward) && (input.isShiftHold) {
var index = state.markerIndex
// NSString Zonble NSStringUtils
// 9B51408D
if index < ((state.composingBuffer as NSString).length) {
index = UInt((state.composingBuffer as NSString).nextUtf16Position(for: Int(index)))
let marking = InputState.Marking(
composingBuffer: state.composingBuffer,
cursorIndex: state.cursorIndex,
markerIndex: index,
readings: state.readings)
marking.tooltipForInputting = state.tooltipForInputting
if marking.markedRange.length == 0 {
let inputting = marking.convertToInputting()
stateCallback(inputting)
} else {
stateCallback(marking)
}
} else {
IME.prtDebugIntel("9B51408D")
errorCallback()
stateCallback(state)
}
return true
}
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()
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 _handleCtrlCommandEnterWithState(
_ 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()
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()
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()
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()
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()
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()
stateCallback(inputting)
} else {
IME.prtDebugIntel("7045E6F3")
errorCallback()
stateCallback(state)
}
}
return true
}
}

View File

@ -60,7 +60,7 @@ class ctlInputMethod: IMKInputController {
// currentKeyHandler keyHandler
// currentKeyHandler
static var currentKeyHandler: KeyHandler = KeyHandler()
@objc static var currentInputMode = ""
@objc static var currentInputMode = mgrPrefs.mostRecentInputMode
// MARK: - Keyboard Layout Specifier
@ -75,6 +75,9 @@ class ctlInputMethod: IMKInputController {
override init!(server: IMKServer!, delegate: Any!, client inputClient: Any!) {
super.init(server: server, delegate: delegate, client: inputClient)
keyHandler.delegate = self
//
activateServer(inputClient)
resetKeyHandler()
}
// MARK: - KeyHandler Reset Command
@ -95,7 +98,7 @@ class ctlInputMethod: IMKInputController {
currentClient = client
keyHandler.clear()
keyHandler.syncWithPreferences()
keyHandler.ensurePhoneticParser()
if let bundleCheckID = (client as? IMKTextInput)?.bundleIdentifier() {
if bundleCheckID != Bundle.main.bundleIdentifier {
// Override the keyboard layout to the basic one.
@ -598,9 +601,7 @@ extension ctlInputMethod: ctlCandidateDelegate {
let selectedValue = state.candidates[Int(index)]
keyHandler.fixNode(value: selectedValue)
guard let inputting = keyHandler.buildInputtingState() as? InputState.Inputting else {
return
}
let inputting = keyHandler.buildInputtingState()
if mgrPrefs.useSCPCTypingMode {
keyHandler.clear()

View File

@ -261,6 +261,7 @@ extension ctlInputMethod {
}
@objc func selfTerminate(_ sender: Any?) {
NSApp.activate(ignoringOtherApps: true)
NSApp.terminate(nil)
}

View File

@ -28,6 +28,7 @@ import Cocoa
struct UserDef {
static let kIsDebugModeEnabled = "_DebugMode"
static let kMostRecentInputMode = "MostRecentInputMode"
static let kUserDataFolderSpecified = "UserDataFolderSpecified"
static let kCheckUpdateAutomatically = "CheckUpdateAutomatically"
static let kMandarinParser = "MandarinParser"
@ -204,6 +205,7 @@ public class mgrPrefs: NSObject {
static var allKeys: [String] {
[
UserDef.kIsDebugModeEnabled,
UserDef.kMostRecentInputMode,
UserDef.kUserDataFolderSpecified,
UserDef.kMandarinParser,
UserDef.kBasicKeyboardLayout,
@ -238,6 +240,7 @@ public class mgrPrefs: NSObject {
// MARK: - Preferences Module plist
@objc public static func setMissingDefaults() {
UserDefaults.standard.setDefault(mgrPrefs.isDebugModeEnabled, forKey: UserDef.kIsDebugModeEnabled)
UserDefaults.standard.setDefault(mgrPrefs.mostRecentInputMode, forKey: UserDef.kMostRecentInputMode)
UserDefaults.standard.setDefault(mgrPrefs.checkUpdateAutomatically, forKey: UserDef.kCheckUpdateAutomatically)
UserDefaults.standard.setDefault(
mgrPrefs.showPageButtonsInCandidateWindow, forKey: UserDef.kShowPageButtonsInCandidateWindow)
@ -271,6 +274,9 @@ public class mgrPrefs: NSObject {
@UserDefault(key: UserDef.kIsDebugModeEnabled, defaultValue: false)
@objc static var isDebugModeEnabled: Bool
@UserDefault(key: UserDef.kMostRecentInputMode, defaultValue: "")
@objc static var mostRecentInputMode: String
@UserDefault(key: UserDef.kCheckUpdateAutomatically, defaultValue: false)
@objc static var checkUpdateAutomatically: Bool

View File

@ -13,7 +13,9 @@
5B27AD6B27CB1F9B000ED75B /* data-zhuyinwen.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5B27AD6927CB1F9B000ED75B /* data-zhuyinwen.txt */; };
5B2DB16F27AF6891006D874E /* data-chs.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5B2DB16D27AF6891006D874E /* data-chs.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 */; };
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 */; };
@ -29,7 +31,9 @@
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 */; };
5B7BC4B027AFFBE800F66C24 /* frmPrefWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5B7BC4AE27AFFBE800F66C24 /* frmPrefWindow.xib */; };
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 */; };
@ -185,7 +189,9 @@
5B2DB16E27AF6891006D874E /* data-cht.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "data-cht.txt"; path = "Data/data-cht.txt"; sourceTree = "<group>"; };
5B2DB17127AF8771006D874E /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; name = Makefile; path = Data/Makefile; 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>"; };
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>"; };
@ -206,8 +212,10 @@
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>"; };
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_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>"; };
@ -324,7 +332,7 @@
D4E33D8927A838CF006DB1CF /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Localizable.strings; sourceTree = "<group>"; };
D4E33D8E27A838F0006DB1CF /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/InfoPlist.strings; sourceTree = "<group>"; };
D4E569DA27A34CC100AC2CEF /* KeyHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KeyHandler.h; sourceTree = "<group>"; };
D4E569DB27A34CC100AC2CEF /* KeyHandler.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = KeyHandler.mm; sourceTree = "<group>"; };
D4E569DB27A34CC100AC2CEF /* KeyHandler.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = KeyHandler.mm; sourceTree = "<group>"; usesTabs = 0; };
D4F0BBDE279AF1AF0071253C /* ArchiveUtil.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArchiveUtil.swift; sourceTree = "<group>"; };
D4F0BBE0279AF8B30071253C /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
D4F0BBE2279B08900071253C /* Chronosphere.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Chronosphere.h; sourceTree = "<group>"; };
@ -423,6 +431,10 @@
D461B791279DAC010070E734 /* InputState.swift */,
D4E569DA27A34CC100AC2CEF /* KeyHandler.h */,
D4E569DB27A34CC100AC2CEF /* KeyHandler.mm */,
5B7F225C2808501000DDD3CB /* KeyHandler_HandleInput.swift */,
5B782EC3280C243C007276DE /* KeyHandler_HandleCandidate.swift */,
5B61B0C9280BEFD4002E3CFA /* KeyHandler_Misc.swift */,
5B3133BE280B229700A4A505 /* KeyHandler_States.swift */,
D456576D279E4F7B00DF6BC9 /* KeyParser.swift */,
6ACC3D3E27914F2400F1B140 /* KeyValueBlobReader.cpp */,
6ACC3D3C27914AAB00F1B140 /* KeyValueBlobReader.h */,
@ -1061,6 +1073,7 @@
D427F76C278CA2B0004A2160 /* AppDelegate.swift in Sources */,
5BA9FD4527FEF3C9002DE248 /* ToolbarItemStyleViewController.swift in Sources */,
5BA9FD4127FEF3C8002DE248 /* PreferencesStyle.swift in Sources */,
5B7F225D2808501000DDD3CB /* KeyHandler_HandleInput.swift in Sources */,
5BA9FD1227FEDB6B002DE248 /* suiPrefPaneExperience.swift in Sources */,
6ACC3D442793701600F1B140 /* ParselessPhraseDB.cpp in Sources */,
D461B792279DAC010070E734 /* InputState.swift in Sources */,
@ -1076,6 +1089,7 @@
5BE78BE027B38804005EA1BE /* LMConsolidator.mm in Sources */,
D456576E279E4F7B00DF6BC9 /* KeyParser.swift in Sources */,
5BA9FD1027FEDB6B002DE248 /* suiPrefPaneKeyboard.swift in Sources */,
5B3133BF280B229700A4A505 /* KeyHandler_States.swift in Sources */,
5BA9FD4327FEF3C8002DE248 /* Preferences.swift in Sources */,
5BA9FD4427FEF3C8002DE248 /* SegmentedControlStyleViewController.swift in Sources */,
D47F7DCE278BFB57002F9DD7 /* ctlPrefWindow.swift in Sources */,
@ -1090,6 +1104,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 */,
@ -1099,6 +1114,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 */,
@ -1434,7 +1450,6 @@
"$(OTHER_CFLAGS)",
"-fcxx-modules",
);
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
@ -1475,8 +1490,6 @@
"$(OTHER_CFLAGS)",
"-fcxx-modules",
);
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Release;
};