KeyHandler // Say goodbye to ObjCpp.

This commit is contained in:
ShikiSuen 2022-05-02 13:49:41 +08:00
parent 62961c44f7
commit 25b3a1b766
13 changed files with 283 additions and 300 deletions

View File

@ -26,37 +26,18 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
@class InputHandler;
@class InputState;
@class KeyHandlerSputnik;
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
@class KeyHandler; @interface Composer : NSObject
+ (BOOL)chkKeyValidity:(UniChar)charCode;
@protocol KeyHandlerDelegate <NSObject> + (BOOL)isBufferEmpty;
- (id)ctlCandidateForKeyHandler:(KeyHandler *)keyHandler; + (void)clearBuffer;
- (void)keyHandler:(KeyHandler *)keyHandler didSelectCandidateAtIndex:(NSInteger)index ctlCandidate:(id)controller; + (void)combineReadingKey:(UniChar)charCode;
- (BOOL)keyHandler:(KeyHandler *)keyHandler didRequestWriteUserPhraseWithState:(InputState *)state; + (BOOL)checkWhetherToneMarkerConfirms;
@end + (NSString *)getSyllableComposition;
+ (void)doBackSpaceToBuffer;
@interface KeyHandler : NSObject + (NSString *)getComposition;
+ (void)ensureParser;
@property(weak, nonatomic) id<KeyHandlerDelegate> delegate;
// The following items need to be exposed to Swift:
- (BOOL)checkWhetherToneMarkerConfirmsPhoneticReadingBuffer;
- (BOOL)chkKeyValidity:(UniChar)value;
- (BOOL)isPhoneticReadingBufferEmpty;
- (BOOL)isPrintable:(UniChar)charCode;
- (NSString *)getCompositionFromPhoneticReadingBuffer;
- (NSString *)getSyllableCompositionFromPhoneticReadingBuffer;
- (void)clearPhoneticReadingBuffer;
- (void)combinePhoneticReadingBufferKey:(UniChar)charCode;
- (void)doBackSpaceToPhoneticReadingBuffer;
- (void)ensurePhoneticParser;
@end @end
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END

116
Source/3rdParty/OVMandarin/Composer.mm vendored Normal file
View File

@ -0,0 +1,116 @@
// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License).
// All possible vChewing-specific modifications are of:
// (c) 2021 and onwards The vChewing Project (MIT-NTL 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 "Composer.hh"
#import "Mandarin.h"
#import "vChewing-Swift.h"
static Mandarin::BopomofoReadingBuffer *PhoneticBuffer;
@implementation Composer
+ (BOOL)chkKeyValidity:(UniChar)charCode
{
return PhoneticBuffer->isValidKey((char)charCode);
}
+ (BOOL)isBufferEmpty
{
return PhoneticBuffer->isEmpty();
}
+ (void)clearBuffer
{
PhoneticBuffer->clear();
}
+ (void)combineReadingKey:(UniChar)charCode
{
PhoneticBuffer->combineKey((char)charCode);
}
+ (BOOL)checkWhetherToneMarkerConfirms
{
return PhoneticBuffer->hasToneMarker();
}
+ (NSString *)getSyllableComposition
{
return [NSString stringWithUTF8String:PhoneticBuffer->syllable().composedString().c_str()];
}
+ (void)doBackSpaceToBuffer
{
PhoneticBuffer->backspace();
}
+ (NSString *)getComposition
{
return [NSString stringWithUTF8String:PhoneticBuffer->composedString().c_str()];
}
+ (void)ensureParser
{
if (PhoneticBuffer)
{
switch (mgrPrefs.mandarinParser)
{
case MandarinParserOfStandard:
PhoneticBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::StandardLayout());
break;
case MandarinParserOfEten:
PhoneticBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::ETenLayout());
break;
case MandarinParserOfHsu:
PhoneticBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::HsuLayout());
break;
case MandarinParserOfEen26:
PhoneticBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::ETen26Layout());
break;
case MandarinParserOfIBM:
PhoneticBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::IBMLayout());
break;
case MandarinParserOfMiTAC:
PhoneticBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::MiTACLayout());
break;
case MandarinParserOfFakeSeigyou:
PhoneticBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::FakeSeigyouLayout());
break;
case MandarinParserOfHanyuPinyin:
PhoneticBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::HanyuPinyinLayout());
break;
default:
PhoneticBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::StandardLayout());
mgrPrefs.mandarinParser = MandarinParserOfStandard;
}
}
else
{
PhoneticBuffer = new Mandarin::BopomofoReadingBuffer(Mandarin::BopomofoKeyboardLayout::StandardLayout());
}
}
@end

View File

@ -30,4 +30,5 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@import Foundation; @import Foundation;
#import "KeyHandler.h" #import "CTools.h"
#import "Composer.hh"

View File

@ -1,6 +1,4 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License). // 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 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 this software and associated documentation files (the "Software"), to deal in
@ -24,19 +22,12 @@ 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. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
import Cocoa #import <Foundation/Foundation.h>
// MARK: - KeyHandler Sputnik. NS_ASSUME_NONNULL_BEGIN
// Swift Extension 不允許直接存放這些變數,所以就寫了這個衛星型別。 @interface CTools : NSObject
// 一旦 Mandarin 模組被 Swift 化,整個 KeyHandler 就可以都用 Swift。 + (BOOL)isPrintable:(UniChar)charCode;
// 屆時會考慮將該衛星型別內的變數與常數都挪回 KeyHandler_Kernel 內。 @end
class KeyHandlerSputnik: NSObject { NS_ASSUME_NONNULL_END
static let kEpsilon: Double = 0.000001
static var inputMode: String = ""
static var languageModel: vChewing.LMInstantiator = .init()
static var userOverrideModel: vChewing.LMUserOverride = .init()
static var builder: Megrez.BlockReadingBuilder = .init(lm: languageModel)
static var walkedNodes: [Megrez.NodeAnchor] = []
}

View File

@ -0,0 +1,32 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL 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 "CTools.h"
@implementation CTools
+ (BOOL)isPrintable:(UniChar)charCode
{
return isprint(charCode);
}
@end

View File

