Zonble: IMC // Refactoring IMController.
- This commit already has vChewing Feature Customizations Applied.
This commit is contained in:
parent
0b996632ca
commit
e7dcbe7e91
|
@ -0,0 +1,219 @@
|
||||||
|
/*
|
||||||
|
* InputState.cpp
|
||||||
|
*
|
||||||
|
* Copyright 2021-2022 vChewing Project (3-Clause BSD License).
|
||||||
|
* Derived from 2011-2022 OpenVanilla Project (MIT License).
|
||||||
|
* Some rights reserved. See "LICENSE.TXT" for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Cocoa
|
||||||
|
|
||||||
|
/// Represents the states for the input method controller.
|
||||||
|
///
|
||||||
|
/// An input method is actually a finite state machine. It receives the inputs
|
||||||
|
/// from hardware like keyboard and mouse, changes its state, updates user
|
||||||
|
/// interface by the state, and finally produces the text output and then them
|
||||||
|
/// to the client apps. It should be a one-way data flow, and the user interface
|
||||||
|
/// and text output should follow unconditionally one single data source.
|
||||||
|
///
|
||||||
|
/// The InputState class is for representing what the input controller is doing,
|
||||||
|
/// and the place to store the variables that could be used. For example, the
|
||||||
|
/// array for the candidate list is useful only when the user is choosing a
|
||||||
|
/// candidate, and the array should not exist when the input controller is in
|
||||||
|
/// another state.
|
||||||
|
///
|
||||||
|
/// They are immutable objects. When the state changes, the controller should
|
||||||
|
/// create a new state object to replace the current state instead of modifying
|
||||||
|
/// the existing one.
|
||||||
|
///
|
||||||
|
/// vChewing's input controller has following possible states:
|
||||||
|
///
|
||||||
|
/// - Deactivated: The user is not using vChewing yet.
|
||||||
|
/// - Empty: The user has switched to vChewing but did not input anything yet,
|
||||||
|
/// or, he or she has committed text into the client apps and starts a new
|
||||||
|
/// input phase.
|
||||||
|
/// - Committing: The input controller is sending text to the client apps.
|
||||||
|
/// - Inputting: The user has inputted something and the input buffer is
|
||||||
|
/// visible.
|
||||||
|
/// - Marking: The user is creating a area in the input buffer and about to
|
||||||
|
/// create a new user phrase.
|
||||||
|
/// - Choosing Candidate: The candidate window is open to let the user to choose
|
||||||
|
/// one among the candidates.
|
||||||
|
class InputState: NSObject {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Represents that the input controller is deactivated.
|
||||||
|
class InputStateDeactivated: InputState {
|
||||||
|
override var description: String {
|
||||||
|
"<InputStateDeactivated>"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Represents that the composing buffer is empty.
|
||||||
|
class InputStateEmpty: InputState {
|
||||||
|
@objc var composingBuffer: String {
|
||||||
|
""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Represents that the composing buffer is empty.
|
||||||
|
class InputStateEmptyIgnoringPreviousState: InputState {
|
||||||
|
@objc var composingBuffer: String {
|
||||||
|
""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Represents that the input controller is committing text into client app.
|
||||||
|
class InputStateCommitting: InputState {
|
||||||
|
@objc private(set) var poppedText: String = ""
|
||||||
|
|
||||||
|
@objc convenience init(poppedText: String) {
|
||||||
|
self.init()
|
||||||
|
self.poppedText = poppedText
|
||||||
|
}
|
||||||
|
|
||||||
|
override var description: String {
|
||||||
|
"<InputStateCommitting poppedText:\(poppedText)>"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Represents that the composing buffer is not empty.
|
||||||
|
class InputStateNotEmpty: InputState {
|
||||||
|
@objc private(set) var composingBuffer: String = ""
|
||||||
|
@objc private(set) var cursorIndex: UInt = 0
|
||||||
|
|
||||||
|
@objc init(composingBuffer: String, cursorIndex: UInt) {
|
||||||
|
self.composingBuffer = composingBuffer
|
||||||
|
self.cursorIndex = cursorIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
override var description: String {
|
||||||
|
"<InputStateNotEmpty, composingBuffer:\(composingBuffer), cursorIndex:\(cursorIndex)>"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Represents that the user is inputting text.
|
||||||
|
class InputStateInputting: InputStateNotEmpty {
|
||||||
|
@objc var bpmfReading: String = ""
|
||||||
|
@objc var bpmfReadingCursorIndex: UInt8 = 0
|
||||||
|
@objc var poppedText: String = ""
|
||||||
|
|
||||||
|
@objc override init(composingBuffer: String, cursorIndex: UInt) {
|
||||||
|
super.init(composingBuffer: composingBuffer, cursorIndex: cursorIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc var attributedString: NSAttributedString {
|
||||||
|
let attributedSting = NSAttributedString(string: composingBuffer, attributes: [
|
||||||
|
.underlineStyle: NSUnderlineStyle.single.rawValue,
|
||||||
|
.markedClauseSegment: 0
|
||||||
|
])
|
||||||
|
return attributedSting
|
||||||
|
}
|
||||||
|
|
||||||
|
override var description: String {
|
||||||
|
"<InputStateInputting, composingBuffer:\(composingBuffer), cursorIndex:\(cursorIndex), poppedText:\(poppedText)>"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private let kMinMarkRangeLength = 2
|
||||||
|
private let kMaxMarkRangeLength = Preferences.maxCandidateLength
|
||||||
|
|
||||||
|
/// Represents that the user is marking a range in the composing buffer.
|
||||||
|
class InputStateMarking: InputStateNotEmpty {
|
||||||
|
@objc private(set) var markerIndex: UInt
|
||||||
|
@objc private(set) var markedRange: NSRange
|
||||||
|
@objc var tooltip: String {
|
||||||
|
|
||||||
|
if Preferences.phraseReplacementEnabled {
|
||||||
|
return NSLocalizedString("⚠︎ Phrase replacement mode enabled, interfering user phrase entry.", comment: "")
|
||||||
|
}
|
||||||
|
|
||||||
|
if markedRange.length == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
let text = (composingBuffer as NSString).substring(with: markedRange)
|
||||||
|
if markedRange.length < kMinMarkRangeLength {
|
||||||
|
return String(format: NSLocalizedString("\"%@\" length must ≥ 2 for a user phrase.", comment: ""), text)
|
||||||
|
} else if (markedRange.length > kMaxMarkRangeLength) {
|
||||||
|
return String(format: NSLocalizedString("\"%@\" length should ≤ %d for a user phrase.", comment: ""), text, kMaxMarkRangeLength)
|
||||||
|
}
|
||||||
|
return String(format: NSLocalizedString("\"%@\" selected. ENTER to add user phrase.", comment: ""), text)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private(set) var readings: [String] = []
|
||||||
|
|
||||||
|
@objc init(composingBuffer: String, cursorIndex: UInt, markerIndex: UInt, readings: [String]) {
|
||||||
|
self.markerIndex = markerIndex
|
||||||
|
let begin = min(cursorIndex, markerIndex)
|
||||||
|
let end = max(cursorIndex, markerIndex)
|
||||||
|
markedRange = NSMakeRange(Int(begin), Int(end - begin))
|
||||||
|
self.readings = readings
|
||||||
|
super.init(composingBuffer: composingBuffer, cursorIndex: cursorIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc var attributedString: NSAttributedString {
|
||||||
|
let attributedSting = NSMutableAttributedString(string: composingBuffer)
|
||||||
|
let end = markedRange.location + markedRange.length
|
||||||
|
|
||||||
|
attributedSting.setAttributes([
|
||||||
|
.underlineStyle: NSUnderlineStyle.single.rawValue,
|
||||||
|
.markedClauseSegment: 0
|
||||||
|
], range: NSRange(location: 0, length: markedRange.location))
|
||||||
|
attributedSting.setAttributes([
|
||||||
|
.underlineStyle: NSUnderlineStyle.thick.rawValue,
|
||||||
|
.markedClauseSegment: 1
|
||||||
|
], range: markedRange)
|
||||||
|
attributedSting.setAttributes([
|
||||||
|
.underlineStyle: NSUnderlineStyle.single.rawValue,
|
||||||
|
.markedClauseSegment: 2
|
||||||
|
], range: NSRange(location: end,
|
||||||
|
length: composingBuffer.count - end))
|
||||||
|
return attributedSting
|
||||||
|
}
|
||||||
|
|
||||||
|
override var description: String {
|
||||||
|
"<InputStateMarking, composingBuffer:\(composingBuffer), cursorIndex:\(cursorIndex), markedRange:\(markedRange), readings:\(readings)>"
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func convertToInputting() -> InputStateInputting {
|
||||||
|
let state = InputStateInputting(composingBuffer: composingBuffer, cursorIndex: cursorIndex)
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc var validToWrite: Bool {
|
||||||
|
markedRange.length >= kMinMarkRangeLength && markedRange.length <= kMaxMarkRangeLength
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc var userPhrase: String {
|
||||||
|
let text = (composingBuffer as NSString).substring(with: markedRange)
|
||||||
|
let end = markedRange.location + markedRange.length
|
||||||
|
let readings = readings[markedRange.location..<end]
|
||||||
|
let joined = readings.joined(separator: "-")
|
||||||
|
return "\(text) \(joined)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Represents that the user is choosing in a candidates list.
|
||||||
|
class InputStateChoosingCandidate: InputStateNotEmpty {
|
||||||
|
@objc private(set) var candidates: [String] = []
|
||||||
|
@objc private(set) var useVerticalMode: Bool = false
|
||||||
|
|
||||||
|
@objc init(composingBuffer: String, cursorIndex: UInt, candidates: [String], useVerticalMode: Bool) {
|
||||||
|
self.candidates = candidates
|
||||||
|
self.useVerticalMode = useVerticalMode
|
||||||
|
super.init(composingBuffer: composingBuffer, cursorIndex: cursorIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc var attributedString: NSAttributedString {
|
||||||
|
let attributedSting = NSAttributedString(string: composingBuffer, attributes: [
|
||||||
|
.underlineStyle: NSUnderlineStyle.single.rawValue,
|
||||||
|
.markedClauseSegment: 0
|
||||||
|
])
|
||||||
|
return attributedSting
|
||||||
|
}
|
||||||
|
|
||||||
|
override var description: String {
|
||||||
|
"<InputStateChoosingCandidate, candidates:\(candidates), useVerticalMode:\(useVerticalMode), composingBuffer:\(composingBuffer), cursorIndex:\(cursorIndex)>"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* KeyHandler.h
|
||||||
|
*
|
||||||
|
* Copyright 2021-2022 vChewing Project (3-Clause BSD License).
|
||||||
|
* Derived from 2011-2022 OpenVanilla Project (MIT License).
|
||||||
|
* Some rights reserved. See "LICENSE.TXT" for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import <string>
|
||||||
|
#import "vChewing-Swift.h"
|
||||||
|
|
||||||
|
@class KeyHandlerInput;
|
||||||
|
@class InputState;
|
||||||
|
@class InputStateInputting;
|
||||||
|
@class InputStateMarking;
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
extern NSString *const kBopomofoModeIdentifierCHS;
|
||||||
|
extern NSString *const kBopomofoModeIdentifierCHT;
|
||||||
|
|
||||||
|
@class KeyHandler;
|
||||||
|
|
||||||
|
@protocol KeyHandlerDelegate <NSObject>
|
||||||
|
- (VTCandidateController *)candidateControllerForKeyHandler:(KeyHandler *)keyHandler;
|
||||||
|
- (void)keyHandler:(KeyHandler *)keyHandler didSelectCandidateAtIndex:(NSInteger)index candidateController:(VTCandidateController *)controller;
|
||||||
|
- (BOOL)keyHandler:(KeyHandler *)keyHandler didRequestWriteUserPhraseWithState:(InputStateMarking *)state;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface KeyHandler : NSObject
|
||||||
|
|
||||||
|
- (BOOL)handleInput:(KeyHandlerInput *)input
|
||||||
|
state:(InputState *)state
|
||||||
|
stateCallback:(void (^)(InputState *))stateCallback
|
||||||
|
candidateSelectionCallback:(void (^)(void))candidateSelectionCallback
|
||||||
|
errorCallback:(void (^)(void))errorCallback;
|
||||||
|
|
||||||
|
- (void)syncWithPreferences;
|
||||||
|
- (void)fixNodeWithValue:(std::string)value;
|
||||||
|
- (void)clear;
|
||||||
|
|
||||||
|
- (InputStateInputting *)_buildInputtingState;
|
||||||
|
|
||||||
|
@property (strong, nonatomic) NSString *inputMode;
|
||||||
|
@property (weak, nonatomic) id <KeyHandlerDelegate> delegate;
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,178 @@
|
||||||
|
/*
|
||||||
|
* KeyHandlerInput.swift
|
||||||
|
*
|
||||||
|
* Copyright 2021-2022 vChewing Project (3-Clause BSD License).
|
||||||
|
* Derived from 2011-2022 OpenVanilla Project (MIT License).
|
||||||
|
* Some rights reserved. See "LICENSE.TXT" for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Cocoa
|
||||||
|
|
||||||
|
enum KeyCode: UInt16 {
|
||||||
|
case none = 0
|
||||||
|
case enter = 76
|
||||||
|
case up = 126
|
||||||
|
case down = 125
|
||||||
|
case left = 123
|
||||||
|
case right = 124
|
||||||
|
case pageUp = 116
|
||||||
|
case pageDown = 121
|
||||||
|
case home = 115
|
||||||
|
case end = 119
|
||||||
|
case delete = 117
|
||||||
|
}
|
||||||
|
|
||||||
|
class KeyHandlerInput: NSObject {
|
||||||
|
@objc private (set) var useVerticalMode: Bool
|
||||||
|
@objc private (set) var inputText: String?
|
||||||
|
@objc private (set) var charCode: UInt16
|
||||||
|
private var keyCode: UInt16
|
||||||
|
private var flags: NSEvent.ModifierFlags
|
||||||
|
private var cursorForwardKey: KeyCode
|
||||||
|
private var cursorBackwardKey: KeyCode
|
||||||
|
private var extraChooseCandidateKey: KeyCode
|
||||||
|
private var absorbedArrowKey: KeyCode
|
||||||
|
private var verticalModeOnlyChooseCandidateKey: KeyCode
|
||||||
|
@objc private (set) var emacsKey: vChewingEmacsKey
|
||||||
|
|
||||||
|
@objc init(inputText: String?, keyCode: UInt16, charCode: UInt16, flags: NSEvent.ModifierFlags, isVerticalMode: Bool) {
|
||||||
|
self.inputText = inputText
|
||||||
|
self.keyCode = keyCode
|
||||||
|
self.charCode = charCode
|
||||||
|
self.flags = flags
|
||||||
|
useVerticalMode = isVerticalMode
|
||||||
|
emacsKey = EmacsKeyHelper.detect(charCode: charCode, flags: flags)
|
||||||
|
cursorForwardKey = useVerticalMode ? .down : .right
|
||||||
|
cursorBackwardKey = useVerticalMode ? .up : .left
|
||||||
|
extraChooseCandidateKey = useVerticalMode ? .left : .down
|
||||||
|
absorbedArrowKey = useVerticalMode ? .right : .up
|
||||||
|
verticalModeOnlyChooseCandidateKey = useVerticalMode ? absorbedArrowKey : .none
|
||||||
|
super.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc init(event: NSEvent, isVerticalMode: Bool) {
|
||||||
|
inputText = event.characters
|
||||||
|
keyCode = event.keyCode
|
||||||
|
flags = event.modifierFlags
|
||||||
|
useVerticalMode = isVerticalMode
|
||||||
|
let charCode: UInt16 = {
|
||||||
|
guard let inputText = event.characters, inputText.count > 0 else {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
let first = inputText[inputText.startIndex].utf16.first!
|
||||||
|
return first
|
||||||
|
}()
|
||||||
|
self.charCode = charCode
|
||||||
|
emacsKey = EmacsKeyHelper.detect(charCode: charCode, flags: event.modifierFlags)
|
||||||
|
cursorForwardKey = useVerticalMode ? .down : .right
|
||||||
|
cursorBackwardKey = useVerticalMode ? .up : .left
|
||||||
|
extraChooseCandidateKey = useVerticalMode ? .left : .down
|
||||||
|
absorbedArrowKey = useVerticalMode ? .right : .up
|
||||||
|
verticalModeOnlyChooseCandidateKey = useVerticalMode ? absorbedArrowKey : .none
|
||||||
|
super.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc var isShiftHold: Bool {
|
||||||
|
flags.contains([.shift])
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc var isCommandHold: Bool {
|
||||||
|
flags.contains([.command])
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc var isControlHold: Bool {
|
||||||
|
flags.contains([.control])
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc var isOptionHold: Bool {
|
||||||
|
flags.contains([.option])
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc var isCapsLockOn: Bool {
|
||||||
|
flags.contains([.capsLock])
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc var isNumericPad: Bool {
|
||||||
|
flags.contains([.numericPad])
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc var isEnter: Bool {
|
||||||
|
KeyCode(rawValue: keyCode) == KeyCode.enter
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc var isUp: Bool {
|
||||||
|
KeyCode(rawValue: keyCode) == KeyCode.up
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc var isDown: Bool {
|
||||||
|
KeyCode(rawValue: keyCode) == KeyCode.down
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc var isLeft: Bool {
|
||||||
|
KeyCode(rawValue: keyCode) == KeyCode.left
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc var isRight: Bool {
|
||||||
|
KeyCode(rawValue: keyCode) == KeyCode.right
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc var isPageUp: Bool {
|
||||||
|
KeyCode(rawValue: keyCode) == KeyCode.pageUp
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc var isPageDown: Bool {
|
||||||
|
KeyCode(rawValue: keyCode) == KeyCode.pageDown
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc var isHome: Bool {
|
||||||
|
KeyCode(rawValue: keyCode) == KeyCode.home
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc var isEnd: Bool {
|
||||||
|
KeyCode(rawValue: keyCode) == KeyCode.end
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc var isDelete: Bool {
|
||||||
|
KeyCode(rawValue: keyCode) == KeyCode.delete
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc var isCursorBackward: Bool {
|
||||||
|
KeyCode(rawValue: keyCode) == cursorBackwardKey
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc var isCursorForward: Bool {
|
||||||
|
KeyCode(rawValue: keyCode) == cursorForwardKey
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc var isAbsorbedArrowKey: Bool {
|
||||||
|
KeyCode(rawValue: keyCode) == absorbedArrowKey
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc var isExtraChooseCandidateKey: Bool {
|
||||||
|
KeyCode(rawValue: keyCode) == extraChooseCandidateKey
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc var isVerticalModeOnlyChooseCandidateKey: Bool {
|
||||||
|
KeyCode(rawValue: keyCode) == verticalModeOnlyChooseCandidateKey
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc enum vChewingEmacsKey: UInt16 {
|
||||||
|
case none = 0
|
||||||
|
case forward = 6 // F
|
||||||
|
case backward = 2 // B
|
||||||
|
case home = 1 // A
|
||||||
|
case end = 5 // E
|
||||||
|
case delete = 4 // D
|
||||||
|
case nextPage = 22 // V
|
||||||
|
}
|
||||||
|
|
||||||
|
class EmacsKeyHelper: NSObject {
|
||||||
|
@objc static func detect(charCode: UniChar, flags: NSEvent.ModifierFlags) -> vChewingEmacsKey {
|
||||||
|
if flags.contains(.control) {
|
||||||
|
return vChewingEmacsKey(rawValue: charCode) ?? .none
|
||||||
|
}
|
||||||
|
return .none;
|
||||||
|
}
|
||||||
|
}
|
|
@ -34,9 +34,7 @@ namespace Taiyan {
|
||||||
void setJoinSeparator(const string& separator);
|
void setJoinSeparator(const string& separator);
|
||||||
const string joinSeparator() const;
|
const string joinSeparator() const;
|
||||||
|
|
||||||
size_t markerCursorIndex() const;
|
vector<string> readings() const;
|
||||||
void setMarkerCursorIndex(size_t inNewIndex);
|
|
||||||
vector<string> readingsAtRange(size_t begin, size_t end) const;
|
|
||||||
|
|
||||||
Grid& grid();
|
Grid& grid();
|
||||||
|
|
||||||
|
@ -49,7 +47,6 @@ namespace Taiyan {
|
||||||
static const size_t MaximumBuildSpanLength = 10;
|
static const size_t MaximumBuildSpanLength = 10;
|
||||||
|
|
||||||
size_t m_cursorIndex;
|
size_t m_cursorIndex;
|
||||||
size_t m_markerCursorIndex;
|
|
||||||
vector<string> m_readings;
|
vector<string> m_readings;
|
||||||
|
|
||||||
Grid m_grid;
|
Grid m_grid;
|
||||||
|
@ -60,14 +57,12 @@ namespace Taiyan {
|
||||||
inline BlockReadingBuilder::BlockReadingBuilder(LanguageModel *inLM)
|
inline BlockReadingBuilder::BlockReadingBuilder(LanguageModel *inLM)
|
||||||
: m_LM(inLM)
|
: m_LM(inLM)
|
||||||
, m_cursorIndex(0)
|
, m_cursorIndex(0)
|
||||||
, m_markerCursorIndex(SIZE_MAX)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void BlockReadingBuilder::clear()
|
inline void BlockReadingBuilder::clear()
|
||||||
{
|
{
|
||||||
m_cursorIndex = 0;
|
m_cursorIndex = 0;
|
||||||
m_markerCursorIndex = SIZE_MAX;
|
|
||||||
m_readings.clear();
|
m_readings.clear();
|
||||||
m_grid.clear();
|
m_grid.clear();
|
||||||
}
|
}
|
||||||
|
@ -86,21 +81,6 @@ namespace Taiyan {
|
||||||
{
|
{
|
||||||
m_cursorIndex = inNewIndex > m_readings.size() ? m_readings.size() : inNewIndex;
|
m_cursorIndex = inNewIndex > m_readings.size() ? m_readings.size() : inNewIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline size_t BlockReadingBuilder::markerCursorIndex() const
|
|
||||||
{
|
|
||||||
return m_markerCursorIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void BlockReadingBuilder::setMarkerCursorIndex(size_t inNewIndex)
|
|
||||||
{
|
|
||||||
if (inNewIndex == SIZE_MAX) {
|
|
||||||
m_markerCursorIndex = SIZE_MAX;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_markerCursorIndex = inNewIndex > m_readings.size() ? m_readings.size() : inNewIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void BlockReadingBuilder::insertReadingAtCursor(const string& inReading)
|
inline void BlockReadingBuilder::insertReadingAtCursor(const string& inReading)
|
||||||
{
|
{
|
||||||
|
@ -111,12 +91,9 @@ namespace Taiyan {
|
||||||
m_cursorIndex++;
|
m_cursorIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline vector<string> BlockReadingBuilder::readingsAtRange(size_t begin, size_t end) const {
|
inline vector<string> BlockReadingBuilder::readings() const
|
||||||
vector<string> v;
|
{
|
||||||
for (size_t i = begin; i < end; i++) {
|
return m_readings;
|
||||||
v.push_back(m_readings[i]);
|
|
||||||
}
|
|
||||||
return v;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool BlockReadingBuilder::deleteReadingBeforeCursor()
|
inline bool BlockReadingBuilder::deleteReadingBeforeCursor()
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
/*
|
|
||||||
* EmacsKeyHelper.swift
|
|
||||||
*
|
|
||||||
* Copyright 2021-2022 vChewing Project (3-Clause BSD License).
|
|
||||||
* Derived from 2011-2022 OpenVanilla Project (MIT License).
|
|
||||||
* Some rights reserved. See "LICENSE.TXT" for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import Cocoa
|
|
||||||
|
|
||||||
@objc enum vChewingEmacsKey: UInt16 {
|
|
||||||
case none = 0
|
|
||||||
case forward = 6 // F
|
|
||||||
case backward = 2 // B
|
|
||||||
case home = 1 // A
|
|
||||||
case end = 5 // E
|
|
||||||
case delete = 4 // D
|
|
||||||
case nextPage = 22 // V
|
|
||||||
}
|
|
||||||
|
|
||||||
class EmacsKeyHelper: NSObject {
|
|
||||||
@objc static func detect(charCode: UniChar, flags: NSEvent.ModifierFlags) -> vChewingEmacsKey {
|
|
||||||
if flags.contains(.control) {
|
|
||||||
return vChewingEmacsKey(rawValue: charCode) ?? .none
|
|
||||||
}
|
|
||||||
return .none;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -8,43 +8,8 @@
|
||||||
|
|
||||||
#import <Cocoa/Cocoa.h>
|
#import <Cocoa/Cocoa.h>
|
||||||
#import <InputMethodKit/InputMethodKit.h>
|
#import <InputMethodKit/InputMethodKit.h>
|
||||||
#import "Mandarin.hh"
|
#import "vChewing-Swift.h"
|
||||||
#import "Gramambular.h"
|
|
||||||
#import "vChewingLM.h"
|
|
||||||
#import "UserOverrideModel.h"
|
|
||||||
|
|
||||||
@interface vChewingInputMethodController : IMKInputController
|
@interface vChewingInputMethodController : IMKInputController
|
||||||
{
|
- (void)handleState:(InputState *)newState client:(id)client;
|
||||||
@private
|
|
||||||
// the reading buffer that takes user input
|
|
||||||
Taiyan::Mandarin::BopomofoReadingBuffer* _bpmfReadingBuffer;
|
|
||||||
|
|
||||||
// language model
|
|
||||||
vChewing::vChewingLM *_languageModel;
|
|
||||||
|
|
||||||
// user override model
|
|
||||||
vChewing::UserOverrideModel *_userOverrideModel;
|
|
||||||
|
|
||||||
// the grid (lattice) builder for the unigrams (and bigrams)
|
|
||||||
Taiyan::Gramambular::BlockReadingBuilder* _builder;
|
|
||||||
|
|
||||||
// latest walked path (trellis) using the Viterbi algorithm
|
|
||||||
std::vector<Taiyan::Gramambular::NodeAnchor> _walkedNodes;
|
|
||||||
|
|
||||||
// the latest composing buffer that is updated to the foreground app
|
|
||||||
NSMutableString *_composingBuffer;
|
|
||||||
NSInteger _latestReadingCursor;
|
|
||||||
|
|
||||||
// the current text input client; we need to keep this when candidate panel is on
|
|
||||||
id _currentCandidateClient;
|
|
||||||
|
|
||||||
// a special deferred client for Terminal.app fix
|
|
||||||
id _currentDeferredClient;
|
|
||||||
|
|
||||||
// currently available candidates
|
|
||||||
NSMutableArray *_candidates;
|
|
||||||
|
|
||||||
// current input mode
|
|
||||||
NSString *_inputMode;
|
|
||||||
}
|
|
||||||
@end
|
@end
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -7,15 +7,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#import "LanguageModelManager.h"
|
#import "LanguageModelManager.h"
|
||||||
#import <fstream>
|
|
||||||
#import <iostream>
|
|
||||||
#import <set>
|
|
||||||
#import "OVUTF8Helper.h"
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace Taiyan::Gramambular;
|
|
||||||
using namespace vChewing;
|
using namespace vChewing;
|
||||||
using namespace OpenVanilla;
|
|
||||||
|
|
||||||
static const int kUserOverrideModelCapacity = 500;
|
static const int kUserOverrideModelCapacity = 500;
|
||||||
static const double kObservedOverrideHalflife = 5400.0; // 1.5 hr.
|
static const double kObservedOverrideHalflife = 5400.0; // 1.5 hr.
|
||||||
|
@ -72,7 +66,7 @@ static void LTLoadLanguageModelFile(NSString *filenameWithoutExtension, vChewing
|
||||||
NSLog(@"User Data Folder N/A.");
|
NSLog(@"User Data Folder N/A.");
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
if (![self checkIfFileExist:[self cnsDataPath]]) {
|
if (![self ensureFileExists:[self cnsDataPath]]) {
|
||||||
NSLog(@"Extracted CNS Data Not Found.");
|
NSLog(@"Extracted CNS Data Not Found.");
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
@ -122,7 +116,7 @@ static void LTLoadLanguageModelFile(NSString *filenameWithoutExtension, vChewing
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (BOOL)checkIfFileExist:(NSString *)filePath
|
+ (BOOL)ensureFileExists:(NSString *)filePath
|
||||||
{
|
{
|
||||||
if (![[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
|
if (![[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
|
||||||
BOOL result = [[@"" dataUsingEncoding:NSUTF8StringEncoding] writeToFile:filePath atomically:YES];
|
BOOL result = [[@"" dataUsingEncoding:NSUTF8StringEncoding] writeToFile:filePath atomically:YES];
|
||||||
|
@ -139,22 +133,22 @@ static void LTLoadLanguageModelFile(NSString *filenameWithoutExtension, vChewing
|
||||||
if (![self checkIfUserDataFolderExists]) {
|
if (![self checkIfUserDataFolderExists]) {
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
if (![self checkIfFileExist:[self userPhrasesDataPath:kBopomofoModeIdentifierCHT]]) {
|
if (![self ensureFileExists:[self userPhrasesDataPath:kBopomofoModeIdentifierCHT]]) {
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
if (![self checkIfFileExist:[self excludedPhrasesDataPath:kBopomofoModeIdentifierCHT]]) {
|
if (![self ensureFileExists:[self excludedPhrasesDataPath:kBopomofoModeIdentifierCHT]]) {
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
if (![self checkIfFileExist:[self phraseReplacementDataPath:kBopomofoModeIdentifierCHT]]) {
|
if (![self ensureFileExists:[self phraseReplacementDataPath:kBopomofoModeIdentifierCHT]]) {
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
if (![self checkIfFileExist:[self userPhrasesDataPath:kBopomofoModeIdentifierCHS]]) {
|
if (![self ensureFileExists:[self userPhrasesDataPath:kBopomofoModeIdentifierCHS]]) {
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
if (![self checkIfFileExist:[self excludedPhrasesDataPath:kBopomofoModeIdentifierCHS]]) {
|
if (![self ensureFileExists:[self excludedPhrasesDataPath:kBopomofoModeIdentifierCHS]]) {
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
if (![self checkIfFileExist:[self phraseReplacementDataPath:kBopomofoModeIdentifierCHS]]) {
|
if (![self ensureFileExists:[self phraseReplacementDataPath:kBopomofoModeIdentifierCHS]]) {
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
return YES;
|
return YES;
|
||||||
|
@ -188,7 +182,7 @@ static void LTLoadLanguageModelFile(NSString *filenameWithoutExtension, vChewing
|
||||||
+ (NSString *)dataFolderPath
|
+ (NSString *)dataFolderPath
|
||||||
{
|
{
|
||||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDirectory, YES);
|
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDirectory, YES);
|
||||||
NSString *appSupportPath = [paths objectAtIndex:0];
|
NSString *appSupportPath = paths[0];
|
||||||
NSString *userDictPath = [appSupportPath stringByAppendingPathComponent:@"vChewing"];
|
NSString *userDictPath = [appSupportPath stringByAppendingPathComponent:@"vChewing"];
|
||||||
return userDictPath;
|
return userDictPath;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,9 +21,9 @@
|
||||||
"Unable to create the user phrase file." = "Unable to create the user phrase file.";
|
"Unable to create the user phrase file." = "Unable to create the user phrase file.";
|
||||||
"Please check the permission of at \"%@\"." = "Please check the permission of at \"%@\".";
|
"Please check the permission of at \"%@\"." = "Please check the permission of at \"%@\".";
|
||||||
"Edit Excluded Phrases" = "Edit Excluded Phrases…";
|
"Edit Excluded Phrases" = "Edit Excluded Phrases…";
|
||||||
"Use Half-Width Punctuations" = "Use Half-Width Punctuations";
|
"Half-Width Punctuation Mode" = "Half-Width Punctuation Mode";
|
||||||
"\"%@\" length must ≥ 2 for a user phrase." = "\"%@\" length must ≥ 2 for a user phrase.";
|
"\"%@\" length must ≥ 2 for a user phrase." = "\"%@\" length must ≥ 2 for a user phrase.";
|
||||||
"\"%@\" length too long for a user phrase." = "\"%@\" length too long for a user phrase.";
|
"\"%@\" length should ≤ %d for a user phrase." = "\"%@\" length should ≤ %d for a user phrase.";
|
||||||
"\"%@\" selected. ENTER to add user phrase." = "\"%@\" selected. ENTER to add user phrase.";
|
"\"%@\" selected. ENTER to add user phrase." = "\"%@\" selected. ENTER to add user phrase.";
|
||||||
"Edit Phrase Replacement Table" = "Edit Phrase Replacement Table…";
|
"Edit Phrase Replacement Table" = "Edit Phrase Replacement Table…";
|
||||||
"Use Phrase Replacement" = "Use Phrase Replacement";
|
"Use Phrase Replacement" = "Use Phrase Replacement";
|
||||||
|
|
|
@ -21,9 +21,9 @@
|
||||||
"Unable to create the user phrase file." = "ユーザー辞書ファイルの作成は失敗しました。";
|
"Unable to create the user phrase file." = "ユーザー辞書ファイルの作成は失敗しました。";
|
||||||
"Please check the permission of at \"%@\"." = "「%@」に書き出す権限は不足らしい。";
|
"Please check the permission of at \"%@\"." = "「%@」に書き出す権限は不足らしい。";
|
||||||
"Edit Excluded Phrases" = "辞書条目排除表を編集…";
|
"Edit Excluded Phrases" = "辞書条目排除表を編集…";
|
||||||
"Use Half-Width Punctuations" = "半角句読機能を起用";
|
"Half-Width Punctuation Mode" = "半角句読モード";
|
||||||
"\"%@\" length must ≥ 2 for a user phrase." = "「%@」もう1つ文字のお選びを。";
|
"\"%@\" length must ≥ 2 for a user phrase." = "「%@」もう1つ文字のお選びを。";
|
||||||
"\"%@\" length too long for a user phrase." = "「%@」文字数過剰で登録不可。";
|
"\"%@\" length should ≤ %d for a user phrase." = "「%@」文字数過剰で登録不可、%d 文字以内にして下さい。";
|
||||||
"\"%@\" selected. ENTER to add user phrase." = "「%@」を ENTER で辞書に登録。";
|
"\"%@\" selected. ENTER to add user phrase." = "「%@」を ENTER で辞書に登録。";
|
||||||
"Edit Phrase Replacement Table" = "言葉置換表を編集…";
|
"Edit Phrase Replacement Table" = "言葉置換表を編集…";
|
||||||
"Use Phrase Replacement" = "言葉置換機能";
|
"Use Phrase Replacement" = "言葉置換機能";
|
||||||
|
|
|
@ -21,9 +21,9 @@
|
||||||
"Unable to create the user phrase file." = "无法创建自订语汇档案。";
|
"Unable to create the user phrase file." = "无法创建自订语汇档案。";
|
||||||
"Please check the permission of at \"%@\"." = "请检查此处的存取权限:\"%@\".";
|
"Please check the permission of at \"%@\"." = "请检查此处的存取权限:\"%@\".";
|
||||||
"Edit Excluded Phrases" = "编辑要滤除的语汇…";
|
"Edit Excluded Phrases" = "编辑要滤除的语汇…";
|
||||||
"Use Half-Width Punctuations" = "啟用半角標點輸出";
|
"Half-Width Punctuation Mode" = "半角标点模式";
|
||||||
"\"%@\" length must ≥ 2 for a user phrase." = "「%@」字数不足以自订语汇。";
|
"\"%@\" length must ≥ 2 for a user phrase." = "「%@」字数不足以自订语汇。";
|
||||||
"\"%@\" length too long for a user phrase." = "「%@」字数太长、无法自订。";
|
"\"%@\" length should ≤ %d for a user phrase." = "「%@」字数超过 %d、无法自订。";
|
||||||
"\"%@\" selected. ENTER to add user phrase." = "「%@」敲 Enter 添入自订语汇。";
|
"\"%@\" selected. ENTER to add user phrase." = "「%@」敲 Enter 添入自订语汇。";
|
||||||
"Edit Phrase Replacement Table" = "编辑语汇置换表…";
|
"Edit Phrase Replacement Table" = "编辑语汇置换表…";
|
||||||
"Use Phrase Replacement" = "使用语汇置换";
|
"Use Phrase Replacement" = "使用语汇置换";
|
||||||
|
|
|
@ -21,9 +21,9 @@
|
||||||
"Unable to create the user phrase file." = "無法創建自訂語彙檔案。";
|
"Unable to create the user phrase file." = "無法創建自訂語彙檔案。";
|
||||||
"Please check the permission of at \"%@\"." = "請檢查此處的存取權限:\"%@\".";
|
"Please check the permission of at \"%@\"." = "請檢查此處的存取權限:\"%@\".";
|
||||||
"Edit Excluded Phrases" = "編輯要濾除的語彙…";
|
"Edit Excluded Phrases" = "編輯要濾除的語彙…";
|
||||||
"Use Half-Width Punctuations" = "啟用半形標點輸出";
|
"Half-Width Punctuation Mode" = "半形標點模式";
|
||||||
"\"%@\" length must ≥ 2 for a user phrase." = "「%@」字數不足以自訂語彙。";
|
"\"%@\" length must ≥ 2 for a user phrase." = "「%@」字數不足以自訂語彙。";
|
||||||
"\"%@\" length too long for a user phrase." = "「%@」字數太長、無法自訂。";
|
"\"%@\" length should ≤ %d for a user phrase." = "「%@」字數超過 %d、無法自訂。";
|
||||||
"\"%@\" selected. ENTER to add user phrase." = "「%@」敲 Enter 添入自訂語彙。";
|
"\"%@\" selected. ENTER to add user phrase." = "「%@」敲 Enter 添入自訂語彙。";
|
||||||
"Edit Phrase Replacement Table" = "編輯語彙置換表…";
|
"Edit Phrase Replacement Table" = "編輯語彙置換表…";
|
||||||
"Use Phrase Replacement" = "使用語彙置換";
|
"Use Phrase Replacement" = "使用語彙置換";
|
||||||
|
|
|
@ -23,12 +23,14 @@
|
||||||
5B810D9F27A3A5E50032C1A9 /* LMConsolidator.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5B810D9D27A3A5E50032C1A9 /* LMConsolidator.mm */; };
|
5B810D9F27A3A5E50032C1A9 /* LMConsolidator.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5B810D9D27A3A5E50032C1A9 /* LMConsolidator.mm */; };
|
||||||
5B9DD0A927A7950D00ED335A /* FSEventStreamHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B9DD0A827A7950D00ED335A /* FSEventStreamHelper.swift */; };
|
5B9DD0A927A7950D00ED335A /* FSEventStreamHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B9DD0A827A7950D00ED335A /* FSEventStreamHelper.swift */; };
|
||||||
5BC2D2882793B434002C0BEC /* KeyValueBlobReader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5BC2D2862793B434002C0BEC /* KeyValueBlobReader.cpp */; };
|
5BC2D2882793B434002C0BEC /* KeyValueBlobReader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5BC2D2862793B434002C0BEC /* KeyValueBlobReader.cpp */; };
|
||||||
5BC2D28B2793B8FB002C0BEC /* EmacsKeyHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC2D28A2793B8FB002C0BEC /* EmacsKeyHelper.swift */; };
|
|
||||||
5BC2D28D2793B98F002C0BEC /* PreferencesModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC2D28C2793B98F002C0BEC /* PreferencesModule.swift */; };
|
5BC2D28D2793B98F002C0BEC /* PreferencesModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC2D28C2793B98F002C0BEC /* PreferencesModule.swift */; };
|
||||||
5BC3EE1B278FC48C00F5E44C /* VerticalCandidateController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC3EE18278FC48C00F5E44C /* VerticalCandidateController.swift */; };
|
5BC3EE1B278FC48C00F5E44C /* VerticalCandidateController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC3EE18278FC48C00F5E44C /* VerticalCandidateController.swift */; };
|
||||||
5BC3EE1C278FC48C00F5E44C /* VTCandidateController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC3EE19278FC48C00F5E44C /* VTCandidateController.swift */; };
|
5BC3EE1C278FC48C00F5E44C /* VTCandidateController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC3EE19278FC48C00F5E44C /* VTCandidateController.swift */; };
|
||||||
5BC3EE1D278FC48C00F5E44C /* HorizontalCandidateController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC3EE1A278FC48C00F5E44C /* HorizontalCandidateController.swift */; };
|
5BC3EE1D278FC48C00F5E44C /* HorizontalCandidateController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC3EE1A278FC48C00F5E44C /* HorizontalCandidateController.swift */; };
|
||||||
5BC3FB83278492DE0022E99A /* data-chs.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5BC3FB82278492DE0022E99A /* data-chs.txt */; };
|
5BC3FB83278492DE0022E99A /* data-chs.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5BC3FB82278492DE0022E99A /* data-chs.txt */; };
|
||||||
|
5BC772AA27A5A1E800CA8391 /* InputState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC772A927A5A1E800CA8391 /* InputState.swift */; };
|
||||||
|
5BC772AC27A5A31200CA8391 /* KeyHandlerInput.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC772AB27A5A31200CA8391 /* KeyHandlerInput.swift */; };
|
||||||
|
5BC772B027A5B3AB00CA8391 /* KeyHandler.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5BC772AD27A5A31B00CA8391 /* KeyHandler.mm */; };
|
||||||
5BD0D19427940E9D0008F48E /* Fart.aif in Resources */ = {isa = PBXBuildFile; fileRef = 5BD0D19327940E9D0008F48E /* Fart.aif */; };
|
5BD0D19427940E9D0008F48E /* Fart.aif in Resources */ = {isa = PBXBuildFile; fileRef = 5BD0D19327940E9D0008F48E /* Fart.aif */; };
|
||||||
5BD0D19A27943D390008F48E /* clsSFX.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BD0D19927943D390008F48E /* clsSFX.swift */; };
|
5BD0D19A27943D390008F48E /* clsSFX.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BD0D19927943D390008F48E /* clsSFX.swift */; };
|
||||||
5BD0D19F279454F60008F48E /* Beep.aif in Resources */ = {isa = PBXBuildFile; fileRef = 5BD0D19E279454F60008F48E /* Beep.aif */; };
|
5BD0D19F279454F60008F48E /* Beep.aif in Resources */ = {isa = PBXBuildFile; fileRef = 5BD0D19E279454F60008F48E /* Beep.aif */; };
|
||||||
|
@ -129,7 +131,6 @@
|
||||||
5BA923AC2791B7C20001323A /* vChewingInstaller-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "vChewingInstaller-Bridging-Header.h"; sourceTree = "<group>"; };
|
5BA923AC2791B7C20001323A /* vChewingInstaller-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "vChewingInstaller-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||||
5BC2D2842793B434002C0BEC /* KeyValueBlobReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KeyValueBlobReader.h; sourceTree = "<group>"; };
|
5BC2D2842793B434002C0BEC /* KeyValueBlobReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KeyValueBlobReader.h; sourceTree = "<group>"; };
|
||||||
5BC2D2862793B434002C0BEC /* KeyValueBlobReader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = KeyValueBlobReader.cpp; sourceTree = "<group>"; };
|
5BC2D2862793B434002C0BEC /* KeyValueBlobReader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = KeyValueBlobReader.cpp; sourceTree = "<group>"; };
|
||||||
5BC2D28A2793B8FB002C0BEC /* EmacsKeyHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmacsKeyHelper.swift; sourceTree = "<group>"; };
|
|
||||||
5BC2D28C2793B98F002C0BEC /* PreferencesModule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesModule.swift; sourceTree = "<group>"; };
|
5BC2D28C2793B98F002C0BEC /* PreferencesModule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesModule.swift; sourceTree = "<group>"; };
|
||||||
5BC3EE18278FC48C00F5E44C /* VerticalCandidateController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VerticalCandidateController.swift; sourceTree = "<group>"; };
|
5BC3EE18278FC48C00F5E44C /* VerticalCandidateController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VerticalCandidateController.swift; sourceTree = "<group>"; };
|
||||||
5BC3EE19278FC48C00F5E44C /* VTCandidateController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VTCandidateController.swift; sourceTree = "<group>"; };
|
5BC3EE19278FC48C00F5E44C /* VTCandidateController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VTCandidateController.swift; sourceTree = "<group>"; };
|
||||||
|
@ -144,6 +145,10 @@
|
||||||
5BC4BC5B2796E6A90023BBD5 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = Source/ja.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
5BC4BC5B2796E6A90023BBD5 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = Source/ja.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||||
5BC4BC5C2796E6A90023BBD5 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = Source/ja.lproj/Localizable.strings; sourceTree = "<group>"; };
|
5BC4BC5C2796E6A90023BBD5 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = Source/ja.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||||
5BC4BC5E2796F5C40023BBD5 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = Source/en.lproj/preferences.strings; sourceTree = "<group>"; };
|
5BC4BC5E2796F5C40023BBD5 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = Source/en.lproj/preferences.strings; sourceTree = "<group>"; };
|
||||||
|
5BC772A927A5A1E800CA8391 /* InputState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputState.swift; sourceTree = "<group>"; };
|
||||||
|
5BC772AB27A5A31200CA8391 /* KeyHandlerInput.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyHandlerInput.swift; sourceTree = "<group>"; };
|
||||||
|
5BC772AD27A5A31B00CA8391 /* KeyHandler.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = KeyHandler.mm; sourceTree = "<group>"; };
|
||||||
|
5BC772AE27A5A31B00CA8391 /* KeyHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KeyHandler.h; sourceTree = "<group>"; };
|
||||||
5BD0D19327940E9D0008F48E /* Fart.aif */ = {isa = PBXFileReference; lastKnownFileType = file; path = Fart.aif; sourceTree = "<group>"; };
|
5BD0D19327940E9D0008F48E /* Fart.aif */ = {isa = PBXFileReference; lastKnownFileType = file; path = Fart.aif; sourceTree = "<group>"; };
|
||||||
5BD0D19927943D390008F48E /* clsSFX.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = clsSFX.swift; sourceTree = "<group>"; };
|
5BD0D19927943D390008F48E /* clsSFX.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = clsSFX.swift; sourceTree = "<group>"; };
|
||||||
5BD0D19E279454F60008F48E /* Beep.aif */ = {isa = PBXFileReference; lastKnownFileType = file; path = Beep.aif; sourceTree = "<group>"; };
|
5BD0D19E279454F60008F48E /* Beep.aif */ = {isa = PBXFileReference; lastKnownFileType = file; path = Beep.aif; sourceTree = "<group>"; };
|
||||||
|
@ -271,21 +276,17 @@
|
||||||
path = LanguageModel;
|
path = LanguageModel;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
5BC2D2832793B434002C0BEC /* vChewing */ = {
|
5BC2D2832793B434002C0BEC /* ControllerModules */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
5BC772AE27A5A31B00CA8391 /* KeyHandler.h */,
|
||||||
|
5BC772AD27A5A31B00CA8391 /* KeyHandler.mm */,
|
||||||
|
5BC772AB27A5A31200CA8391 /* KeyHandlerInput.swift */,
|
||||||
5BC2D2842793B434002C0BEC /* KeyValueBlobReader.h */,
|
5BC2D2842793B434002C0BEC /* KeyValueBlobReader.h */,
|
||||||
5BC2D2862793B434002C0BEC /* KeyValueBlobReader.cpp */,
|
5BC2D2862793B434002C0BEC /* KeyValueBlobReader.cpp */,
|
||||||
|
5BC772A927A5A1E800CA8391 /* InputState.swift */,
|
||||||
);
|
);
|
||||||
path = vChewing;
|
path = ControllerModules;
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
5BC2D2892793B8DB002C0BEC /* Keyboard */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
5BC2D28A2793B8FB002C0BEC /* EmacsKeyHelper.swift */,
|
|
||||||
);
|
|
||||||
path = Keyboard;
|
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
5BD0D19827943D270008F48E /* SFX */ = {
|
5BD0D19827943D270008F48E /* SFX */ = {
|
||||||
|
@ -452,8 +453,7 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
5BD0D19827943D270008F48E /* SFX */,
|
5BD0D19827943D270008F48E /* SFX */,
|
||||||
5BC2D2892793B8DB002C0BEC /* Keyboard */,
|
5BC2D2832793B434002C0BEC /* ControllerModules */,
|
||||||
5BC2D2832793B434002C0BEC /* vChewing */,
|
|
||||||
5BA8DAFE27928120009C9FFF /* LanguageModel */,
|
5BA8DAFE27928120009C9FFF /* LanguageModel */,
|
||||||
6A0D4F1315FC0EB100ABF4B3 /* Gramambular */,
|
6A0D4F1315FC0EB100ABF4B3 /* Gramambular */,
|
||||||
);
|
);
|
||||||
|
@ -711,7 +711,7 @@
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
5BDF2CFE2791BE4400838ADB /* InputSourceHelper.swift in Sources */,
|
5BDF2CFE2791BE4400838ADB /* InputSourceHelper.swift in Sources */,
|
||||||
5BC2D28B2793B8FB002C0BEC /* EmacsKeyHelper.swift in Sources */,
|
5BC772AC27A5A31200CA8391 /* KeyHandlerInput.swift in Sources */,
|
||||||
5BDD25F5279D6CFE00AA18F8 /* AWFileHash.m in Sources */,
|
5BDD25F5279D6CFE00AA18F8 /* AWFileHash.m in Sources */,
|
||||||
5BDD25F8279D6D1200AA18F8 /* zip.m in Sources */,
|
5BDD25F8279D6D1200AA18F8 /* zip.m in Sources */,
|
||||||
5BD0D19A27943D390008F48E /* clsSFX.swift in Sources */,
|
5BD0D19A27943D390008F48E /* clsSFX.swift in Sources */,
|
||||||
|
@ -727,6 +727,7 @@
|
||||||
5BE798A42792E58A00337FF9 /* TooltipController.swift in Sources */,
|
5BE798A42792E58A00337FF9 /* TooltipController.swift in Sources */,
|
||||||
5BDD25F6279D6D0200AA18F8 /* SSZipArchive.m in Sources */,
|
5BDD25F6279D6D0200AA18F8 /* SSZipArchive.m in Sources */,
|
||||||
5BDF2D062791DFF200838ADB /* AppDelegate.swift in Sources */,
|
5BDF2D062791DFF200838ADB /* AppDelegate.swift in Sources */,
|
||||||
|
5BC772B027A5B3AB00CA8391 /* KeyHandler.mm in Sources */,
|
||||||
5BC3EE1B278FC48C00F5E44C /* VerticalCandidateController.swift in Sources */,
|
5BC3EE1B278FC48C00F5E44C /* VerticalCandidateController.swift in Sources */,
|
||||||
5B42B64027876FDC00BB9B9F /* UserOverrideModel.mm in Sources */,
|
5B42B64027876FDC00BB9B9F /* UserOverrideModel.mm in Sources */,
|
||||||
5BDD25F7279D6D1200AA18F8 /* unzip.m in Sources */,
|
5BDD25F7279D6D1200AA18F8 /* unzip.m in Sources */,
|
||||||
|
@ -743,6 +744,7 @@
|
||||||
5BC3EE1C278FC48C00F5E44C /* VTCandidateController.swift in Sources */,
|
5BC3EE1C278FC48C00F5E44C /* VTCandidateController.swift in Sources */,
|
||||||
5BDF2D032791C71200838ADB /* NonModalAlertWindowController.swift in Sources */,
|
5BDF2D032791C71200838ADB /* NonModalAlertWindowController.swift in Sources */,
|
||||||
5BC3EE1D278FC48C00F5E44C /* HorizontalCandidateController.swift in Sources */,
|
5BC3EE1D278FC48C00F5E44C /* HorizontalCandidateController.swift in Sources */,
|
||||||
|
5BC772AA27A5A1E800CA8391 /* InputState.swift in Sources */,
|
||||||
5BDD25FD279D6D6300AA18F8 /* CNSLM.mm in Sources */,
|
5BDD25FD279D6D6300AA18F8 /* CNSLM.mm in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
|
Loading…
Reference in New Issue