KeyHandler // Swiftify: day 5.

This commit is contained in:
ShikiSuen 2022-04-18 00:35:17 +08:00
parent 6d4894af54
commit 01ae065d9b
9 changed files with 128 additions and 94 deletions

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>
@ -51,7 +59,6 @@ extern InputMode imeModeNULL;
- (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;
@ -70,8 +77,10 @@ extern InputMode imeModeNULL;
- (NSArray<NSString *> *)getCandidatesArray;
- (NSInteger)getBuilderCursorIndex;
- (NSInteger)getBuilderLength;
- (NSString *)_currentMandarinParser;
- (NSInteger)getPackagedCursorIndex;
- (NSString *)getComposedText;
- (NSString *)getCompositionFromPhoneticReadingBuffer;
- (NSString *)getStrLocationResult:(BOOL)isAfter NS_SWIFT_NAME(getStrLocationResult(isAfter:));
- (NSString *)getSyllableCompositionFromPhoneticReadingBuffer;
- (void)clearPhoneticReadingBuffer;
- (void)combinePhoneticReadingBufferKey:(UniChar)charCode;
@ -82,6 +91,7 @@ extern InputMode imeModeNULL;
- (void)doBackSpaceToPhoneticReadingBuffer;
- (void)ensurePhoneticParser;
- (void)insertReadingToBuilderAtCursor:(NSString *)reading;
- (void)packageBufferStateMaterials;
- (void)removeBuilderAndReset:(BOOL)shouldReset;
- (void)setBuilderCursorIndex:(NSInteger)value;
- (void)setInputModesToLM:(BOOL)isCHS;

View File

@ -44,6 +44,12 @@ typedef Mandarin::BopomofoReadingBuffer PhoneticBuffer;
static const double kEpsilon = 0.000001;
NSString *packagedComposedText;
NSInteger packagedCursorIndex;
NSString *packagedResultOfBefore;
NSString *packagedResultOfAfter;
// NON-SWIFTIFIABLE
static double FindHighestScore(const std::vector<Gramambular::NodeAnchor> &nodes, double epsilon)
{
double highestScore = 0.0;
@ -56,6 +62,7 @@ static double FindHighestScore(const std::vector<Gramambular::NodeAnchor> &nodes
return highestScore + epsilon;
}
// NON-SWIFTIFIABLE
class NodeAnchorDescendingSorter
{
public:
@ -71,6 +78,7 @@ class NodeAnchorDescendingSorter
static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
#endif
// NON-SWIFTIFIABLE
@implementation KeyHandler
{
// the reading buffer that takes user input
@ -91,19 +99,23 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
NSString *_inputMode;
}
//@synthesize inputMode = _inputMode;
@synthesize delegate = _delegate;
// NON-SWIFTIFIABLE DUE TO VARIABLE AVAILABLE ACCESSIBILITY RANGE.
// VARIABLE: "_inputMode"
- (NSString *)inputMode
{
return _inputMode;
}
// NON-SWIFTIFIABLE
- (BOOL)isBuilderEmpty
{
return (_builder->grid().width() == 0);
}
// NON-SWIFTIFIABLE DUE TO VARIABLE AVAILABLE ACCESSIBILITY RANGE.
// VARIABLE: "_inputMode"
- (void)setInputMode:(NSString *)value
{
// 下面這句的「isKindOfClass」是做類型檢查
@ -131,6 +143,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
_inputMode = ctlInputMethod.currentInputMode;
}
// NON-SWIFTIFIABLE: Required by an ObjC(pp)-based class.
- (void)dealloc
{ // clean up everything
if (_bpmfReadingBuffer)
@ -139,6 +152,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
[self removeBuilderAndReset:NO];
}
// NON-SWIFTIFIABLE: Not placeable in swift extensions.
- (instancetype)init
{
self = [super init];
@ -198,21 +212,19 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
_walkedNodes.clear();
}
- (NSString *)_currentMandarinParser
{
return [mgrPrefs.mandarinParserName stringByAppendingString:@"_"];
}
#pragma mark - States Building
// NON-SWIFTIFIABLE
- (InputStateInputting *)buildInputtingState
- (void)packageBufferStateMaterials
{
// We gather the data through this function, package it,
// and sent it to our Swift extension to build the InputState.Inputting there.
// Otherwise, ObjC++ always bugs for "expecting a type".
// "updating the composing buffer" means to request the client to "refresh" the text input buffer
// with our "composing text"
NSMutableString *composingBuffer = [[NSMutableString alloc] init];
NSInteger composedStringCursorIndex = 0;
NSString *tooltip = @"";
// we must do some Unicode codepoint counting to find the actual cursor location for the client
// i.e. we need to take UTF-16 into consideration, for which a surrogate pair takes 2 UniChars
@ -221,6 +233,9 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
size_t readingCursorIndex = 0;
size_t builderCursorIndex = [self getBuilderCursorIndex];
NSString *resultOfBefore = @"";
NSString *resultOfAfter = @"";
for (std::vector<Gramambular::NodeAnchor>::iterator wi = _walkedNodes.begin(), we = _walkedNodes.end(); wi != we;
++wi)
{
@ -267,30 +282,20 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
}
if (builderCursorIndex == 0)
{
tooltip = [NSString
stringWithFormat:NSLocalizedString(@"Cursor is before \"%@\".", @""),
[NSString stringWithUTF8String:_builder->readings()[builderCursorIndex]
.c_str()]];
resultOfBefore =
[NSString stringWithUTF8String:_builder->readings()[builderCursorIndex].c_str()];
}
else if (builderCursorIndex >= _builder->readings().size())
{
tooltip = [NSString
stringWithFormat:NSLocalizedString(@"Cursor is after \"%@\".", @""),
[NSString
stringWithUTF8String:_builder
->readings()[_builder->readings().size() -
1]
.c_str()]];
resultOfAfter = [NSString
stringWithUTF8String:_builder->readings()[_builder->readings().size() - 1].c_str()];
}
else
{
tooltip = [NSString
stringWithFormat:NSLocalizedString(@"Cursor is between \"%@\" and \"%@\".", @""),
[NSString
stringWithUTF8String:_builder->readings()[builderCursorIndex - 1]
.c_str()],
[NSString stringWithUTF8String:_builder->readings()[builderCursorIndex]
.c_str()]];
resultOfBefore =
[NSString stringWithUTF8String:_builder->readings()[builderCursorIndex].c_str()];
resultOfAfter =
[NSString stringWithUTF8String:_builder->readings()[builderCursorIndex - 1].c_str()];
}
}
}
@ -307,10 +312,31 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
NSString *composedText = [head stringByAppendingString:[reading stringByAppendingString:tail]];
NSInteger cursorIndex = composedStringCursorIndex + [reading length];
InputStateInputting *newState = [[InputStateInputting alloc] initWithComposingBuffer:composedText
cursorIndex:cursorIndex];
newState.tooltip = tooltip;
return newState;
packagedComposedText = composedText;
packagedCursorIndex = cursorIndex;
packagedResultOfBefore = resultOfBefore;
packagedResultOfAfter = resultOfAfter;
}
// NON-SWIFTIFIABLE DUE TO VARIABLE AVAILABLE ACCESSIBILITY RANGE.
- (NSString *)getStrLocationResult:(BOOL)isAfter
{
if (isAfter)
return packagedResultOfAfter;
else
return packagedResultOfBefore;
}
// NON-SWIFTIFIABLE DUE TO VARIABLE AVAILABLE ACCESSIBILITY RANGE.
- (NSString *)getComposedText
{
return packagedComposedText;
}
// NON-SWIFTIFIABLE DUE TO VARIABLE AVAILABLE ACCESSIBILITY RANGE.
- (NSInteger)getPackagedCursorIndex
{
return packagedCursorIndex;
}
// NON-SWIFTIFIABLE

View File

@ -1,33 +0,0 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// Refactored from the ObjCpp-version of this class by:
// (c) 2011 and onwards The OpenVanilla Project (MIT License).
/*
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
1. The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
2. No trademark license is granted to use the trade names, trademarks, service
marks, or product names of Contributor, except as required to fulfill notice
requirements above.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import Cocoa
// MARK: - § Build Input State.
@objc extension KeyHandler {
}

View File

@ -59,7 +59,7 @@ import Cocoa
let empty = InputState.EmptyIgnoringPreviousState()
stateCallback(empty)
} else {
let inputting = buildInputtingState() as! InputState.Inputting
let inputting = buildInputtingState()
stateCallback(inputting)
}
return true
@ -286,7 +286,7 @@ import Cocoa
punctuationNamePrefix = "_punctuation_"
}
let parser: String! = _currentMandarinParser()
let parser = getCurrentMandarinParser()
let arrCustomPunctuations: [String] = [
punctuationNamePrefix, parser, String(format: "%c", CChar(charCode)),
@ -315,7 +315,8 @@ import Cocoa
clear()
let empty = InputState.EmptyIgnoringPreviousState()
stateCallback(empty)
return handle(input: input, state: empty, stateCallback: stateCallback, errorCallback: errorCallback)
return handle(
input: input, state: empty, stateCallback: stateCallback, errorCallback: errorCallback)
}
return true
}

View File

@ -146,7 +146,7 @@ import Cocoa
// update the composing buffer.
composeReading = checkWhetherToneMarkerConfirmsPhoneticReadingBuffer()
if !composeReading {
let inputting = buildInputtingState() as! InputState.Inputting
let inputting = buildInputtingState()
stateCallback(inputting)
return true
}
@ -163,7 +163,7 @@ import Cocoa
if !ifLangModelHasUnigrams(forKey: reading) {
IME.prtDebugIntel("B49C0979")
errorCallback()
let inputting = buildInputtingState() as! InputState.Inputting
let inputting = buildInputtingState()
stateCallback(inputting)
return true
}
@ -180,7 +180,7 @@ import Cocoa
// ... then update the text.
clearPhoneticReadingBuffer()
let inputting = buildInputtingState() as! InputState.Inputting
let inputting = buildInputtingState()
inputting.poppedText = poppedText
stateCallback(inputting)
@ -238,7 +238,7 @@ import Cocoa
} else if ifLangModelHasUnigrams(forKey: " ") {
insertReadingToBuilder(atCursor: " ")
let poppedText = _popOverflowComposingTextAndWalk()
let inputting = buildInputtingState() as! InputState.Inputting
let inputting = buildInputtingState()
inputting.poppedText = poppedText
stateCallback(inputting)
}
@ -309,8 +309,8 @@ import Cocoa
// MARK: Enter
if input.isEnter {
return (input.isCommandHold)
? _handleCommandEnterWithState(state, stateCallback: stateCallback, errorCallback: errorCallback)
return (input.isCommandHold && input.isControlHold)
? _handleCtrlCommandEnterWithState(state, stateCallback: stateCallback, errorCallback: errorCallback)
: _handleEnterWithState(state, stateCallback: stateCallback, errorCallback: errorCallback)
}
@ -323,7 +323,7 @@ import Cocoa
if isPhoneticReadingBufferEmpty() {
insertReadingToBuilder(atCursor: "_punctuation_list")
let poppedText: String! = _popOverflowComposingTextAndWalk()
let inputting = buildInputtingState() as! InputState.Inputting
let inputting = buildInputtingState()
inputting.poppedText = poppedText
stateCallback(inputting)
let choosingCandidate =
@ -363,7 +363,7 @@ import Cocoa
punctuationNamePrefix = "_punctuation_"
}
let parser: String! = _currentMandarinParser()
let parser = getCurrentMandarinParser()
let arrCustomPunctuations: [String] = [
punctuationNamePrefix, parser, String(format: "%c", CChar(charCode)),
]

View File

@ -28,6 +28,11 @@ 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.

View File

@ -29,6 +29,38 @@ 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,
@ -53,7 +85,7 @@ import Cocoa
) -> Bool {
if input.isESC {
let inputting = buildInputtingState() as! InputState.Inputting
let inputting = buildInputtingState()
stateCallback(inputting)
return true
}
@ -68,7 +100,7 @@ import Cocoa
}
}
let inputting = buildInputtingState() as! InputState.Inputting
let inputting = buildInputtingState()
stateCallback(inputting)
return true
}
@ -143,7 +175,7 @@ import Cocoa
if isPhoneticReadingBufferEmpty() {
insertReadingToBuilder(atCursor: customPunctuation)
let poppedText = _popOverflowComposingTextAndWalk()
let inputting = buildInputtingState() as! InputState.Inputting
let inputting = buildInputtingState()
inputting.poppedText = poppedText
stateCallback(inputting)
@ -198,7 +230,7 @@ import Cocoa
}
// MARK: - CMD+Enter
func _handleCommandEnterWithState(
func _handleCtrlCommandEnterWithState(
_ state: InputState,
stateCallback: @escaping (InputState) -> Void,
errorCallback: @escaping () -> Void
@ -250,7 +282,7 @@ import Cocoa
let empty = InputState.EmptyIgnoringPreviousState()
stateCallback(empty)
} else {
let inputting = buildInputtingState() as! InputState.Inputting
let inputting = buildInputtingState()
stateCallback(inputting)
}
return true
@ -270,7 +302,7 @@ import Cocoa
if getBuilderCursorIndex() != getBuilderLength() {
deleteBuilderReadingAfterCursor()
_walk()
let inputting = buildInputtingState() as! InputState.Inputting
let inputting = buildInputtingState()
if inputting.composingBuffer.count == 0 {
let empty = InputState.EmptyIgnoringPreviousState()
stateCallback(empty)
@ -327,7 +359,7 @@ import Cocoa
if getBuilderCursorIndex() != 0 {
setBuilderCursorIndex(0)
let inputting = buildInputtingState() as! InputState.Inputting
let inputting = buildInputtingState()
stateCallback(inputting)
} else {
IME.prtDebugIntel("66D97F90")
@ -357,7 +389,7 @@ import Cocoa
if getBuilderCursorIndex() != getBuilderLength() {
setBuilderCursorIndex(getBuilderLength())
let inputting = buildInputtingState() as! InputState.Inputting
let inputting = buildInputtingState()
stateCallback(inputting)
} else {
IME.prtDebugIntel("9B69908E")
@ -440,7 +472,7 @@ import Cocoa
} else {
if getBuilderCursorIndex() < getBuilderLength() {
setBuilderCursorIndex(getBuilderCursorIndex() + 1)
let inputting = buildInputtingState() as! InputState.Inputting
let inputting = buildInputtingState()
stateCallback(inputting)
} else {
IME.prtDebugIntel("A96AAD58")
@ -490,7 +522,7 @@ import Cocoa
} else {
if getBuilderCursorIndex() > 0 {
setBuilderCursorIndex(getBuilderCursorIndex() - 1)
let inputting = buildInputtingState() as! InputState.Inputting
let inputting = buildInputtingState()
stateCallback(inputting)
} else {
IME.prtDebugIntel("7045E6F3")
@ -500,5 +532,4 @@ import Cocoa
}
return true
}
}

View File

@ -601,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

@ -32,7 +32,6 @@
5B707CEC27D9F4870099EF99 /* OpenCC in Frameworks */ = {isa = PBXBuildFile; productRef = 5B707CEB27D9F4870099EF99 /* OpenCC */; };
5B73FB5E27B2BE1300E9BF49 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5B73FB6027B2BE1300E9BF49 /* InfoPlist.strings */; };
5B782EC4280C243C007276DE /* KeyHandler_HandleCandidate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B782EC3280C243C007276DE /* KeyHandler_HandleCandidate.swift */; };
5B782EC6280C2F4B007276DE /* KeyHandler_BuildInput.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B782EC5280C2F4B007276DE /* KeyHandler_BuildInput.swift */; };
5B7BC4B027AFFBE800F66C24 /* frmPrefWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5B7BC4AE27AFFBE800F66C24 /* frmPrefWindow.xib */; };
5B7F225D2808501000DDD3CB /* KeyHandler_HandleInput.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B7F225C2808501000DDD3CB /* KeyHandler_HandleInput.swift */; };
5BA9FD0F27FEDB6B002DE248 /* suiPrefPaneGeneral.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA9FD0A27FEDB6B002DE248 /* suiPrefPaneGeneral.swift */; };
@ -214,7 +213,6 @@
5B73FB5427B2BD6900E9BF49 /* PhraseEditor-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "PhraseEditor-Info.plist"; path = "UserPhraseEditor/PhraseEditor-Info.plist"; sourceTree = SOURCE_ROOT; };
5B73FB5F27B2BE1300E9BF49 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
5B782EC3280C243C007276DE /* KeyHandler_HandleCandidate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyHandler_HandleCandidate.swift; sourceTree = "<group>"; };
5B782EC5280C2F4B007276DE /* KeyHandler_BuildInput.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyHandler_BuildInput.swift; sourceTree = "<group>"; };
5B7BC4AF27AFFBE800F66C24 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/frmPrefWindow.xib; sourceTree = "<group>"; };
5B7BC4B227AFFC0B00F66C24 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/frmPrefWindow.strings; sourceTree = "<group>"; };
5B7F225C2808501000DDD3CB /* KeyHandler_HandleInput.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyHandler_HandleInput.swift; sourceTree = "<group>"; };
@ -433,7 +431,6 @@
D461B791279DAC010070E734 /* InputState.swift */,
D4E569DA27A34CC100AC2CEF /* KeyHandler.h */,
D4E569DB27A34CC100AC2CEF /* KeyHandler.mm */,
5B782EC5280C2F4B007276DE /* KeyHandler_BuildInput.swift */,
5B7F225C2808501000DDD3CB /* KeyHandler_HandleInput.swift */,
5B782EC3280C243C007276DE /* KeyHandler_HandleCandidate.swift */,
5B61B0C9280BEFD4002E3CFA /* KeyHandler_Misc.swift */,
@ -1091,7 +1088,6 @@
5B62A32F27AE78B000A19448 /* CoreLM.mm in Sources */,
5BE78BE027B38804005EA1BE /* LMConsolidator.mm in Sources */,
D456576E279E4F7B00DF6BC9 /* KeyParser.swift in Sources */,
5B782EC6280C2F4B007276DE /* KeyHandler_BuildInput.swift in Sources */,
5BA9FD1027FEDB6B002DE248 /* suiPrefPaneKeyboard.swift in Sources */,
5B3133BF280B229700A4A505 /* KeyHandler_States.swift in Sources */,
5BA9FD4327FEF3C8002DE248 /* Preferences.swift in Sources */,