@ -1,155 +0,0 @@
// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License).
// All possible vChewing-specific modifications are of:
// (c) 2021 and onwards The vChewing Project (MIT-NTL 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 "KeyHandler.h"
#import "Mandarin.h"
#import "vChewing-Swift.h"
#import <string>
typedef Mandarin::BopomofoReadingBuffer PhoneticBuffer;
// NON-SWIFTIFIABLE
@implementation KeyHandler
{
// the reading buffer that takes user input
PhoneticBuffer *_bpmfReadingBuffer;
}
@synthesize delegate = _delegate;
// Not migrable as long as there's still ObjC++ components needed.
// Will deprecate this once Mandarin gets Swiftified.
- (instancetype)init
{
self = [super init];
if (self)
{
[self ensurePhoneticParser];
[self setInputMode:ctlInputMethod.currentInputMode];
}
return self;
}
// NON-SWIFTIFIABLE: Mandarin
- (void)dealloc
{ // clean up everything
if (_bpmfReadingBuffer)
delete _bpmfReadingBuffer;
}
// MARK: - 目前到這裡了
#pragma mark - 必須用 ObjCpp 處理的部分: Mandarin
- (BOOL)chkKeyValidity:(UniChar)charCode
{
return _bpmfReadingBuffer->isValidKey((char)charCode);
}
- (BOOL)isPhoneticReadingBufferEmpty
{
return _bpmfReadingBuffer->isEmpty();
}
- (void)clearPhoneticReadingBuffer
{
_bpmfReadingBuffer->clear();
}
- (void)combinePhoneticReadingBufferKey:(UniChar)charCode
{
_bpmfReadingBuffer->combineKey((char)charCode);
}
- (BOOL)checkWhetherToneMarkerConfirmsPhoneticReadingBuffer
{
return _bpmfReadingBuffer->hasToneMarker();
}
- (NSString *)getSyllableCompositionFromPhoneticReadingBuffer
{
return [NSString stringWithUTF8String:_bpmfReadingBuffer->syllable().composedString().c_str()];
}
- (void)doBackSpaceToPhoneticReadingBuffer
{
_bpmfReadingBuffer->backspace();
}
- (NSString *)getCompositionFromPhoneticReadingBuffer
{
return [NSString stringWithUTF8String:_bpmfReadingBuffer->composedString().c_str()];
}
- (void)ensurePhoneticParser
{
if (_bpmfReadingBuffer)
{
switch (mgrPrefs.mandarinParser)
{
case MandarinParserOfStandard:
_bpmfReadingBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::StandardLayout());
break;
case MandarinParserOfEten:
_bpmfReadingBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::ETenLayout());
break;
case MandarinParserOfHsu:
_bpmfReadingBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::HsuLayout());
break;
case MandarinParserOfEen26:
_bpmfReadingBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::ETen26Layout());
break;
case MandarinParserOfIBM:
_bpmfReadingBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::IBMLayout());
break;
case MandarinParserOfMiTAC:
_bpmfReadingBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::MiTACLayout());
break;
case MandarinParserOfFakeSeigyou:
_bpmfReadingBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::FakeSeigyouLayout());
break;
case MandarinParserOfHanyuPinyin:
_bpmfReadingBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::HanyuPinyinLayout());
break;
default:
_bpmfReadingBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::StandardLayout());
mgrPrefs.mandarinParser = MandarinParserOfStandard;
}
}
else
{
_bpmfReadingBuffer = new Mandarin::BopomofoReadingBuffer(Mandarin::BopomofoKeyboardLayout::StandardLayout());
}
}
#pragma mark - 威注音認為有必要單獨拿出來處理的部分,交給 Swift 則有些困難。
- (BOOL)isPrintable:(UniChar)charCode
{
return isprint(charCode);
}
@end

View File

@ -34,16 +34,31 @@ public enum InputMode: String {
// MARK: - Delegate. // MARK: - Delegate.
protocol KeyHandlerDelegate: NSObjectProtocol {
func ctlCandidate(for _: KeyHandler) -> Any
func keyHandler(
_: KeyHandler, didSelectCandidateAt index: Int,
ctlCandidate controller: Any
)
func keyHandler(_ keyHandler: KeyHandler, didRequestWriteUserPhraseWith state: InputState)
-> Bool
}
// MARK: - Kernel. // MARK: - Kernel.
extension KeyHandler { class KeyHandler: NSObject {
var kEpsilon: Double { let kEpsilon: Double = 0.000001
KeyHandlerSputnik.kEpsilon var _inputMode: String = ""
} var _languageModel: vChewing.LMInstantiator = .init()
var _userOverrideModel: vChewing.LMUserOverride = .init()
var _builder: Megrez.BlockReadingBuilder
var _walkedNodes: [Megrez.NodeAnchor] = []
weak var delegate: KeyHandlerDelegate?
var inputMode: InputMode { var inputMode: InputMode {
get { get {
switch KeyHandlerSputnik.inputMode { switch _inputMode {
case "org.atelierInmu.inputmethod.vChewing.IMECHS": case "org.atelierInmu.inputmethod.vChewing.IMECHS":
return InputMode.imeModeCHS return InputMode.imeModeCHS
case "org.atelierInmu.inputmethod.vChewing.IMECHT": case "org.atelierInmu.inputmethod.vChewing.IMECHT":
@ -55,17 +70,17 @@ extension KeyHandler {
set { setInputMode(newValue.rawValue) } set { setInputMode(newValue.rawValue) }
} }
// TODO: Will reenable this once Mandarin gets Swiftified. override init() {
// override public init() { _builder = Megrez.BlockReadingBuilder(lm: _languageModel)
// self.ensurePhoneticParser() super.init()
// self.setInputMode(ctlInputMethod.currentInputMode) Composer.ensureParser()
// super.init() setInputMode(ctlInputMethod.currentInputMode)
// } }
func clear() { func clear() {
clearPhoneticReadingBuffer() Composer.clearBuffer()
KeyHandlerSputnik.builder.clear() _builder.clear()
KeyHandlerSputnik.walkedNodes.removeAll() _walkedNodes.removeAll()
} }
// ObjC 使 // ObjC 使
@ -79,7 +94,7 @@ extension KeyHandler {
mgrPrefs.mostRecentInputMode = ctlInputMethod.currentInputMode mgrPrefs.mostRecentInputMode = ctlInputMethod.currentInputMode
// _inputMode ctlInputMethod // _inputMode ctlInputMethod
if KeyHandlerSputnik.inputMode != ctlInputMethod.currentInputMode { if _inputMode != ctlInputMethod.currentInputMode {
// Reinitiate language models if necessary // Reinitiate language models if necessary
setInputModesToLM(isCHS: isCHS) setInputModesToLM(isCHS: isCHS)
@ -89,12 +104,12 @@ extension KeyHandler {
// Create new grid builder. // Create new grid builder.
createNewBuilder() createNewBuilder()
if !isPhoneticReadingBufferEmpty() { if !Composer.isBufferEmpty() {
clearPhoneticReadingBuffer() Composer.clearBuffer()
} }
} }
// //
KeyHandlerSputnik.inputMode = ctlInputMethod.currentInputMode _inputMode = ctlInputMethod.currentInputMode
} }
// MARK: - Functions dealing with Megrez. // MARK: - Functions dealing with Megrez.
@ -103,14 +118,14 @@ extension KeyHandler {
// Retrieve the most likely trellis, i.e. a Maximum Likelihood Estimation // Retrieve the most likely trellis, i.e. a Maximum Likelihood Estimation
// of the best possible Mandarin characters given the input syllables, // of the best possible Mandarin characters given the input syllables,
// using the Viterbi algorithm implemented in the Gramambular library // using the Viterbi algorithm implemented in the Gramambular library
let walker = Megrez.Walker(grid: KeyHandlerSputnik.builder.grid()) let walker = Megrez.Walker(grid: _builder.grid())
// the reverse walk traces the trellis from the end // the reverse walk traces the trellis from the end
let walked: [Megrez.NodeAnchor] = walker.reverseWalk(at: KeyHandlerSputnik.builder.grid().width()) let walked: [Megrez.NodeAnchor] = walker.reverseWalk(at: _builder.grid().width())
// then we use ".reversed()" to reverse the nodes so that we get the forward-walked nodes // then we use ".reversed()" to reverse the nodes so that we get the forward-walked nodes
KeyHandlerSputnik.walkedNodes.removeAll() _walkedNodes.removeAll()
KeyHandlerSputnik.walkedNodes.append(contentsOf: walked.reversed()) _walkedNodes.append(contentsOf: walked.reversed())
} }
func popOverflowComposingTextAndWalk() -> String { func popOverflowComposingTextAndWalk() -> String {
@ -123,13 +138,13 @@ extension KeyHandler {
// (i.e. popped out.) // (i.e. popped out.)
var poppedText = "" var poppedText = ""
if KeyHandlerSputnik.builder.grid().width() > mgrPrefs.composingBufferSize { if _builder.grid().width() > mgrPrefs.composingBufferSize {
if KeyHandlerSputnik.walkedNodes.count > 0 { if _walkedNodes.count > 0 {
let anchor: Megrez.NodeAnchor = KeyHandlerSputnik.walkedNodes[0] let anchor: Megrez.NodeAnchor = _walkedNodes[0]
if let theNode = anchor.node { if let theNode = anchor.node {
poppedText = theNode.currentKeyValue().value poppedText = theNode.currentKeyValue().value
} }
KeyHandlerSputnik.builder.removeHeadReadings(count: anchor.spanningLength) _builder.removeHeadReadings(count: anchor.spanningLength)
} }
} }
walk() walk()
@ -138,15 +153,15 @@ extension KeyHandler {
func buildAssociatePhraseArray(withKey key: String) -> [String] { func buildAssociatePhraseArray(withKey key: String) -> [String] {
var arrResult: [String] = [] var arrResult: [String] = []
if KeyHandlerSputnik.languageModel.hasAssociatedPhrasesForKey(key) { if _languageModel.hasAssociatedPhrasesForKey(key) {
arrResult.append(contentsOf: KeyHandlerSputnik.languageModel.associatedPhrasesForKey(key)) arrResult.append(contentsOf: _languageModel.associatedPhrasesForKey(key))
} }
return arrResult return arrResult
} }
func fixNode(value: String) { func fixNode(value: String) {
let cursorIndex: Int = getActualCandidateCursorIndex() let cursorIndex: Int = getActualCandidateCursorIndex()
let selectedNode: Megrez.NodeAnchor = KeyHandlerSputnik.builder.grid().fixNodeSelectedCandidate( let selectedNode: Megrez.NodeAnchor = _builder.grid().fixNodeSelectedCandidate(
location: cursorIndex, value: value location: cursorIndex, value: value
) )
// //
@ -167,8 +182,8 @@ extension KeyHandler {
} }
} }
if addToUserOverrideModel { if addToUserOverrideModel {
KeyHandlerSputnik.userOverrideModel.observe( _userOverrideModel.observe(
walkedNodes: KeyHandlerSputnik.walkedNodes, cursorIndex: cursorIndex, candidate: value, walkedNodes: _walkedNodes, cursorIndex: cursorIndex, candidate: value,
timestamp: NSDate().timeIntervalSince1970 timestamp: NSDate().timeIntervalSince1970
) )
} }
@ -177,7 +192,7 @@ extension KeyHandler {
if mgrPrefs.moveCursorAfterSelectingCandidate { if mgrPrefs.moveCursorAfterSelectingCandidate {
var nextPosition = 0 var nextPosition = 0
for node in KeyHandlerSputnik.walkedNodes { for node in _walkedNodes {
if nextPosition >= cursorIndex { break } if nextPosition >= cursorIndex { break }
nextPosition += node.spanningLength nextPosition += node.spanningLength
} }
@ -216,13 +231,13 @@ extension KeyHandler {
var overrideValue = var overrideValue =
mgrPrefs.useSCPCTypingMode mgrPrefs.useSCPCTypingMode
? "" ? ""
: KeyHandlerSputnik.userOverrideModel.suggest( : _userOverrideModel.suggest(
walkedNodes: KeyHandlerSputnik.walkedNodes, cursorIndex: getBuilderCursorIndex(), walkedNodes: _walkedNodes, cursorIndex: getBuilderCursorIndex(),
timestamp: NSDate().timeIntervalSince1970 timestamp: NSDate().timeIntervalSince1970
) )
if !overrideValue.isEmpty { if !overrideValue.isEmpty {
KeyHandlerSputnik.builder.grid().overrideNodeScoreForSelectedCandidate( _builder.grid().overrideNodeScoreForSelectedCandidate(
location: getActualCandidateCursorIndex(), location: getActualCandidateCursorIndex(),
value: &overrideValue, value: &overrideValue,
overridingScore: findHighestScore(nodes: getRawNodes(), epsilon: kEpsilon) overridingScore: findHighestScore(nodes: getRawNodes(), epsilon: kEpsilon)
@ -245,65 +260,65 @@ extension KeyHandler {
// MARK: - Extracted methods and functions. // MARK: - Extracted methods and functions.
func isBuilderEmpty() -> Bool { KeyHandlerSputnik.builder.grid().width() == 0 } func isBuilderEmpty() -> Bool { _builder.grid().width() == 0 }
func getRawNodes() -> [Megrez.NodeAnchor] { func getRawNodes() -> [Megrez.NodeAnchor] {
/// 使 nodesCrossing macOS /// 使 nodesCrossing macOS
/// nodeCrossing Megrez /// nodeCrossing Megrez
/// Windows /// Windows
mgrPrefs.setRearCursorMode mgrPrefs.setRearCursorMode
? KeyHandlerSputnik.builder.grid().nodesCrossingOrEndingAt(location: getActualCandidateCursorIndex()) ? _builder.grid().nodesCrossingOrEndingAt(location: getActualCandidateCursorIndex())
: KeyHandlerSputnik.builder.grid().nodesEndingAt(location: getActualCandidateCursorIndex()) : _builder.grid().nodesEndingAt(location: getActualCandidateCursorIndex())
} }
func setInputModesToLM(isCHS: Bool) { func setInputModesToLM(isCHS: Bool) {
KeyHandlerSputnik.languageModel = isCHS ? mgrLangModel.lmCHS : mgrLangModel.lmCHT _languageModel = isCHS ? mgrLangModel.lmCHS : mgrLangModel.lmCHT
KeyHandlerSputnik.userOverrideModel = isCHS ? mgrLangModel.uomCHS : mgrLangModel.uomCHT _userOverrideModel = isCHS ? mgrLangModel.uomCHS : mgrLangModel.uomCHT
} }
func syncBaseLMPrefs() { func syncBaseLMPrefs() {
KeyHandlerSputnik.languageModel.isPhraseReplacementEnabled = mgrPrefs.phraseReplacementEnabled _languageModel.isPhraseReplacementEnabled = mgrPrefs.phraseReplacementEnabled
KeyHandlerSputnik.languageModel.isCNSEnabled = mgrPrefs.cns11643Enabled _languageModel.isCNSEnabled = mgrPrefs.cns11643Enabled
KeyHandlerSputnik.languageModel.isSymbolEnabled = mgrPrefs.symbolInputEnabled _languageModel.isSymbolEnabled = mgrPrefs.symbolInputEnabled
} }
func createNewBuilder() { func createNewBuilder() {
KeyHandlerSputnik.builder = Megrez.BlockReadingBuilder(lm: KeyHandlerSputnik.languageModel) _builder = Megrez.BlockReadingBuilder(lm: _languageModel)
// Each Mandarin syllable is separated by a hyphen. // Each Mandarin syllable is separated by a hyphen.
KeyHandlerSputnik.builder.setJoinSeparator(separator: "-") _builder.setJoinSeparator(separator: "-")
} }
func currentReadings() -> [String] { KeyHandlerSputnik.builder.readings() } func currentReadings() -> [String] { _builder.readings() }
func ifLangModelHasUnigrams(forKey reading: String) -> Bool { func ifLangModelHasUnigrams(forKey reading: String) -> Bool {
KeyHandlerSputnik.languageModel.hasUnigramsFor(key: reading) _languageModel.hasUnigramsFor(key: reading)
} }
func insertReadingToBuilderAtCursor(reading: String) { func insertReadingToBuilderAtCursor(reading: String) {
KeyHandlerSputnik.builder.insertReadingAtCursor(reading: reading) _builder.insertReadingAtCursor(reading: reading)
} }
func setBuilderCursorIndex(value: Int) { func setBuilderCursorIndex(value: Int) {
KeyHandlerSputnik.builder.setCursorIndex(newIndex: value) _builder.setCursorIndex(newIndex: value)
} }
func getBuilderCursorIndex() -> Int { func getBuilderCursorIndex() -> Int {
KeyHandlerSputnik.builder.cursorIndex() _builder.cursorIndex()
} }
func getBuilderLength() -> Int { func getBuilderLength() -> Int {
KeyHandlerSputnik.builder.length() _builder.length()
} }
func deleteBuilderReadingInFrontOfCursor() { func deleteBuilderReadingInFrontOfCursor() {
KeyHandlerSputnik.builder.deleteReadingBeforeCursor() _builder.deleteReadingBeforeCursor()
} }
func deleteBuilderReadingAfterCursor() { func deleteBuilderReadingAfterCursor() {
KeyHandlerSputnik.builder.deleteReadingAfterCursor() _builder.deleteReadingAfterCursor()
} }
func getKeyLengthAtIndexZero() -> Int { func getKeyLengthAtIndexZero() -> Int {
KeyHandlerSputnik.walkedNodes[0].node?.currentKeyValue().value.count ?? 0 _walkedNodes[0].node?.currentKeyValue().value.count ?? 0
} }
} }

View File

@ -28,7 +28,7 @@ import Cocoa
// MARK: - § Handle Candidate State. // MARK: - § Handle Candidate State.
@objc extension KeyHandler { extension KeyHandler {
func handleCandidate( func handleCandidate(
state: InputState, state: InputState,
input: InputHandler, input: InputHandler,
@ -331,7 +331,7 @@ import Cocoa
let punctuation: String = arrPunctuations.joined(separator: "") let punctuation: String = arrPunctuations.joined(separator: "")
var shouldAutoSelectCandidate: Bool = var shouldAutoSelectCandidate: Bool =
chkKeyValidity(charCode) || ifLangModelHasUnigrams(forKey: customPunctuation) Composer.chkKeyValidity(charCode) || ifLangModelHasUnigrams(forKey: customPunctuation)
|| ifLangModelHasUnigrams(forKey: punctuation) || ifLangModelHasUnigrams(forKey: punctuation)
if !shouldAutoSelectCandidate, input.isUpperCaseASCIILetterKey { if !shouldAutoSelectCandidate, input.isUpperCaseASCIILetterKey {

View File

@ -28,7 +28,7 @@ import Cocoa
// MARK: - § Handle Input with States. // MARK: - § Handle Input with States.
@objc extension KeyHandler { extension KeyHandler {
func handle( func handle(
input: InputHandler, input: InputHandler,
state: InputState, state: InputState,
@ -75,7 +75,7 @@ import Cocoa
// If ASCII but not printable, don't use insertText:replacementRange: // If ASCII but not printable, don't use insertText:replacementRange:
// Certain apps don't handle non-ASCII char insertions. // Certain apps don't handle non-ASCII char insertions.
if charCode < 0x80, !isPrintable(charCode) { if charCode < 0x80, !CTools.isPrintable(charCode) {
return false return false
} }
@ -90,7 +90,7 @@ import Cocoa
if input.isNumericPad { if input.isNumericPad {
if !input.isLeft, !input.isRight, !input.isDown, if !input.isLeft, !input.isRight, !input.isDown,
!input.isUp, !input.isSpace, isPrintable(charCode) !input.isUp, !input.isSpace, CTools.isPrintable(charCode)
{ {
clear() clear()
stateCallback(InputState.Empty()) stateCallback(InputState.Empty())
@ -139,13 +139,13 @@ import Cocoa
let skipPhoneticHandling = input.isReservedKey || input.isControlHold || input.isOptionHold let skipPhoneticHandling = input.isReservedKey || input.isControlHold || input.isOptionHold
// See if Phonetic reading is valid. // See if Phonetic reading is valid.
if !skipPhoneticHandling && chkKeyValidity(charCode) { if !skipPhoneticHandling && Composer.chkKeyValidity(charCode) {
combinePhoneticReadingBufferKey(charCode) Composer.combineReadingKey(charCode)
// If we have a tone marker, we have to insert the reading to the // 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 // builder in other words, if we don't have a tone marker, we just
// update the composing buffer. // update the composing buffer.
composeReading = checkWhetherToneMarkerConfirmsPhoneticReadingBuffer() composeReading = Composer.checkWhetherToneMarkerConfirms()
if !composeReading { if !composeReading {
stateCallback(buildInputtingState()) stateCallback(buildInputtingState())
return true return true
@ -155,9 +155,9 @@ import Cocoa
// See if we have composition if Enter/Space is hit and buffer is not empty. // 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. // We use "|=" conditioning so that the tone marker key is also taken into account.
// However, Swift does not support "|=". // However, Swift does not support "|=".
composeReading = composeReading || (!isPhoneticReadingBufferEmpty() && (input.isSpace || input.isEnter)) composeReading = composeReading || (!Composer.isBufferEmpty() && (input.isSpace || input.isEnter))
if composeReading { if composeReading {
let reading = getSyllableCompositionFromPhoneticReadingBuffer() let reading = Composer.getSyllableComposition()
if !ifLangModelHasUnigrams(forKey: reading) { if !ifLangModelHasUnigrams(forKey: reading) {
IME.prtDebugIntel("B49C0979語彙庫內無「\(reading)」的匹配記錄。") IME.prtDebugIntel("B49C0979語彙庫內無「\(reading)」的匹配記錄。")
@ -176,7 +176,7 @@ import Cocoa
dealWithOverrideModelSuggestions() dealWithOverrideModelSuggestions()
// ... then update the text. // ... then update the text.
clearPhoneticReadingBuffer() Composer.clearBuffer()
let inputting = buildInputtingState() let inputting = buildInputtingState()
inputting.poppedText = poppedText inputting.poppedText = poppedText
@ -216,7 +216,7 @@ import Cocoa
// MARK: Calling candidate window using Space or Down or PageUp / PageDn. // MARK: Calling candidate window using Space or Down or PageUp / PageDn.
if let currentState = state as? InputState.NotEmpty { if let currentState = state as? InputState.NotEmpty {
if isPhoneticReadingBufferEmpty(), if Composer.isBufferEmpty(),
input.isExtraChooseCandidateKey || input.isExtraChooseCandidateKeyReverse || input.isSpace input.isExtraChooseCandidateKey || input.isExtraChooseCandidateKeyReverse || input.isSpace
|| input.isPageDown || input.isPageUp || input.isTab || input.isPageDown || input.isPageUp || input.isTab
|| (input.useVerticalMode && (input.isVerticalModeOnlyChooseCandidateKey)) || (input.useVerticalMode && (input.isVerticalModeOnlyChooseCandidateKey))
@ -329,7 +329,7 @@ import Cocoa
if input.isSymbolMenuPhysicalKey && !input.isShiftHold { if input.isSymbolMenuPhysicalKey && !input.isShiftHold {
if !input.isOptionHold { if !input.isOptionHold {
if ifLangModelHasUnigrams(forKey: "_punctuation_list") { if ifLangModelHasUnigrams(forKey: "_punctuation_list") {
if isPhoneticReadingBufferEmpty() { if Composer.isBufferEmpty() {
insertReadingToBuilderAtCursor(reading: "_punctuation_list") insertReadingToBuilderAtCursor(reading: "_punctuation_list")
let poppedText: String! = popOverflowComposingTextAndWalk() let poppedText: String! = popOverflowComposingTextAndWalk()
let inputting = buildInputtingState() let inputting = buildInputtingState()
@ -418,7 +418,7 @@ import Cocoa
// "thinking" that the key is not actually consumed. // "thinking" that the key is not actually consumed.
// F1-F12 // F1-F12
// 便 // 便
if (state is InputState.NotEmpty) || !isPhoneticReadingBufferEmpty() { if (state is InputState.NotEmpty) || !Composer.isBufferEmpty() {
IME.prtDebugIntel( IME.prtDebugIntel(
"Blocked data: charCode: \(charCode), keyCode: \(input.keyCode)") "Blocked data: charCode: \(charCode), keyCode: \(input.keyCode)")
IME.prtDebugIntel("A9BFF20E") IME.prtDebugIntel("A9BFF20E")

View File

@ -28,7 +28,7 @@ import Cocoa
// MARK: - § Misc functions. // MARK: - § Misc functions.
@objc extension KeyHandler { extension KeyHandler {
func getCurrentMandarinParser() -> String { func getCurrentMandarinParser() -> String {
mgrPrefs.mandarinParserName + "_" mgrPrefs.mandarinParserName + "_"
} }

View File

@ -28,7 +28,7 @@ import Cocoa
// MARK: - § State managements. // MARK: - § State managements.
@objc extension KeyHandler { extension KeyHandler {
// MARK: - State Building // MARK: - State Building
func buildInputtingState() -> InputState.Inputting { func buildInputtingState() -> InputState.Inputting {
@ -44,7 +44,7 @@ import Cocoa
// i.e. we need to take UTF-16 into consideration, for which a surrogate pair takes 2 UniChars // i.e. we need to take UTF-16 into consideration, for which a surrogate pair takes 2 UniChars
// locations. These processes are inherited from the ObjC++ version of this class and might be // locations. These processes are inherited from the ObjC++ version of this class and might be
// unnecessary in Swift, but this deduction requires further experiments. // unnecessary in Swift, but this deduction requires further experiments.
for walkedNode in KeyHandlerSputnik.walkedNodes { for walkedNode in _walkedNodes {
if let theNode = walkedNode.node { if let theNode = walkedNode.node {
let strNodeValue = theNode.currentKeyValue().value let strNodeValue = theNode.currentKeyValue().value
composingBuffer += strNodeValue composingBuffer += strNodeValue
@ -87,7 +87,7 @@ import Cocoa
// The reading text is what the user is typing. // The reading text is what the user is typing.
let head = String((composingBuffer as NSString).substring(to: composedStringCursorIndex)) let head = String((composingBuffer as NSString).substring(to: composedStringCursorIndex))
let reading = getCompositionFromPhoneticReadingBuffer() let reading = Composer.getComposition()
let tail = String((composingBuffer as NSString).substring(from: composedStringCursorIndex)) let tail = String((composingBuffer as NSString).substring(from: composedStringCursorIndex))
let composedText = head + reading + tail let composedText = head + reading + tail
let cursorIndex = composedStringCursorIndex + reading.count let cursorIndex = composedStringCursorIndex + reading.count
@ -213,14 +213,14 @@ import Cocoa
return false return false
} }
if isPhoneticReadingBufferEmpty() { if Composer.isBufferEmpty() {
insertReadingToBuilderAtCursor(reading: customPunctuation) insertReadingToBuilderAtCursor(reading: customPunctuation)
let poppedText = popOverflowComposingTextAndWalk() let poppedText = popOverflowComposingTextAndWalk()
let inputting = buildInputtingState() let inputting = buildInputtingState()
inputting.poppedText = poppedText inputting.poppedText = poppedText
stateCallback(inputting) stateCallback(inputting)
if mgrPrefs.useSCPCTypingMode, isPhoneticReadingBufferEmpty() { if mgrPrefs.useSCPCTypingMode, Composer.isBufferEmpty() {
let candidateState = buildCandidate( let candidateState = buildCandidate(
state: inputting, state: inputting,
useVerticalMode: useVerticalMode useVerticalMode: useVerticalMode
@ -303,7 +303,7 @@ import Cocoa
return false return false
} }
if isPhoneticReadingBufferEmpty() { if Composer.isBufferEmpty() {
if getBuilderCursorIndex() >= 0 { if getBuilderCursorIndex() >= 0 {
deleteBuilderReadingInFrontOfCursor() deleteBuilderReadingInFrontOfCursor()
walk() walk()
@ -314,10 +314,10 @@ import Cocoa
return true return true
} }
} else { } else {
doBackSpaceToPhoneticReadingBuffer() Composer.doBackSpaceToBuffer()
} }
if isPhoneticReadingBufferEmpty(), getBuilderLength() == 0 { if Composer.isBufferEmpty(), getBuilderLength() == 0 {
stateCallback(InputState.EmptyIgnoringPreviousState()) stateCallback(InputState.EmptyIgnoringPreviousState())
} else { } else {
stateCallback(buildInputtingState()) stateCallback(buildInputtingState())
@ -336,7 +336,7 @@ import Cocoa
return false return false
} }
if isPhoneticReadingBufferEmpty() { if Composer.isBufferEmpty() {
if getBuilderCursorIndex() != getBuilderLength() { if getBuilderCursorIndex() != getBuilderLength() {
deleteBuilderReadingAfterCursor() deleteBuilderReadingAfterCursor()
walk() walk()
@ -371,7 +371,7 @@ import Cocoa
if !(state is InputState.Inputting) { if !(state is InputState.Inputting) {
return false return false
} }
if !isPhoneticReadingBufferEmpty() { if !Composer.isBufferEmpty() {
IME.prtDebugIntel("9B6F908D") IME.prtDebugIntel("9B6F908D")
errorCallback() errorCallback()
} }
@ -390,7 +390,7 @@ import Cocoa
return false return false
} }
if !isPhoneticReadingBufferEmpty() { if !Composer.isBufferEmpty() {
IME.prtDebugIntel("ABC44080") IME.prtDebugIntel("ABC44080")
errorCallback() errorCallback()
stateCallback(state) stateCallback(state)
@ -420,7 +420,7 @@ import Cocoa
return false return false
} }
if !isPhoneticReadingBufferEmpty() { if !Composer.isBufferEmpty() {
IME.prtDebugIntel("9B69908D") IME.prtDebugIntel("9B69908D")
errorCallback() errorCallback()
stateCallback(state) stateCallback(state)
@ -459,8 +459,8 @@ import Cocoa
stateCallback(InputState.EmptyIgnoringPreviousState()) stateCallback(InputState.EmptyIgnoringPreviousState())
} else { } else {
// If reading is not empty, we cancel the reading. // If reading is not empty, we cancel the reading.
if !isPhoneticReadingBufferEmpty() { if !Composer.isBufferEmpty() {
clearPhoneticReadingBuffer() Composer.clearBuffer()
if getBuilderLength() == 0 { if getBuilderLength() == 0 {
stateCallback(InputState.Empty()) stateCallback(InputState.Empty())
} else { } else {
@ -481,7 +481,7 @@ import Cocoa
) -> Bool { ) -> Bool {
if !(state is InputState.Inputting) { return false } if !(state is InputState.Inputting) { return false }
if !isPhoneticReadingBufferEmpty() { if !Composer.isBufferEmpty() {
IME.prtDebugIntel("B3BA5257") IME.prtDebugIntel("B3BA5257")
errorCallback() errorCallback()
stateCallback(state) stateCallback(state)
@ -532,7 +532,7 @@ import Cocoa
) -> Bool { ) -> Bool {
if !(state is InputState.Inputting) { return false } if !(state is InputState.Inputting) { return false }
if !isPhoneticReadingBufferEmpty() { if !Composer.isBufferEmpty() {
IME.prtDebugIntel("6ED95318") IME.prtDebugIntel("6ED95318")
errorCallback() errorCallback()
stateCallback(state) stateCallback(state)

View File

@ -93,7 +93,7 @@ class ctlInputMethod: IMKInputController {
currentClient = client currentClient = client
keyHandler.clear() keyHandler.clear()
keyHandler.ensurePhoneticParser() Composer.ensureParser()
if let bundleCheckID = (client as? IMKTextInput)?.bundleIdentifier() { if let bundleCheckID = (client as? IMKTextInput)?.bundleIdentifier() {
if bundleCheckID != Bundle.main.bundleIdentifier { if bundleCheckID != Bundle.main.bundleIdentifier {
// Override the keyboard layout to the basic one. // Override the keyboard layout to the basic one.

View File

@ -25,6 +25,7 @@
5B38F5A2281E2E49007D5F5D /* 0_Megrez.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A0D4F1615FC0EB100ABF4B3 /* 0_Megrez.swift */; }; 5B38F5A2281E2E49007D5F5D /* 0_Megrez.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A0D4F1615FC0EB100ABF4B3 /* 0_Megrez.swift */; };
5B38F5A3281E2E49007D5F5D /* 3_Span.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A0D4F1C15FC0EB100ABF4B3 /* 3_Span.swift */; }; 5B38F5A3281E2E49007D5F5D /* 3_Span.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A0D4F1C15FC0EB100ABF4B3 /* 3_Span.swift */; };
5B38F5A4281E2E49007D5F5D /* 5_LanguageModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A0D4F1915FC0EB100ABF4B3 /* 5_LanguageModel.swift */; }; 5B38F5A4281E2E49007D5F5D /* 5_LanguageModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A0D4F1915FC0EB100ABF4B3 /* 5_LanguageModel.swift */; };
5B407153281F94E6009C24CB /* Composer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5B407152281F94E6009C24CB /* Composer.mm */; };
5B40730C281672610023DFFF /* lmAssociates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B407309281672610023DFFF /* lmAssociates.swift */; }; 5B40730C281672610023DFFF /* lmAssociates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B407309281672610023DFFF /* lmAssociates.swift */; };
5B40730D281672610023DFFF /* lmReplacements.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B40730A281672610023DFFF /* lmReplacements.swift */; }; 5B40730D281672610023DFFF /* lmReplacements.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B40730A281672610023DFFF /* lmReplacements.swift */; };
5B5D28AC281EA1E900523D4D /* lmLite.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B5D28AB281EA1E800523D4D /* lmLite.swift */; }; 5B5D28AC281EA1E900523D4D /* lmLite.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B5D28AB281EA1E800523D4D /* lmLite.swift */; };
@ -83,9 +84,8 @@
5BBBB77627AED70B0023B93A /* MenuIcon-TCVIM.png in Resources */ = {isa = PBXBuildFile; fileRef = 5BBBB77227AED70B0023B93A /* MenuIcon-TCVIM.png */; }; 5BBBB77627AED70B0023B93A /* MenuIcon-TCVIM.png in Resources */ = {isa = PBXBuildFile; fileRef = 5BBBB77227AED70B0023B93A /* MenuIcon-TCVIM.png */; };
5BBBB77A27AEDC690023B93A /* clsSFX.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BBBB77927AEDC690023B93A /* clsSFX.swift */; }; 5BBBB77A27AEDC690023B93A /* clsSFX.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BBBB77927AEDC690023B93A /* clsSFX.swift */; };
5BC2652227E04B7E00700291 /* uninstall.sh in Resources */ = {isa = PBXBuildFile; fileRef = 5BC2652127E04B7B00700291 /* uninstall.sh */; }; 5BC2652227E04B7E00700291 /* uninstall.sh in Resources */ = {isa = PBXBuildFile; fileRef = 5BC2652127E04B7B00700291 /* uninstall.sh */; };
5BC4F6382819FF4500A2514A /* KeyHandlerSputnik.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC4F6372819FF4500A2514A /* KeyHandlerSputnik.swift */; };
5BD0113B28180D6100609769 /* LMInstantiator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BD0113A28180D6100609769 /* LMInstantiator.swift */; }; 5BD0113B28180D6100609769 /* LMInstantiator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BD0113A28180D6100609769 /* LMInstantiator.swift */; };
5BD0113D2818543900609769 /* KeyHandler_Kernel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BD0113C2818543900609769 /* KeyHandler_Kernel.swift */; }; 5BD0113D2818543900609769 /* KeyHandler_Core.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BD0113C2818543900609769 /* KeyHandler_Core.swift */; };
5BD05B8127B22F3C004C4F1D /* char-kanji-cns.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5BD05B8027B22F3C004C4F1D /* char-kanji-cns.txt */; }; 5BD05B8127B22F3C004C4F1D /* char-kanji-cns.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5BD05B8027B22F3C004C4F1D /* char-kanji-cns.txt */; };
5BD05BCA27B2A43D004C4F1D /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6A2E40F5253A69DA00D1AE1D /* Images.xcassets */; }; 5BD05BCA27B2A43D004C4F1D /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6A2E40F5253A69DA00D1AE1D /* Images.xcassets */; };
5BD05C5D27B2BBA9004C4F1D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5BD05C5B27B2BBA9004C4F1D /* Main.storyboard */; }; 5BD05C5D27B2BBA9004C4F1D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5BD05C5B27B2BBA9004C4F1D /* Main.storyboard */; };
@ -118,7 +118,7 @@
D4A13D5A27A59F0B003BE359 /* ctlInputMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4A13D5927A59D5C003BE359 /* ctlInputMethod.swift */; }; D4A13D5A27A59F0B003BE359 /* ctlInputMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4A13D5927A59D5C003BE359 /* ctlInputMethod.swift */; };
D4E33D8A27A838CF006DB1CF /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = D4E33D8827A838CF006DB1CF /* Localizable.strings */; }; D4E33D8A27A838CF006DB1CF /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = D4E33D8827A838CF006DB1CF /* Localizable.strings */; };
D4E33D8F27A838F0006DB1CF /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = D4E33D8D27A838F0006DB1CF /* InfoPlist.strings */; }; D4E33D8F27A838F0006DB1CF /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = D4E33D8D27A838F0006DB1CF /* InfoPlist.strings */; };
D4E569DC27A34D0E00AC2CEF /* KeyHandler.mm in Sources */ = {isa = PBXBuildFile; fileRef = D4E569DB27A34CC100AC2CEF /* KeyHandler.mm */; }; D4E569DC27A34D0E00AC2CEF /* CTools.m in Sources */ = {isa = PBXBuildFile; fileRef = D4E569DB27A34CC100AC2CEF /* CTools.m */; };
D4F0BBDF279AF1AF0071253C /* ArchiveUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4F0BBDE279AF1AF0071253C /* ArchiveUtil.swift */; }; D4F0BBDF279AF1AF0071253C /* ArchiveUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4F0BBDE279AF1AF0071253C /* ArchiveUtil.swift */; };
D4F0BBE1279AF8B30071253C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4F0BBE0279AF8B30071253C /* AppDelegate.swift */; }; D4F0BBE1279AF8B30071253C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4F0BBE0279AF8B30071253C /* AppDelegate.swift */; };
D4F0BBE4279B08900071253C /* Chronosphere.m in Sources */ = {isa = PBXBuildFile; fileRef = D4F0BBE3279B08900071253C /* Chronosphere.m */; }; D4F0BBE4279B08900071253C /* Chronosphere.m in Sources */ = {isa = PBXBuildFile; fileRef = D4F0BBE3279B08900071253C /* Chronosphere.m */; };
@ -201,6 +201,8 @@
5B2DB17127AF8771006D874E /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; name = Makefile; path = Data/Makefile; 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>"; }; 5B30F11227BA568800484E24 /* vChewingKeyLayout.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = vChewingKeyLayout.bundle; sourceTree = "<group>"; };
5B3133BE280B229700A4A505 /* KeyHandler_States.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = KeyHandler_States.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 1; }; 5B3133BE280B229700A4A505 /* KeyHandler_States.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = KeyHandler_States.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 1; };
5B407151281F94E6009C24CB /* Composer.hh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Composer.hh; sourceTree = "<group>"; };
5B407152281F94E6009C24CB /* Composer.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = Composer.mm; sourceTree = "<group>"; };
5B407309281672610023DFFF /* lmAssociates.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; lineEnding = 0; path = lmAssociates.swift; sourceTree = "<group>"; usesTabs = 1; }; 5B407309281672610023DFFF /* lmAssociates.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; lineEnding = 0; path = lmAssociates.swift; sourceTree = "<group>"; usesTabs = 1; };
5B40730A281672610023DFFF /* lmReplacements.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; lineEnding = 0; path = lmReplacements.swift; sourceTree = "<group>"; usesTabs = 1; }; 5B40730A281672610023DFFF /* lmReplacements.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; lineEnding = 0; path = lmReplacements.swift; sourceTree = "<group>"; usesTabs = 1; };
5B5D28AB281EA1E800523D4D /* lmLite.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = lmLite.swift; sourceTree = "<group>"; }; 5B5D28AB281EA1E800523D4D /* lmLite.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = lmLite.swift; sourceTree = "<group>"; };
@ -263,9 +265,8 @@
5BC0AAC927F58472002D33E9 /* pkgPreInstall.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = pkgPreInstall.sh; sourceTree = "<group>"; }; 5BC0AAC927F58472002D33E9 /* pkgPreInstall.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = pkgPreInstall.sh; sourceTree = "<group>"; };
5BC0AACA27F58472002D33E9 /* pkgPostInstall.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = pkgPostInstall.sh; sourceTree = "<group>"; }; 5BC0AACA27F58472002D33E9 /* pkgPostInstall.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = pkgPostInstall.sh; sourceTree = "<group>"; };
5BC2652127E04B7B00700291 /* uninstall.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; lineEnding = 0; path = uninstall.sh; sourceTree = "<group>"; }; 5BC2652127E04B7B00700291 /* uninstall.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; lineEnding = 0; path = uninstall.sh; sourceTree = "<group>"; };
5BC4F6372819FF4500A2514A /* KeyHandlerSputnik.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; lineEnding = 0; path = KeyHandlerSputnik.swift; sourceTree = "<group>"; usesTabs = 1; };
5BD0113A28180D6100609769 /* LMInstantiator.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; lineEnding = 0; path = LMInstantiator.swift; sourceTree = "<group>"; usesTabs = 1; }; 5BD0113A28180D6100609769 /* LMInstantiator.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; lineEnding = 0; path = LMInstantiator.swift; sourceTree = "<group>"; usesTabs = 1; };
5BD0113C2818543900609769 /* KeyHandler_Kernel.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; lineEnding = 0; path = KeyHandler_Kernel.swift; sourceTree = "<group>"; usesTabs = 1; }; 5BD0113C2818543900609769 /* KeyHandler_Core.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; lineEnding = 0; path = KeyHandler_Core.swift; sourceTree = "<group>"; usesTabs = 1; };
5BD05B8027B22F3C004C4F1D /* char-kanji-cns.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "char-kanji-cns.txt"; path = "Data/components/common/char-kanji-cns.txt"; sourceTree = "<group>"; }; 5BD05B8027B22F3C004C4F1D /* char-kanji-cns.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "char-kanji-cns.txt"; path = "Data/components/common/char-kanji-cns.txt"; sourceTree = "<group>"; };
5BD05BB827B2A429004C4F1D /* vChewingPhraseEditor.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = vChewingPhraseEditor.app; sourceTree = BUILT_PRODUCTS_DIR; }; 5BD05BB827B2A429004C4F1D /* vChewingPhraseEditor.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = vChewingPhraseEditor.app; sourceTree = BUILT_PRODUCTS_DIR; };
5BD05BC627B2A42A004C4F1D /* vChewingPhraseEditor.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = vChewingPhraseEditor.entitlements; sourceTree = "<group>"; }; 5BD05BC627B2A42A004C4F1D /* vChewingPhraseEditor.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = vChewingPhraseEditor.entitlements; sourceTree = "<group>"; };
@ -334,8 +335,8 @@
D4A13D5927A59D5C003BE359 /* ctlInputMethod.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = ctlInputMethod.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 1; }; D4A13D5927A59D5C003BE359 /* ctlInputMethod.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = ctlInputMethod.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 1; };
D4E33D8927A838CF006DB1CF /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Localizable.strings; sourceTree = "<group>"; }; 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>"; }; D4E33D8E27A838F0006DB1CF /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/InfoPlist.strings; sourceTree = "<group>"; };
D4E569DA27A34CC100AC2CEF /* KeyHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = KeyHandler.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; }; D4E569DA27A34CC100AC2CEF /* CTools.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = CTools.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
D4E569DB27A34CC100AC2CEF /* KeyHandler.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = KeyHandler.mm; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; }; D4E569DB27A34CC100AC2CEF /* CTools.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = CTools.m; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
D4F0BBDE279AF1AF0071253C /* ArchiveUtil.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = ArchiveUtil.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 1; }; D4F0BBDE279AF1AF0071253C /* ArchiveUtil.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = ArchiveUtil.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 1; };
D4F0BBE0279AF8B30071253C /* AppDelegate.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = AppDelegate.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 1; }; D4F0BBE0279AF8B30071253C /* AppDelegate.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = AppDelegate.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 1; };
D4F0BBE2279B08900071253C /* Chronosphere.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = Chronosphere.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; }; D4F0BBE2279B08900071253C /* Chronosphere.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = Chronosphere.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
@ -419,6 +420,8 @@
children = ( children = (
6A0D4F2015FC0EB100ABF4B3 /* Mandarin.cpp */, 6A0D4F2015FC0EB100ABF4B3 /* Mandarin.cpp */,
6A0D4F2115FC0EB100ABF4B3 /* Mandarin.h */, 6A0D4F2115FC0EB100ABF4B3 /* Mandarin.h */,
5B407151281F94E6009C24CB /* Composer.hh */,
5B407152281F94E6009C24CB /* Composer.mm */,
); );
path = OVMandarin; path = OVMandarin;
sourceTree = "<group>"; sourceTree = "<group>";
@ -435,16 +438,15 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
5B11328827B94CFB00E58451 /* AppleKeyboardConverter.swift */, 5B11328827B94CFB00E58451 /* AppleKeyboardConverter.swift */,
D4E569DA27A34CC100AC2CEF /* CTools.h */,
D4E569DB27A34CC100AC2CEF /* CTools.m */,
D456576D279E4F7B00DF6BC9 /* InputHandler.swift */, D456576D279E4F7B00DF6BC9 /* InputHandler.swift */,
D461B791279DAC010070E734 /* InputState.swift */, D461B791279DAC010070E734 /* InputState.swift */,
5BD0113C2818543900609769 /* KeyHandler_Core.swift */,
5B782EC3280C243C007276DE /* KeyHandler_HandleCandidate.swift */, 5B782EC3280C243C007276DE /* KeyHandler_HandleCandidate.swift */,
5B7F225C2808501000DDD3CB /* KeyHandler_HandleInput.swift */, 5B7F225C2808501000DDD3CB /* KeyHandler_HandleInput.swift */,
5BD0113C2818543900609769 /* KeyHandler_Kernel.swift */,
5B61B0C9280BEFD4002E3CFA /* KeyHandler_Misc.swift */, 5B61B0C9280BEFD4002E3CFA /* KeyHandler_Misc.swift */,
5B3133BE280B229700A4A505 /* KeyHandler_States.swift */, 5B3133BE280B229700A4A505 /* KeyHandler_States.swift */,
5BC4F6372819FF4500A2514A /* KeyHandlerSputnik.swift */,
D4E569DA27A34CC100AC2CEF /* KeyHandler.h */,
D4E569DB27A34CC100AC2CEF /* KeyHandler.mm */,
5B62A33727AE79CD00A19448 /* NSStringUtils.swift */, 5B62A33727AE79CD00A19448 /* NSStringUtils.swift */,
5BF8423027BAA942008E7E4C /* vChewingKanjiConverter.swift */, 5BF8423027BAA942008E7E4C /* vChewingKanjiConverter.swift */,
); );
@ -1088,9 +1090,8 @@
D47B92C027972AD100458394 /* main.swift in Sources */, D47B92C027972AD100458394 /* main.swift in Sources */,
D4A13D5A27A59F0B003BE359 /* ctlInputMethod.swift in Sources */, D4A13D5A27A59F0B003BE359 /* ctlInputMethod.swift in Sources */,
5BA9FD4827FEF3C9002DE248 /* PreferencesWindowController.swift in Sources */, 5BA9FD4827FEF3C9002DE248 /* PreferencesWindowController.swift in Sources */,
5BC4F6382819FF4500A2514A /* KeyHandlerSputnik.swift in Sources */,
5BD0113B28180D6100609769 /* LMInstantiator.swift in Sources */, 5BD0113B28180D6100609769 /* LMInstantiator.swift in Sources */,
D4E569DC27A34D0E00AC2CEF /* KeyHandler.mm in Sources */, D4E569DC27A34D0E00AC2CEF /* CTools.m in Sources */,
5BA9FD4627FEF3C9002DE248 /* Container.swift in Sources */, 5BA9FD4627FEF3C9002DE248 /* Container.swift in Sources */,
D47F7DD0278C0897002F9DD7 /* ctlNonModalAlertWindow.swift in Sources */, D47F7DD0278C0897002F9DD7 /* ctlNonModalAlertWindow.swift in Sources */,
5B38F5A2281E2E49007D5F5D /* 0_Megrez.swift in Sources */, 5B38F5A2281E2E49007D5F5D /* 0_Megrez.swift in Sources */,
@ -1101,7 +1102,7 @@
5BA9FD4327FEF3C8002DE248 /* Preferences.swift in Sources */, 5BA9FD4327FEF3C8002DE248 /* Preferences.swift in Sources */,
5BA9FD4427FEF3C8002DE248 /* SegmentedControlStyleViewController.swift in Sources */, 5BA9FD4427FEF3C8002DE248 /* SegmentedControlStyleViewController.swift in Sources */,
D47F7DCE278BFB57002F9DD7 /* ctlPrefWindow.swift in Sources */, D47F7DCE278BFB57002F9DD7 /* ctlPrefWindow.swift in Sources */,
5BD0113D2818543900609769 /* KeyHandler_Kernel.swift in Sources */, 5BD0113D2818543900609769 /* KeyHandler_Core.swift in Sources */,
5BA9FD4227FEF3C8002DE248 /* PreferencePane.swift in Sources */, 5BA9FD4227FEF3C8002DE248 /* PreferencePane.swift in Sources */,
5BA0DF312817857D009E73BB /* lmUserOverride.swift in Sources */, 5BA0DF312817857D009E73BB /* lmUserOverride.swift in Sources */,
5BA9FD8B28006B41002DE248 /* VDKComboBox.swift in Sources */, 5BA9FD8B28006B41002DE248 /* VDKComboBox.swift in Sources */,
@ -1117,6 +1118,7 @@
5B62A33827AE79CD00A19448 /* NSStringUtils.swift in Sources */, 5B62A33827AE79CD00A19448 /* NSStringUtils.swift in Sources */,
5BA9FD0F27FEDB6B002DE248 /* suiPrefPaneGeneral.swift in Sources */, 5BA9FD0F27FEDB6B002DE248 /* suiPrefPaneGeneral.swift in Sources */,
5BA9FD4927FEF3C9002DE248 /* Section.swift in Sources */, 5BA9FD4927FEF3C9002DE248 /* Section.swift in Sources */,
5B407153281F94E6009C24CB /* Composer.mm in Sources */,
5BA9FD3E27FEF3C8002DE248 /* Utilities.swift in Sources */, 5BA9FD3E27FEF3C8002DE248 /* Utilities.swift in Sources */,
5BA9FD1127FEDB6B002DE248 /* ctlPrefUI.swift in Sources */, 5BA9FD1127FEDB6B002DE248 /* ctlPrefUI.swift in Sources */,
5B38F59C281E2E49007D5F5D /* 2_Grid.swift in Sources */, 5B38F59C281E2E49007D5F5D /* 2_Grid.swift in Sources */,